Favicon is not as simple as you think

Favicon is the little icon that displayed on the title bar or tab bar when you browsing a web site. At very beginning, it is used to be the little icon displayed in favoriate bar when user add the website to favorites. Then later, it becomes the the standard way to specify custom icon for a website.

Most web site provides favico, developer add one line description in the <head>:

1
<link rel="shortcut icon" href="/favico.ico" type="image/x-icon">

This simple piece of code works, but there are a lot of issues with this declaration. Actually specify the favico isn’t as simple as you might expect!

For this piece of code, according to W3C document how to favicon, there are 2 issues with it:

First, shortcut isn’t a standard value for rel, it is only for IE.

Second, ico format is a Microsoft oriented file type, not all platform likes it. Linux, Mac, iOS, Android, do not really appreciate this format.

Beides the 2 issues described above, the size of the favicon also matters.

Someone says it should be 16x16. Yes, 16x16 icon is used in tab or tree view. Some other says it should be 32x32. Well, this is also true. 32x32 icon is displayed in toolbar.

16x16 and 32x32 are the most used sizes for favico, but that’s not all. The reality is a lot complicated, I’ll explain this issue later. Let focus on this 2 size first.

To provide the image with 2 different sizes. For ico it is not an issue, since ico is a image container file format, which can encapsulate several images with different sizes and color in a single file. It is convenient for developer, but not for users. Because it means the users need to download a big file, most of the data in which is not used at all.

For the recommended png, it is no way to provide multiple images in a single file. So we have to provide 2 different separate files, and specify them with 2 different <link> tags with sizes attribute. This is a more efficient way, but unfortunately, you’re living in the world has something called Internet Explorer. The favico in png is not supported by IE until IE 11. What a hell!

Actually, there is a lot of issue with IE in this case. There is an great article by Mathias Bynen that discussed this issue in detail, which provides a lot of interesting information related to favico.

Microsoft Windows 8

Besides typical browser usage, Favicon is also used to create Metro Tile by IE 10 and IE 11 on Windows 8. It requires something quite different. Here is a MSDN document that described how to create custom tiles for IE11 websites. For these tile icon, Windows 8 also asks for a background color other than the icon itself.

Android

In the age of mobile internet, favicon is not just used by the desktop browser, but also mobile devices. On mobile devices, there are some more specific requirements.

On android, the screen size and resolution varies between devices. So the visual elements on Android are measured in dp. According to the screen resolution, there are different conversion ratios between dp and px. And to have pixel perfect image on Android, developer should provide several images for different dp-px-ratios.

Google have a well written document that described how to create icon for the web app that added to homescreen.

iOS

For iOS, it is simliar to Android, but seems to be much more complicated. On iOS, it is also possible to create a shortcut for the web apps. Apple named such icon as apple touch icon, which is used by Safari and other browsers on iOS.

For the iOS devices, iPhone and iPad have different screen sizes, so they have different size requirements for touch icon.

Furthermore, there are device with retina display and with normal one. To have pixel perfect image on retina display, it requires the resolution of the image to be doubled.

And since iOS 7, iOS changed its UI style, the icon size used by iOS 7 is also slightly changed. So you should provide new icons for iOS 7 devices!

To make the icon fit iOS visual style best, Apple recommend web application to provide precomposed icon, which is a icon that added rounded corner and background by itself.

To have the pixel perfect icon on iOS, you might need to provide around 10 different images files as apple touch icon.

What a hell!!!! The touch icon on iOS is totally a mess!!!!

Here is a document from Apple that describes how configure web application icon.

Other

Besides all cases that describe above, favicon is also used in some special cases, such as Google TV, Opera Speed Dial, Chrome Web App. They all requires different size of favico.

Conclusion

In a short description, favico isn’t as simple as it looks. And it actually used wrongly by most websites.
To provide proper favico for all platforms and devices is not a simple work to do.
Here is the favico declaration that used this blog:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<link rel="apple-touch-icon" sizes="57x57" href="/apple-touch-icon-57x57.png">
<link rel="apple-touch-icon" sizes="114x114" href="/apple-touch-icon-114x114.png">
<link rel="apple-touch-icon" sizes="72x72" href="/apple-touch-icon-72x72.png">
<link rel="apple-touch-icon" sizes="144x144" href="/apple-touch-icon-144x144.png">
<link rel="apple-touch-icon" sizes="60x60" href="/apple-touch-icon-60x60.png">
<link rel="apple-touch-icon" sizes="120x120" href="/apple-touch-icon-120x120.png">
<link rel="apple-touch-icon" sizes="76x76" href="/apple-touch-icon-76x76.png">
<link rel="apple-touch-icon" sizes="152x152" href="/apple-touch-icon-152x152.png">
<link rel="icon" type="image/png" href="/favicon-196x196.png" sizes="196x196">
<link rel="icon" type="image/png" href="/favicon-160x160.png" sizes="160x160">
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96">
<link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16">
<link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32">
<meta name="msapplication-TileColor" content="#00a300">
<meta name="msapplication-TileImage" content="/mstile-144x144.png">

