Usage
What comes out of one image
| File | What wants it |
|---|---|
favicon.ico | 16, 32 and 48px in one file — browser tabs, bookmarks, crawlers, link unfurlers |
favicon-16x16.png … favicon-96x96.png | Modern browsers, which prefer a PNG when offered one |
icon.svg | Copied through when the source is an SVG, for high-density tab strips |
apple-touch-icon.png | The iOS home screen, at 180px, flattened onto your background colour |
icon-192.png, icon-512.png | Android launchers, through the manifest |
mstile-150x150.png | Windows pinned tiles |
manifest.json | The two launcher icons and your two colours |
browserconfig.xml | The tile, and its colour |
Only files that exist are linked to. If part of a set could not be built, the browser gets fewer icons rather than links that 404, because a browser caches a missing icon and stops asking.
Source images
A square PNG, 512×512 or larger, works best. A non-square image is contained rather than cropped.
An SVG source is rasterised and also copied through as icon.svg, but only on servers running
Imagick. GD cannot rasterise vector artwork, and when it fails it produces a blank PNG rather than
an error, so Fav refuses an SVG under GD and says so on the screen. Upload a PNG instead.
SVGs are sanitised before they are copied or rasterised. Scripts, event handlers and references to other files or URLs are removed, because the copy is served from your site's own domain.
Where the tags go
By default Fav adds them to every front-end HTML page, just before the first </head>. This works
whether or not the template calls {{ head() }}.
A page whose head already links to an icon is left alone, so a hand-built head keeps working.
Turn off skipPagesWithIcons to add Fav's tags anyway. They go in last, which is the copy the
browser keeps.
Responses that are not HTML are never touched. That includes feed.rss.twig, sitemap.xml.twig
and other templates whose extension sets a different content type.
Twig
To place the tags yourself:
{{ craft.fav.tags() }}
Calling it turns off the automatic injection for that page, so the tags never appear twice.
{{ craft.fav.tagList() }} {# the tags as a list, to place one at a time #}
{{ craft.fav.url('apple-touch-icon.png') }} {# one file's URL, or null if it was not generated #}
{{ craft.fav.favicon().themeColor }} {# the set itself, for its colours #}
Each takes an optional site ID. They default to the current site.
/favicon.ico
Browsers, crawlers and link unfurlers ask for /favicon.ico at the site root, whether or not a
page links to one. Fav answers that request. Craft only sees it when there is no real file at that
path, so a favicon.ico you put in the web root yourself still wins.
Where the files live
In web/fav/<site uid>/, served by the web server as ordinary static files. If the web root is not
writable — a read-only deploy, a container — they go to storage/fav/ and are served through
Craft instead. Nothing else changes.
The folder is named by site UID, not ID. IDs differ between environments, and a set of icons that followed a database sync to the wrong site would be very hard to spot.
Staying current
Fav records a fingerprint of everything that affects the pixels: the image, its size and modification date, the colours, the padding and the manifest settings. Saving a set only regenerates it when that fingerprint has changed, so saving an unrelated setting costs nothing.
Replacing the source image in the assets index regenerates every set built from it.
Console commands
php craft fav/favicons/generate # every site, only what is out of date
php craft fav/favicons/generate default # one site, by handle
php craft fav/favicons/generate --force # rebuild regardless
php craft fav/favicons/status # what each site has, and whether it is current
php craft fav/favicons/clear # delete the generated files, keep the settings
php craft fav/favicons/clear default # one site