Read more

How to reliably center (block) icons vertically with text

Dominik Schöler
January 31, 2023Software engineer at makandra GmbH

vertical-align is hard. Have you ever wanted to vertically center an icon with text? This usually means "vertically align with capital letters", as visually, a text line goes from baseline up to the capital top. (That's because descenders are far less frequent than ascenders.)

Illustration online protection

Rails Long Term Support

Rails LTS provides security patches for old versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2)

  • Prevents you from data breaches and liability risks
  • Upgrade at your own pace
  • Works with modern Rubies
Read more Show archive.org snapshot

In this card we'll vertically center an icon (or any "blockish" inline element, really) with the capital letters of surrounding text. This works well with our modern approach to SVG icons, or e.g. for custom list icons. Note that it won't work with "text" icons that scale with font-size.

Technical background

  • All text has a "baseline". It is the bottom edge of most letters, like A or a.
  • The browser aligns all inline elements to the baseline of their container (i.e. the baseline of the text of their container).
    • Elements with display: inline have their baseline aligned (to the baseline of their container)
    • Elements with display: inline-block, inline-grid etc. have their bottom edge aligned (to the baseline of their container)
  • vertical-align: middle aligns an element to the middle of a lowercase x. We cannot use it, since we want to align to uppercase letters.

The solution

We'll move the bottom edge of the icon up to the middle of a capital letter, then push it down by half its own height. This will center the icon vertically to uppercase letters – no matter the icon height or the surrounding font size!

  1. Find the Capital Height of the font you're using, e.g. with fontforge Show archive.org snapshot : open a font file > Menu "Element" > Font Info > OS/2 > Metrics > Capital Height. Store it as a decimal, i.e. for a capital height of 675 and an em-square of 1000:
    :root {
      --font-capital-height: 0.675;
    }
    
  2. Now you simply calculate the vertical middle of the icon, and the vertical middle of surrounding capital letters. Note that this relies on inheriting the em, so the icon must not have a font size set.
    .icon {
      /* Do not set a font-size here! */
      height: var(--icon-height);
      --icon-v-middle: calc(var(--icon-height)/2);
      --capital-v-middle: calc(var(--font-capital-height)/2 * 1em);
      vertical-align: calc(var(--capital-v-middle) - var(--icon-v-middle));
    }
    

Try in this jsfiddle! Show archive.org snapshot

Posted by Dominik Schöler to makandra dev (2023-01-31 08:47)