SVG favicon

Posted on December 29, 2020
Updated on January 12, 2021

I’ve wanted to change this website’s favicon from a plain .ico file to a proper SVG. The problem I was trying to solve was to reuse the same image on other places, such as avatars.

Generating a PNG from the existing 16x16 icon was possible but bad: the final image was blurry. Converting the .ico to an SVG was possible, but sub-optimal: tools try to guess some vector paths, and the final SVG didn’t match the original.

Instead I used a tool to draw the “vector pixels” as black squares, and after getting the final result I manually cleaned-up the generated XML:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16">
  <path d="M 0  8  L 1  8  L 1  9  L 0  9  L 0  8  Z" />
  <path d="M 0  13 L 1  13 L 1  14 L 0  14 L 0  13 Z" />
  <path d="M 1  8  L 2  8  L 2  9  L 1  9  L 1  8  Z" />
  <path d="M 1  13 L 2  13 L 2  14 L 1  14 L 1  13 Z" />
  <path d="M 2  8  L 3  8  L 3  9  L 2  9  L 2  8  Z" />
  <path d="M 2  13 L 3  13 L 3  14 L 2  14 L 2  13 Z" />
  <path d="M 3  8  L 4  8  L 4  9  L 3  9  L 3  8  Z" />
  <path d="M 3  13 L 4  13 L 4  14 L 3  14 L 3  13 Z" />
  <path d="M 4  7  L 5  7  L 5  8  L 4  8  L 4  7  Z" />
  <path d="M 4  8  L 5  8  L 5  9  L 4  9  L 4  8  Z" />
  <path d="M 4  13 L 5  13 L 5  14 L 4  14 L 4  13 Z" />
  <path d="M 5  6  L 6  6  L 6  7  L 5  7  L 5  6  Z" />
  <path d="M 5  7  L 6  7  L 6  8  L 5  8  L 5  7  Z" />
  <path d="M 5  13 L 6  13 L 6  14 L 5  14 L 5  13 Z" />
  <path d="M 6  5  L 7  5  L 7  6  L 6  6  L 6  5  Z" />
  <path d="M 6  6  L 7  6  L 7  7  L 6  7  L 6  6  Z" />
  <path d="M 6  14 L 7  14 L 7  15 L 6  15 L 6  14 Z" />
  <path d="M 7  1  L 8  1  L 8  2  L 7  2  L 7  1  Z" />
  <path d="M 7  14 L 8  14 L 8  15 L 7  15 L 7  14 Z" />
  <path d="M 7  15 L 8  15 L 8  16 L 7  16 L 7  15 Z" />
  <path d="M 7  2  L 8  2  L 8  3  L 7  3  L 7  2  Z" />
  <path d="M 7  3  L 8  3  L 8  4  L 7  4  L 7  3  Z" />
  <path d="M 7  4  L 8  4  L 8  5  L 7  5  L 7  4  Z" />
  <path d="M 7  5  L 8  5  L 8  6  L 7  6  L 7  5  Z" />
  <path d="M 8  1  L 9  1  L 9  2  L 8  2  L 8  1  Z" />
  <path d="M 8  15 L 9  15 L 9  16 L 8  16 L 8  15 Z" />
  <path d="M 9  1  L 10 1  L 10 2  L 9  2  L 9  1  Z" />
  <path d="M 9  2  L 10 2  L 10 3  L 9  3  L 9  2  Z" />
  <path d="M 9  6  L 10 6  L 10 7  L 9  7  L 9  6  Z" />
  <path d="M 9  15 L 10 15 L 10 16 L 9  16 L 9  15 Z" />
  <path d="M 10 2  L 11 2  L 11 3  L 10 3  L 10 2  Z" />
  <path d="M 10 3  L 11 3  L 11 4  L 10 4  L 10 3  Z" />
  <path d="M 10 4  L 11 4  L 11 5  L 10 5  L 10 4  Z" />
  <path d="M 10 5  L 11 5  L 11 6  L 10 6  L 10 5  Z" />
  <path d="M 10 6  L 11 6  L 11 7  L 10 7  L 10 6  Z" />
  <path d="M 11 6  L 12 6  L 12 7  L 11 7  L 11 6  Z" />
  <path d="M 11 8  L 12 8  L 12 9  L 11 9  L 11 8  Z" />
  <path d="M 10 15 L 11 15 L 11 16 L 10 16 L 10 15 Z" />
  <path d="M 11 10 L 12 10 L 12 11 L 11 11 L 11 10 Z" />
  <path d="M 11 12 L 12 12 L 12 13 L 11 13 L 11 12 Z" />
  <path d="M 11 14 L 12 14 L 12 15 L 11 15 L 11 14 Z" />
  <path d="M 11 15 L 12 15 L 12 16 L 11 16 L 11 15 Z" />
  <path d="M 12 6  L 13 6  L 13 7  L 12 7  L 12 6  Z" />
  <path d="M 12 8  L 13 8  L 13 9  L 12 9  L 12 8  Z" />
  <path d="M 12 10 L 13 10 L 13 11 L 12 11 L 12 10 Z" />
  <path d="M 12 12 L 13 12 L 13 13 L 12 13 L 12 12 Z" />
  <path d="M 12 14 L 13 14 L 13 15 L 12 15 L 12 14 Z" />
  <path d="M 13 6  L 14 6  L 14 7  L 13 7  L 13 6  Z" />
  <path d="M 13 8  L 14 8  L 14 9  L 13 9  L 13 8  Z" />
  <path d="M 13 10 L 14 10 L 14 11 L 13 11 L 13 10 Z" />
  <path d="M 13 12 L 14 12 L 14 13 L 13 13 L 13 12 Z" />
  <path d="M 13 13 L 14 13 L 14 14 L 13 14 L 13 13 Z" />
  <path d="M 13 14 L 14 14 L 14 15 L 13 15 L 13 14 Z" />
  <path d="M 14 7  L 15 7  L 15 8  L 14 8  L 14 7  Z" />
  <path d="M 14 8  L 15 8  L 15 9  L 14 9  L 14 8  Z" />
  <path d="M 14 9  L 15 9  L 15 10 L 14 10 L 14 9  Z" />
  <path d="M 14 10 L 15 10 L 15 11 L 14 11 L 14 10 Z" />
  <path d="M 14 11 L 15 11 L 15 12 L 14 12 L 14 11 Z" />
  <path d="M 14 12 L 15 12 L 15 13 L 14 13 L 14 12 Z" />
</svg>

The good thing about this new favicon (at /static/favicon.svg) is that a) it is simple enough that I feel comfortable editing it manually and b) it is an SVG, which means I can generate any desired size.

With the new favicon file, I now had to add to the templates’ <head> a <link> to this icon:

1
2
3
4
<head>
  <meta charset="UTF-8" />
  <link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
  ...

Still missing is a bitmap image for places that can’t handle vector images. I used Jekyll generator to create an PNG from the existing SVG:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module Jekyll
  class FaviconGenerator < Generator
    safe true
    priority :high

    SIZE = 420

    def generate(site)
      svg = 'static/favicon.svg'
      png = 'static/favicon.png'
      unless File.exist? png then
        puts "Missing '#{png}', generating..."
        puts `inkscape -o #{png} -w #{SIZE} -h #{SIZE} #{svg}`
      end
    end
  end
end

I had to increase the priority of the generator so that it would run before other places that would use a /static/favicon.png, otherwise the file would be considered missing.