Stefan Judis has a “Today I Learned” (TIL) post explaining how SVGs filters can be inlined in CSS. The idea is that CSS has the filter
property which supports some built-in functions, like grayscale(100%)
and stuff like that.
But it can also point to a filter defined by SVG. So you could do filter: url(#my-custom-filter)
which is in some inline <svg>
as <filter id="my-custom-filter">
. It’s kinda funny to have to refer out to the HTML like that. A filter is such a visual thing that it makes sense to bring it into the CSS. That looks like this:
img {
filter: url('data:image/svg+xml,\
<svg xmlns="http://www.w3.org/2000/svg">\
<filter id="waves" x="-20%" y="-20%" width="140%" height="140%" filterUnits="objectBoundingBox" primitiveUnits="userSpaceOnUse" color-interpolation-filters="linearRGB">\
<feTurbulence type="turbulence" baseFrequency="0.01 0.01" numOctaves="1" seed="1" stitchTiles="noStitch" result="turbulence" />\
<feDisplacementMap in="SourceGraphic" in2="turbulence" scale="20" xChannelSelector="G" yChannelSelector="A" result="displacementMap" />\
</filter>\
</svg>#waves')
;
}
That’s Stefan’s turbulence filter example, something CSS alone definitely cannot do.
Look at all those backslashes (\
). Makes ya wish CSS had template literals, eh? Makes me nervous that a code formatter or minifier would choke on that, but I don’t actually know, maybe it would be fine.
What’s nice is that the SVG remains fairly intact (readable and editable). So here you can edit the SVG filter in the CSS and have a play:
I also think of Yoksel’s tools. This editor for two-tone and three-tone images is so cool. I can pick up one of those filters and drop it into some CSS as well:
Filters aren’t the only kind of SVG that makes some sense to inline into CSS though. You can put SVG drawing right into CSS as well.
This works everywhere but Safari in a quick blast through modern browsers. But I think in the not-so-distant past, we needed to encode more of the special characters in the SVG to get it to work (although you didn’t have to resort to base64). Yoskel’s URL-encoder is literally just for this — I just don’t know that it’s necessary anymore.
I recently used this when I needed to place one icon and custom CSS was the fastest/easiest solution. I was disappointed to learn that I could not change the color of the svg vector with CSS and had to insert the svg again with a different fill value for the hover state.
You may want to try the
currentcolor
keyword. I don’t know whether it’ll work here but it works very well for a variety of dynamic color use cases, including styling external definitions referenced by ause
tag.It works via
mask-image
!So you’d do:
In theory this is a black square, but due to
mask-image
only the shape of your SVG icon will be visible (like a stamp), and you can update thebackground-color
as you like!mask-image
supports all the same stuff thatbackground
does, so you’ll also want to play around with keywords likecontain
andno-repeat
.Thanks for pointing this out! I was just looking for a way to replace a gif loader animation with SVG, this let me do just that.
Playing around in code pen, I found that I did need to encode to get it to work in Chrome 88.
I discovered a helper for testing different types of color bliness, that makes use of this, years ago.
https://github.com/hail2u/color-blindness-emulation
Backslashes? Just put data in a var!
I’m not sure that helps with the line breaks? Does it? (The line breaks being kinda useful for readability and editability.)
Yet another case where CSS-in-JS shines