SCSS variable in background image with SVG image data URI
Asked Answered
P

4

21

In the following SCSS, I would like to use the fg-color variable within the url background-image attribute.

$fg-color: #ff6464;

i.icon-back {
  background-image: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 20'><path d='M10,0l2,2l-8,8l8,8l-2,2L0,10L10,0z' fill='%23ff6464'/></svg>");
}

At the moment the value, of the variable in simply repeated within the SVG string, like so:

fill='%23ff6464'

I would like this to be automatically updated whenever the fg-color variable is updated.

How can I do this?


UPDATE:

This input SCSS:

i.icon-back {
  background-image: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 20'><path d='M10,0l2,2l-8,8l8,8l-2,2L0,10L10,0z' fill='$fg-color'/></svg>");
}

Outputs this CSS:

i.icon-back {
  background-image: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 20'><path d='M10,0l2,2l-8,8l8,8l-2,2L0,10L10,0z' fill='$fg-color'/></svg>");
}

... it is exactly the same - the variable is not processed.


NOTE:

I have reviewed these questions, that appear to be similar, but are not the same:

Preconceive answered 25/8, 2014 at 1:7 Comment(2)
@cimmanon I'll ignore the snarkiness of your comment. Anyway, yes, I have tried using the variable, and the output that I get doesn't do any substitution at all. I'll update my question to show exactly what I get.Preconceive
@cimmanon I have found a way to do this. It turns out that it was a more complicated than simply "using the variable".Preconceive
P
44

First, create a SASS function. This (ab)uses string interpolation to convert the colour to a string, and then strips the first character (should always be '#'), and puts '%23' in its place (URL encoded form of '#').

@function url-friendly-colour($colour) {
    @return '%23' + str-slice('#{$colour}', 2, -1)
}

Then use the function - but in order for it to work within the string, it must be interpolated, using #{}

i.icon-back {
  background-image: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 20'><path d='M10,0l2,2l-8,8l8,8l-2,2L0,10L10,0z' fill='#{url-friendly-colour($fg-color)}'/></svg>");
}

The caveat with this approach, of course, is that it will not work with colours that are specified by colour name instead of their hexadecimal colour.

E.g. #f00 works but red will not.

Preconceive answered 25/8, 2014 at 3:20 Comment(6)
That's an interesting approach, which browser were you using? For me just using fill="#{$color}" works just fine.Tribromoethanol
@JureTriglav all of them (including IE)Preconceive
Yes, should work with anything above IE 8. Is the url-friendly-colour required for cross-browser support? From my testing it isn't necessary, and simply interpolating a color directly works: fill="#{$color}.Tribromoethanol
Thanx! Worked for me. In Chrome I had it working by using: fill='#{$fg-color'} But Firefox wouldn't accept this. I could use rgb() color definitions, that works too. But I your SASS function better...Jopa
This is years later but I just used @JureTriglav option and it worked easiest.Turrell
I found this site useful for giving you the perfectly encoded URL ready for use: yoksel.github.io/url-encoder - Just copy the SVG code into it and copy out the returned CSS :-)Grasp
V
7

Not an answer to your question, but an alternative way to achieve a similar result in many cases (think simple mono-color icons). You can use CSS mask-image like so:

i.icon-back {
  background-color: $fg-color; 
  mask-image: url('data:image/svg…');
}

Browser support for CSS masks is missing Edge/IE at the time of this writing.

Vexillum answered 15/2, 2018 at 9:1 Comment(0)
C
1

A better solution

// SASS 
$nt-link-color
.circle{
  background: url("data:image/svg+xml;utf8,<svg version='1.1' xmlns='http://www.w3.org/2000/svg' style='fill:#{toRGB($nt-link-color)};' width='24' height='28' viewBox='0 0 24 28'><path d='M24 14c0 6.625-5.375 12-12 12s-12-5.375-12-12 5.375-12 12-12 12 5.375 12 12z'></path></svg>")  no-repeat;
}

// FUNCTION
@function toRGB ($color) {
  @return "rgb(" + red($color) + ", " + green($color) + ", " + blue($color)+ ")";
}
Coat answered 29/8, 2019 at 13:15 Comment(2)
svg doesn't show upInglenook
@Inglenook that's because the # hasn't been encoded. use %23 instead.Gratification
B
1

You can use postcss-inline-svg plugin like this :

in _variable.scss

    $text-primary-100 : #11091a;
    ...

in _header.scss :

    .logo {
        width: 154px;
        height:32px;
        background: svg-load("../assets/logo/logo.svg", fill=$text-primary-100) center no-repeat;
    }

this will become :

.nav {
    background: url("data:image/svg+xml;charset=utf-8,%3Csvg fill='%11091a'%3E%3Cpath d='...'/%3E%3Cpath d='...' fill='%11091a'/%3E%3Cpath d='...'/%3E%3C/svg%3E");
}
Breadthways answered 3/10, 2023 at 21:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.