A favicon by itself is not a website
But what if it was?
Browsers will try a lot before they give up on rendering a website, this includes accepting binary garbage. Anything they don't know what to do with is just dumped on the screen as text.
Icon format
In the beginning, web icons used to be in Windows® icon format. This format was introduced with the very first version of the operating system, it still is the de facto icon type for modern Windows, and it has not actually significantly changed over all the years. The additions were increasing color capabilities, and the support to embed PNG files.
Fun fact: This is also the format used for static cursors on Windows
Web browsers
Web browsers will try to load the icon from /favicon.ico whenever you visit a web site.
This can be changed using a meta tag
<link rel="shortcut icon" href="/custom/path/to/icon.png" />
The "shortcut" exists purely for backwards compatibility reasons, just using "icon" is sufficient now
Modern browsers allow you to use practically any type of supported image as an icon, including vector graphic formats like SVG.
Combining HTML with an image
Most image parsers don't have a problem if there's arbitrary data after the image content, so we could just stick the image and html together. This however is fairly unstable, and editing the image will destroy the HTML.
It would be better to use a supported mechanism, and for this, PNG is ideal.
A PNG has the following structure:
- Bytes (in hex):
89 50 4E 47 0D 0A 1A 0A - IHDR chunk
- Any number of other chunks (at least one IDAT)
- IEND chunk
PNG Header byte sequence
The bytes are a fairly clever choice made by the authors:
89: If this is09we know that the topmost bit got shaved off due to a faulty 7-bit transmission somewhere. This is no longer relevant today50 4E 47: The lettersPNG0D 0A: A standard internet linebreak. Used to detect if faulty CRLF to LF conversion happened somewhere, for example in FTP transmissions that wrongly use ASCII mode rather than binary mode1A: (Known as CTRL+Z) used to terminate any attempt to print it to the terminal. On Windows, if you dotype <pngfile>in the terminal, it will just printëPNGand then end output rather than spewing binary onto the console.0A: Same reason as0D 0Abut to detect faulty conversion into the other direction.
Chunks
Every PNG chunk has the exact same structure:
- 4 bytes: Length of the header payload
- 4 bytes: Name of the header
- variable: Payload
- 4 bytes: Checksum of the header
PNG values are big endian
Apart from that, there's very few rules for PNG files. The remaining rules mostly boil down to what chunks are mutually exclusive with each other, and what chunks require a certain ordering. For ordering, the rule mostly is "do not require backtracking", which for example means that headers that influence rendering must come before the raw pixel data.
The casing of the 4 character chunk name actually tells you a few bits about it:
- Critical chunk. If this is uppercase, and the decoder doesn't knows it, it must abort rendering
- Public chunk: If this is uppercase, the chunk is officially described in the PNG spec
- Reserved: This must always be uppercase
- Copy safe: If this is uppercase, it's safe for a PNG editor to just copy the chunk to the new file if they don't know how to deal with it.
Example: tEXT can be safely ignored, is officially described, and is safe to just copy.
Text chunk
The text chunk of a PNG is uncompressed. We use this to store our HTML code inside.
As long as we tell the browser that this PNG is in reality of text/html type,
it will happily render the HTML. There will be garbage data before and after the HTML,
but this can be taken care off completely passively without any JavaScript.
If you want to read more about this on a website that is actually just a favicon, see here