Using ligatures as icons on a website



You can look at font icons here: Font icon ligatures

Intro

There are two reasons why I got interested in reasearching about this topic. First of a lot of google products loads garbage when you are not using super fast internet speeds. The main most noticeble one used to gmail but it looks like they fixed it now.

Analytics icons font not loaded

But even though it was annoying it didn’t spark enough enterest to go and dig deeper to understand reasons behind it. The main reason was me misclicking on an icon and selecting just a portion of it. It looked like this:

Reasons

The ‘information’ icon from the above video is added to the page like this:

<i class="google-material-icons VCmZ8 kdYqFe" aria-hidden="true">info_filled</i>

At the beginning I thought that ‘info_filled’ text inside the tag is used as a ‘helper’ text to show information when images are not loaded but examining css classes attached to the tag didn’t reveal any background image being applied to this tag.

In reality they used ligatures for icon rendering with ‘Material Icons Extended’. I knew about icon fonts but using ligatures for that never crossed my mind.

If you don’t know, using ligatures is a technique to render a ‘unified’ symbol when certain combination of letters/codepoints go one after another (not exactly but good enough here). For example when when two equal signs, ==, are placed next to each other only one long equal sign rendered instead of two short ones.

In the example from the video letter combinatio for ‘info_filled’ is combined into single icon. The reason why I could select that icon is related to how browser does it selection. In this example chromium renders one icon but behind the scenes it sees them as a collection of letters. You can select middle part and paste it into a text editor and see exact letters.

Libreoffice

If we try the same trick in libreoffice (or probably microsoft office) it has the same properties. In the video below I use the same font to render text. The video show similar behaviour of rendering one symbol but during selection it select just parts of it.

Inkscape

Inkscape does similar for rendering but selection works on the whole icon.

In both examples you can see how it works when with icons that are part of a bigger combination. For example when I type ‘facebook’ with the material font I first get a ‘face’ icon and then it converts ‘facebook’ icon.

About the font ‘Material Icons’ font.

I downloaded a version of ‘Material Icons’ in woff2 format as in that website. It weighs 227.2 KiB and contains 3000+ icons in it. This give around 60 bytes per icon which sound pretty good when you consider throughput.

There is a list of strings that could be used on the google material page but I wanted to have a look into it myself. For this I used python with ‘fonttool’ package. Then I with this tiny script I got all multiletter used for for ligatures:

from fontTools.ttLib import TTFont
font = TTFont('google.woff2')
for k,v in font.getBestCmap().items():
    print(v)

This will give back a list of ‘words’ that could be used in the as icons. There single letter icons too (for example ‘g’) but I ignored those. Here is a list of some of those combinations.

error
error_outline
warning
add_alert
notification_important
qr_code_2
flutter_dash
align_vertical_top
align_horizontal_left
bnagent
align_horizontal_center
align_horizontal_right
align_vertical_center
kormo
...
...
...
gke_protect
18_up_rating
no_adult_content
wallet

Is this approach good?

I understand the reasoning behind using this technique. They wanted to use an upgraded version of forgotten technique of ‘css sprites’. It should be better as it is in vector format and only one version is good enough for any kind of screen size but in practice it is horrible. Especially for a website it takes some time to load those 200+ Kb of data just to start rendering icons. It is especially bad when you use just 10 icons on a page but wait to load 3000.

It looks like even google understood its mistake as if you go to Gmail it no longer uses this font. Now the switched bad to ‘inneficient’ png icon one by one loading and it worked.

Extra

To my surprise the icon that drove my attention was unique on ‘search console’ page. So that 200+ Kb font file is used just to draw 1 (sic!) icon(there might be more but I found only one). Then how are the other are drawn? Here is how the drawing is split:

Four ways to draw icons

There are 2 different icon fonts, inline svg icons and a bit of CSS tricks. This is one icon that uses CSS border trick to make a bottom triangle icon. ‘Google Material Icons’ we have looked at in this article. The last is ‘Material Icons Extended’. It is different in that if you look at the source code it does not have word combinations as ligatures but and what looked like an empty space. When I looked in the developer console it was just span with a white space. After copying it to vscode it also was a white space. So I copied it to vim to get its extract it whitespace code and got this:

Vim code

So for some of the icons instead of ligatures they used unicode chars which loaded specific icons from the second font file. In the picture above they were drawn as square boxes because I blocked that font file and my system didn’t have appropriate font to draw them (but font in vim still knew how to draw them).

It is google and they probably know what they are doing but I am glad I don’t have to deal with this variaty in my projects.

Conclusion

So I finally spent some time to look into the font drawing issue and found the reasons behind huge ugly text on many of googles products. The reason behind it was usage of ligatures and text descriptions for the icons. It looks like that this approach is an overkill and actually worsen the user experience. And in some critical projects google fixed this by removing this ‘icon drawing with font’ approach (gmaail now only pull png icons).

This approach could be a good solution in mobile or desktop apps as you can bake that font into the app itself but for websites it is debatable.

You can look at font icons here: Font icon ligatures