skip to Main Content

Using values="var(--color1);var(--color2)" in an SVG <animate> tag works in Firefox but not Chrome (see the snippet below). Is there a way to make it work in Chrome?

:root {
    --color1: #7F0000;
    --color2: #007F00;
}
<svg width="100" viewBox="-50 -50 100 100">
    <circle cx="0" cy="0" r="25" fill="var(--color1)">
        <animate attributeName="fill" dur="3s" values="var(--color1);var(--color2);var(--color1)" repeatCount="indefinite" />
    </circle>
</svg>

3

Answers


  1. Easiest workaround is a native JavaScript Web Component

    something like:
    getComputedStyle(this).getPropertyValue("--color1") to read CSS values

    customElements.define("svg-circle", class extends HTMLElement {
      connectedCallback() {
        this.style.display = "inline-block";
        let c1 = this.getAttribute("color1") || "lightgoldenrodyellow";
        let c2 = this.getAttribute("color2") || "rebeccapurple";
        this.innerHTML = `<svg width="180" viewBox="-50 -50 100 100">
        <circle r="49">
         <animate attributeName="fill" dur="3s" values="${c1};${c2};${c1}" repeatCount="indefinite"/>
        </circle></svg>`;
      }
    });
    <svg-circle></svg-circle>
    <svg-circle color1="gold"></svg-circle>
    <svg-circle color1="red" color2="green"></svg-circle>
    Login or Signup to reply.
  2. You could replace the SMIL animation with an animation done with Web Animations API.

    const circle01 = document.getElementById('circle');
    
    var circleKeyframes = new KeyframeEffect(
      circle01, [{
          fill: 'var(--color1)'
        },
        {
          fill: 'var(--color2)'
        }
      ], {
        duration: 3000,
        iterations: Infinity
      }
    );
    
    var a1 = new Animation(circleKeyframes, document.timeline);
    a1.play();
    :root {
      --color1: #7F0000;
      --color2: #007F00;
    }
    
    circle {
      fill: var(--color1);
    }
    <svg width="100" viewBox="-50 -50 100 100">
      <circle id="circle" cx="0" cy="0" r="25" />
    </svg>
    Login or Signup to reply.
  3. I believe that the easiest way to do this is with pure CSS. I added a "id" attribute to the circle so we can target it with a CSS selector. I then used CSS keyframes and animation to add the color change effect. I also switched the svg fill attribute out for a CSS style fill so we can avoid the weirdness of accessing CSS var() outside of CSS.

    :root {
        --color1:#7F0000;
        --color2:#007F00;
    }
    #aCircle{
        animation:test 3s linear 0s infinite;
    }
    @keyframes test{
        0% {fill:var(--color1);}
        50% {fill:var(--color2);}
        100% {fill:var(--color1);}
    }
    <svg width="100" viewBox="-50 -50 100 100">
        <circle id="aCircle" cx="0" cy="0" r="25" style="fill:var(--color1);"/>
    </svg>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search