SVG within CSS

Avatar of Chris Coyier
Chris Coyier on

📣 Freelancers, Developers, and Part-Time Agency Owners: Kickstart Your Own Digital Agency with UACADEMY Launch by UGURUS 📣

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.