There are two bugs here, one in Blink (Chrome and Chromium based browsers) and one in webkit, both caused by the transitioning of the background-image property.
Here is a minimal repro of these bugs:
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 34 26">
<path d="M0,0h34v4H0V0z M0,22h34v3.9H0V22z M0,11h34v4H0V11z" fill="black"/>
</svg>`;
const url = 'url(data:image/svg+xml,' + encodeURIComponent( svg ) + ')';
const urls = [ url, url.replace( 'black', 'red' ) ];
let i = 0;
setInterval(() =>
document.querySelector( '.burger' ).style.backgroundImage = urls[ (++i % 2) ],
500
);
.burger {
height: 30px;
width: 100px;
background-position: center;
background-repeat: no-repeat;
transition: background-image .2s linear;
}
<div class="burger">
</div>
Chrome's bug is due to the fact your svg files don't have their own width and height attributes, setting one will fix it there.
Safari bug is caused by the retina scaling, on which they weirdly apply the transition too... For this one a fix would be harder, but setting the correct height will make it less visible since we'd only have antialiasing artifacts to move.
Here is the same snippet as above, with just the height
and width
attributes set:
const svg = `<svg width="34" height="26" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 34 26">
<path d="M0,0h34v4H0V0z M0,22h34v3.9H0V22z M0,11h34v4H0V11z" fill="black"/>
</svg>`;
const url = 'url(data:image/svg+xml,' + encodeURIComponent( svg ) + ')';
const urls = [ url, url.replace( 'black', 'red' ) ];
let i = 0;
setInterval(() =>
document.querySelector( '.burger' ).style.backgroundImage = urls[ (++i % 2) ],
500
);
.burger {
height: 30px;
width: 100px;
background-position: center;
background-repeat: no-repeat;
transition: background-image .2s linear;
}
<div class="burger">
</div>
Now, there should probably be a note that if targeting only quite recent browsers is not an issue for you, you could achieve the same effect by using only CSS filters, saving one network request:
const svg = `<svg width="34" height="26" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 34 26">
<path d="M0,0h34v4H0V0z M0,22h34v3.9H0V22z M0,11h34v4H0V11z"/>
</svg>`;
// This time we generate only a single black url
const url = 'url(data:image/svg+xml,' + encodeURIComponent( svg ) + ')';
document.querySelector( '.burger' ).style.backgroundImage = url;
.burger {
height: 30px;
width: 100px;
background-position: center;
background-repeat: no-repeat;
transition: filter .2s linear;
}
.burger:hover {
/*
Using formula from
https://stackoverflow.com/a/43959856/3702797
to safely fallback on black for browsers withtou support for filters
*/
filter: invert(10%) sepia(100%) saturate(10000%) ;
}
hover the icon to change its color.
<div class="burger">
</div>