Every web developer has torn their hair out trying to align an icon with some text, or two separate pieces of text with each other, or (god forbid) a whole sequence of text nodes, icons, form elements, etc. Niki has put together a really great article on why this is so tricky, what we can do about it, and how designers/font creators can help make everyone's lives easier.
This is my claim: we, as a civilization, forgot how to center things.
Together, I trust, we can find our way back to putting one rectangle inside another rectangle without messing it up.
On why text-align: middle
never quite seems to do what you want:
text-align: middle
comes closest, but it aligns by x-height, not cap-height, which still looks unbalanced
On how fonts can make themselves more easily align-able:
If you are a font designer, make life easier for everybody by setting your metrics so that
ascender − cap-height = descender
Important! You don’t have to actually extend your ascenders/descenders to these boundaries. As you can see in the picture, my ascender space, for example, is way underutilized. Just make the numbers match.
On how to calculate the right amount of padding to use on any given font:
You can get the required font metrics for your font from opentype.js.org/font-inspector.html (ascender, descender, sCapHeight).
On how to extend that to icons and inline iconography/imagery:
Now that we have that sorted, aligning icons is not that hard too. You set
vertical-align: baseline
and then move them down by(iconHeight - capHeight) / 2