Dynamic SVG fill color using Compass

Both background-colors — text-box and eye-catcher — should match and require no effort if the color changes (thanks TheStocks for the image)

Recently I’ve added eye-catcher graphics to connect images and text-boxes. Both elements use a solid background and I wanted to make sure these two colors always match — if I need to change the text background-color, the eye-catcher should magically adjust. SASS/Compass and SVG made my wish come true.

As SVG outputs text it’s simple to make dynamic changes, actually the solution only requires two steps:

  • Embed SVG as data URI
  • Adjust the path’s fill attribute using a variable

Sounds pretty easy, but we need to fight some nasty quirks, because IE is difficult with encodings (URL encoding worked fine for me, more on that later).

Side note for the sake of completeness: Right after I’ve started I had problems with double quotes and switched to single quotes.

The pasted SVG code in this example is really long, so I am not pasting the source code. Just download the example, all steps are briefly listed in the SASS-file.

Step 1: Make it work in Chrome and Safari

The first step creates a variable that holds the SVG string and adjusts the text background- and SVG fill-color using one variable (note, that you need to interpolate the variable in order to evaluate it):

$background-color: #b0aca7;
$svg-string: "<svg ...><path fill='#{$bg-color}' ... /></svg>";

The example will now work in Chrome and Safari, but not in Firefox.

Step 2: Adjust for Firefox

Firefox doesn’t like the #-symbol. We can easily solve that problem by replacing the HEX color-format with RGB color-format. SASS’ red, green and blue functions come in handy to build a custom RGB-string:

$background-color-rgb-string: "rgb(" + 
red($background-color) + ", " +
green($background-color) + ", " +
blue($background-color) +
")";

To be honest, this step is off-topic because IE requires encoding the SVG string anyway.

Step 3: Internet Explorer, here we go!

As usually Internet Explorer needs a bit more elbow-grease. It seems to be difficult with encoding and even in IE 11, I couldn’t manage to display SVGs without additional encoding. I’ve worked with Base64-encoding in the past and it was always fine. Nonetheless, it adds overhead that is not necessary, so this time I used URL encoding and it worked just as well.

Facing our scenario, we need to encode our string dynamically as we define the fill-color using a variable. Therefore we need to write a custom Ruby-function and include it using require in the config.rb (code shows URL encoding but Base64 comes with the example download as well):

require 'sass'
require 'cgi'
module Sass::Script::Functions
def custom_url_encode(string)
assert_type string, :String
encoded_svg = CGI::escape(string.value).gsub('+', '%20')
Sass::Script::String.new(encoded_svg)
end
declare :url_encode_svg, :args => [:string]
end

Example & Further readings

Show your support

Clapping shows how much you appreciated Frau Doudou’s story.