Read more

A modern approach to SVG icons

Tobias Kraze
December 01, 2022Software engineer at makandra GmbH

You have some SVG files you want to use as icons on your website. How would you embed them?

Illustration online protection

Rails professionals since 2007

Our laser focus on a single technology has made us a leader in this space. Need help?

  • We build a solid first version of your product
  • We train your development team
  • We rescue your project in trouble
Read more Show archive.org snapshot

Common options are:

  1. Use them with an image: <img src='path-to-icon.svg'>
  2. Embed them inline with <svg>$ICON</svg>
  3. Embed them using CSS and background-image: url(path-to-icon.svg) or even background-image: url(data:$ICON).
  4. Build your own icon font.

All of these have drawbacks:

  • Image and background-image do not allow to recolor the image using CSS.
  • Inline-<svg> are unnecessary work for the server and are not cached.
  • Icon-fonts require complicated setup and are unnecessarily large. In times of http 2+, having fewer request no longer matters.
  • Most solutions do not scale the icon with the font size.

One option that seems to work better is to use the mask CSS feature. The idea is to have an element with a background color in the desired icon color and then use the SVG to mask it, giving it the correct shape. Using SASS, you can write something like this:

// unfortunately, we manually have to list all our icons
$icons: check-mark, loading-indicator, back-arrow

.custom-icon
  --size: 1em
  
  display: inline-block
  width: var(--size)
  height: var(--size)
  background-color: currentcolor
  mask: var(--icon-url) center / contain no-repeat
  
  // only if you do not have auto-prefixer:
  -webkit-mask: var(--icon-url) center / contain no-repeat
  
  // this can probably be done in a better way:
  vertical-align: text-bottom
  margin-bottom: -.1em // depends on the icons
  
  @each $icon in $icons
    &.-#{$icon}
      --icon-url: url(../../images/custom_icons/#{$icon}.svg)

Use it with

<span class="custom-icon -check-mark"></span>

The icon will use the font-size and color of the surrounding block. It works in all relevant browser.

Posted by Tobias Kraze to makandra dev (2022-12-01 10:50)