Using ligatures as icons on a website
You can look at font icons here: Font icon ligatures
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.
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:
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.
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 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():
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.
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.
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:
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:
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.
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