And these files are served on this blog as favico:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
favicon.ico
favicon-16x16.png
favicon-32x32.png
favicon-96x96.png
favicon-160x160.png
favicon-196x196.png
apple-touch-icon.png
apple-touch-icon-precomposed.png
apple-touch-icon-57x57.png
apple-touch-icon-60x60.png
apple-touch-icon-72x72.png
apple-touch-icon-76x76.png
apple-touch-icon-114x114.png
apple-touch-icon-120x120.png
apple-touch-icon-144x144.png
apple-touch-icon-152x152.png
browserconfig.xml
mstile-70x70.png
mstile-144x144.png
mstile-150x150.png
mstile-310x150.png
mstile-310x310.png

As you can see, to prepare all these configurations and files is not an easy job to do. It really consumes you a lot effort.

Fortunately, we have the awesome Real Favicon Generator brought by Philippe Bernard, which will save your tons of time to have the proper fav icon configuration.

Real Favicon Generator also comes with a favicon checker, which check the favorite configuration for your website, and generates beautiful report.

At last the FAQ of the site also provides a good explanation of the issue described above in details. Hope it helps.

Remove Bower from your build script

The mysterious broken build

This morning, our QA told us that knockout, a javascript library that we used in our web app is missing on staging environment. Then we checked the package she got from CI server, and the javascript library was indeed not included. But when we tried to generate the package on our local dev box, we found that knockout is included.

It is a big surprise to us, because we share the exact same build scripts and environment between dev-boxes and CI agents and because we manage the front-end dependencies with bower. In our gulp script, we ask bower to install the dependencies every time to make sure they are up to date.

The root cause of the broken build

After spending hours on diagnosing the CI agents, we finally figure out the reason, a tricky story:

When the Knockout maintainer released the v3.1 bower package, they made a mistake in bower.json config file, which packaged the spec folder instead of the dist folder. So this package is actually broken, because the main javascript file dist/knockout.js , described in bower.json doesn’t exist.

Later, the engineers realized they made a mistake, and they fixed the issue by releasing a new package. Maybe they think they haven’t changed any script logic, so they release the new package under the same version number, which is the criminal who broke our builds.

We’re so unlucky that the broken package is downloaded on our CI server when our build script was executed there for the first time. And the broken package is stored in bower cache at that time.

Because of Bower’s cache mechanism, the broken package is used unless the version is bumped or cache is expired. This is the reason why our build is broken on the CI server.

But on our dev box, for some reason, we had run bower cache clean, which invalidated the cache. So we have a good build on our local dev box. This is the reason why we can generate good package on our dev box.

It is a very tricky issue when using bower to manage dependencies. Although it is not completely our fault, but it is kind of the worst case then we can face. The build broke silently, there were no error logs or messages that helped to figure out the reason. (Well, we haven’t got a chance to setup the smoke test for our app yet, so it could be kind of our fault.)

We thought we had been careful enough to clean the bower_components folder every time, but that prevented us from figuring out the real cause.

After fixing this issue, discussed with my pair Rafa and we came up some practices that could be helpful to avoid this kind of issue:

Best practices

  • Avoid bower install or any equivalent step (such as gulp-bower, grunt-bower, etc.) in the build script
  • Check bower_components into the code repository or download the dependencies from our self managed repository for large projects.
  • When dependencies are changed, manually install them and make sure they’re good.

After doing this, our build script runs even faster, because we don’t need to check all dependencies are up-to-date every time. This is a bonus from removing bower install from our build script.

Some thoughts on the package system

Bower components are maintained by the community, and there is no strict quality control to ensure the package is bug-free or being released in an appropriate way. So it could be safer if we can check them manually, and lock them down across environments.

This could be common issue for all kind of community managed package system. Not just Bower, it could be Maven, Ruby Gem, Node.js package, Python pip package, nuget package or even Docker containers!