10

Same question as How do I have an SVG image inherit colors from the HTML document?, but specifically when applied to an svg image used as content on a :before pseudo-element.

(Desired behavior is that both checkmarks inherit the red color from the body. Currently only the inline SVG does.)

<style type='text/css'>
    body {
        color: red;
    }

    .checkmark {
        height: 2em;
        width: 2em;
    }

    .checkmark:before {
        content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100%' height='100%' viewBox='-0.5 0 20 15'><rect fill='currentColor' stroke='none' transform='rotate(45 4.0033 8.87436)' height='5' width='6.32304' y='6.37436' x='0.84178'></rect><rect fill='currentColor' stroke='none' transform='rotate(45 11.1776 7.7066)' width='5' height='16.79756' y='-0.69218' x='8.67764'></rect></svg>");
    }
</style>

<!-- Renders red -->
<svg xmlns='http://www.w3.org/2000/svg' width='2em' height='2em' viewBox='-0.5 0 20 15'><rect fill='currentColor' stroke='none' transform='rotate(45 4.0033 8.87436)' height='5' width='6.32304' y='6.37436' x='0.84178'></rect><rect fill='currentColor' stroke='none' transform='rotate(45 11.1776 7.7066)' width='5' height='16.79756' y='-0.69218' x='8.67764'></rect></svg>

<!-- Renders #000 -->
<div class="checkmark"></div>

jsFiddle Demo

Community
  • 1
  • 1
Adam
  • 1,744
  • 1
  • 14
  • 34

2 Answers2

11

content: url(...) makes the url part into an image, in other words the svg becomes its own separate document. Styles don't apply across documents, so it's not possible to get color to affect the svg in this scenario.

When the svg is inline it is OTOH part of the document, so styles can be applied to it.

You could make (or dynamically generate) multiple versions of the checkmark svg and tune the stylerules such that the appropriate "pre-colored" one is selected.

Erik Dahlström
  • 59,452
  • 12
  • 120
  • 139
  • Yeah, I was hoping that wouldn't be the case, but it makes sense. (And yeah, that's [basically what I'm doing](https://gist.github.com/adamschwartz/7923018) at the moment.) – Adam Dec 12 '13 at 04:03
9

For certain usecases where the icon is all the same color, you can get away with using a css filter on the element instead of changing it's color.

E.g. don't use currentColor in your SVG url, but instead use a base color e.g. red Then instead of changing the color on the containing element (your containing element is <body> for illustration purposes, but I'm thinking of an <a href="#" class="checkmark"> here), add a filter to the element:

.checkmark {
    color: red;  /* matches fill in the SVG */
}

.checkmark::before {
    content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100%' height='100%' viewBox='-0.5 0 20 15'><rect fill='red' stroke='none' transform='rotate(45 4.0033 8.87436)' height='5' width='6.32304' y='6.37436' x='0.84178'></rect><rect fill='red' stroke='none' transform='rotate(45 11.1776 7.7066)' width='5' height='16.79756' y='-0.69218' x='8.67764'></rect></svg>");
}

.checkmark::before:hover {
    filter: hue-rotate(120deg);  /* changes both text and tick from red to green */
}

You'll have to play around with the filter to get the right color transformation, e.g. you can also change brightness or make it grayscale: https://css-tricks.com/almanac/properties/f/filter/

EoghanM
  • 25,161
  • 23
  • 90
  • 123