Snippets

Align SVG Icons to Text and Say Goodbye to Font Icons

In building my own SVG-based icon system, I’ve run into (and mostly solved) these same issues.

Why should I care about how SVGs are styled?

If you’ve ever used font icon systems like Font Awesome you know how easy it is to add to a project and get going. The icons align to your text easily and can be modified by changing the font-size of the element. There is no clearly defined way for styling an SVG icon system. I’ve seen some systems custom style and place each icon in their library. This route sounds painfully unsustainable if you utilize more than 15 icons in your UI.

Can it scale like an icon font?

To emulate the font-size scaling I use a class to set the SVG size to 1em by 1em. This means that if your title text is a 48px font size the SVG will be 48px by 48px. This works nicely for components like buttons and inputs when you want to add an icon. This also empowers you to pass a font size to the element via modifier class or inlined CSS. Using font-size to determine the size of your icon makes your life a little easier.

Code language: CSS

.svg-icon svg {
  height: 1em;
  width: 1em;
}

My SVG won’t align to with my text. How do I fix this?

The downside is that a DOM element on it’s own doesn’t align nicely with text. To counter this I wrote the .svg-icon handler class to hold the size and be relative positioned so that I can absolute position the SVG inside of it. Moving the icon down by “-0.125em” allows me to pull down the icon by 12.5% at any scale.

The first example shows that DOM elements align to the baseline of text by default. However, since our icon is already properly scaled to consider the baseline, we need to pull it down for the baseline to truly align. At this size the distance is 6px away, 6px/48px = ⅛ or 12.5%. In the second example, pulling the icon down by -0.125em places the icon onto the proper baseline of the text.

Code language: CSS

.svg-icon {
  display: inline-flex;
  align-self: center;
  position: relative;
  height: 1em;
  width: 1em;
}
 
.svg-icon svg {
  height:1em;
  width:1em;
}
 
.svg-icon.svg-baseline svg {
  bottom: -0.125em;
  position: absolute;
}

The end of the clearfix hack?

A new value of the display property has landed in Chrome Canary and Firefox Nightlies. In the Editor’s Draft of the CSS Display Module Level 3, display: flow-root is defined as:

“The element generates a block container box, and lays out its contents using flow layout. It always establishes a new block formatting context for its contents.”

The key use of this comes when you have a box with a floated element inside it, and the floated element is taller than the other content inside the box. Default behaviour is that the box will not clear the float, and anything that comes afterwards will also wrap the floated item.

A screenshot of an element floated beside some text, with the containing element only containing the text, with the floated element bleeding through the bottom.
The floated element is out of flow causing the box to collapse.

The typical way we have solved this issue is to use a clearfix hack. The hack inserts some generated content, sets it to display; table or display: block and then clears it. This then ensures that the box becomes self-clearing, in our example the border will display after the floated item, and any following content will not rise up to wrap the float.

Enter display: flow-root

Using display: flow-root on an element will perform this clearing for us. Instead of needing to apply the clearfix hack we can use the CSS display property on the container with a value of flow-root.

Code language: CSS

.container {
  display: flow-root;
}

The border then clears the float and following content displays after our contained floated element.

The container element from the previous screenshot now has display: flow-root; which causes the container to properly contain the float, without the need for the clearfix hack.
After setting display: flow-root; on the container, the float no longer escapes the flow.

[…]

There is some discussion about the name of the value on an issue posted to the CSS Working Group GitHub. If you want to see interoperable support for this feature soon, then I’d suggest you pop over to the Edge UserVoice site and give it a vote.