6

Trouble is that I can't set value (color) in fill property in Chrome, but in Firefox it works. I tried a lot ways to do it, but there is no result. The only way I see to change color of SVG icon is via jQuery (or JavaScript) by changing id of <symbol>, which is below. Please help me solve this problem!

This is what I need to work in Chrome:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        span:hover .pathCrossBtn{
            fill: blue;
        }
    </style>
</head>
<body>
    <svg width="0" height="0" style='display: none;' xmlns="http://www.w3.org/2000/svg">
    <symbol viewBox="0 0 2048 2048" id="crossBtn">
        <path class="pathCrossBtn" fill="red" d="M1618 1450q0 40-28 68l-136     136q-28 28-68 28t-68-28l-294-294-294 294q-28 28-68 28t-68-28l-136-136q-28-28-28-68t28-68l294-294-294-294q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 294 294-294q28-28 68-28t68 28l136 136q28 28 28 68t-28 68l-294 294 294 294q28 28 28 68z"/>
    </symbol>
</svg>
<span>
    <svg class="crossBtn" viewBox="0 0 2048 2048" width="30" height="30">
        <use xlink:href="#crossBtn"></use>
    </svg>
</span>
</body>
</html>

This is bad way to solve my problem which is not approriate for me.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
</head>
<body>
    <svg width="0" height="0" style='display: none;' xmlns="http://www.w3.org/2000/svg">
        <symbol viewBox="0 0 2048 2048" id="crossBtnBlue">
          <path class="pathCrossBtn" fill="blue" d="M1618 1450q0 40-28 68l-136 136q-28 28-68 28t-68-28l-294-294-294 294q-28 28-68 28t-68-28l-136-136q-28-28-28-68t28-68l294-294-294-294q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 294 294-294q28-28 68-28t68 28l136 136q28 28 28 68t-28 68l-294 294 294 294q28 28 28 68z"/>
        </symbol>
        <symbol viewBox="0 0 2048 2048" id="crossBtnRed">
           <path class="pathCrossBtn" fill="red" d="M1618 1450q0 40-28 68l-136 136q-28 28-68 28t-68-28l-294-294-294 294q-28 28-68 28t-68-28l-136-136q-28-28-28-68t28-68l294-294-294-294q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 294 294-294q28-28 68-28t68 28l136 136q28 28 28 68t-28 68l-294 294 294 294q28 28 28 68z"/>
        </symbol>
</svg>
<span>
    <svg class="crossBtn" viewBox="0 0 2048 2048" width="30" height="30">
        <use xlink:href="#crossBtnRed"></use>
    </svg>
</span>
<script>
;(function(){
    $('.crossBtn')
        .mouseover(function(){
            $('span svg use').attr('xlink:href','#crossBtnBlue');
        })
        .mouseleave(function(){
            $('span svg use').attr('xlink:href','#crossBtnRed');
        })
}());
</script>
</body>
</html>
Mr Lister
  • 45,515
  • 15
  • 108
  • 150
Hombre Honrado
  • 65
  • 1
  • 2
  • 5
  • @RobertLongson want to make sure I understand: are you saying it's a bug in an svg referenced with `use` because that embedded svg is in the shadow dom? – henry Aug 09 '17 at 16:45
  • @henry Firefox has fixed its implementation to match the SVG 2 spec. Try a nightly and see. I imagine Chrome will align with the SVG 2 spec if it hasn't already. – Robert Longson Aug 09 '17 at 19:22
  • @RobertLongson but I'm still not clear exactly what the "this" in "this is a known bug" is. I've tried looking for a bug ticket but no luck so far. – henry Aug 10 '17 at 18:12
  • @henry https://bugzilla.mozilla.org/show_bug.cgi?id=265894 – Robert Longson Aug 10 '17 at 19:44

2 Answers2

12

Use currentcolor in the path fill attribute of the <symbol> element.

The currentcolor keyword represents the value of an element's color property. This lets you use the color value on properties that do not receive it by default.

Then, add a color CSS property to the class of the <svg> container that will wrap the <symbol> instantiated by the <use> element.

.icon {
  width: 30px;
  height: 30px;
}

.icon--blue {
  color: blue;
}

.icon--red {
  color: red;
}
<svg width="0" height="0" style="display: none;" xmlns="http://www.w3.org/2000/svg">
  <symbol viewBox="0 0 2048 2048" id="crossBtn">
    <path class="pathCrossBtn" fill="currentcolor" d="M1618 1450q0 40-28 68l-136     136q-28 28-68 28t-68-28l-294-294-294 294q-28 28-68 28t-68-28l-136-136q-28-28-28-68t28-68l294-294-294-294q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 294 294-294q28-28 68-28t68 28l136 136q28 28 28 68t-28 68l-294 294 294 294q28 28 28 68z"
    />
  </symbol>
</svg>

<svg class="icon icon--red" viewBox="0 0 2048 2048">
  <use xlink:href="#crossBtn"></use>
</svg>
<svg class="icon icon--blue" viewBox="0 0 2048 2048">
  <use xlink:href="#crossBtn"></use>
</svg>
Ricky Ruiz
  • 25,455
  • 6
  • 44
  • 53
0

Not exactly a generic solution to the problem mentioned above, but I came here for a similar problem, where fill="none" on an svg node doesn't seem to work under all circumstances in both Chrome and Firefox, and potentially other browsers. This piece of SCSS fixes it for us, in our case for feather icons rendered via react-svgr:

svg:global(.feather) {
    // Fix for `fill="none"` not working properly in (at least) Chrome and Firefox
    // Part 1: If there is a `fill` property, reset `fill-opacity`.
    //         This is for children of elements with `fill="none"`
    &[fill], *[fill] {
        fill-opacity: initial;
    }
    // Part 2: If the element uses `fill="none"`, set `fill-opacity` to 0.
    &[fill='none'], *[fill='none'] {
        fill-opacity: 0;
    }

}

The equivalent CSS, for the generic case:

svg[fill], svg *[fill] {
    fill-opacity: initial;
}
svg[fill='none'], svg *[fill='none'] {
    fill-opacity: 0;
}

Note that this may not cover all cases of SVG elements with fill properties and children with differently valued properties, so adapt to your needs.

Bart
  • 2,062
  • 15
  • 19