| 3 min read

SVG Favicon Generation: A Tiny Detail That Matters

SVG favicon branding CSS web development

Why SVG Favicons?

Traditional favicons are bitmap images (ICO, PNG) that look blurry on high-DPI displays and require multiple sizes for different contexts. SVG favicons are vector-based, so they scale perfectly at any size. They also support CSS media queries, which means your favicon can automatically adapt to dark mode.

I switched my portfolio to an SVG favicon and the improvement in quality at small sizes was immediately noticeable. Here is how to create one.

Creating an SVG Favicon

For a text-based favicon like my initials, the SVG is simple:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
  <text x="4" y="48"
    font-family="Georgia, serif"
    font-size="48"
    font-weight="700"
    fill="#4d94d4">
    SL
  </text>
</svg>

This creates a 64x64 viewport with the letters "SL" in blue Georgia font. Because it is vector, it looks sharp at 16x16 in a browser tab, 32x32 in bookmarks, and 180x180 on an iOS home screen.

Adding Dark Mode Support

SVG favicons can include CSS with media queries:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
  <style>
    text { fill: #4d94d4; }
    @media (prefers-color-scheme: dark) {
      text { fill: #6db3f2; }
    }
  </style>
  <text x="4" y="48"
    font-family="Georgia, serif"
    font-size="48"
    font-weight="700">
    SL
  </text>
</svg>

When the user's system is in dark mode, the favicon automatically switches to a lighter blue that is visible against a dark browser tab bar. This is a subtle touch that most sites miss.

Inline SVG Favicons

For maximum simplicity, you can inline the SVG directly in the HTML link tag using a data URI. This eliminates an HTTP request:

<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Ctext x='4' y='48' font-family='Georgia,serif' font-size='48' font-weight='700' fill='%234d94d4'%3ESL%3C/text%3E%3C/svg%3E" type="image/svg+xml">

This is what I use on my site. The SVG is URL-encoded and embedded directly in the href attribute. No separate file to serve, cache, or worry about.

Encoding SVGs for Data URIs

You can generate the data URI in Python:

from urllib.parse import quote

svg = '''<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
  <text x="4" y="48" font-family="Georgia,serif" font-size="48" font-weight="700" fill="#4d94d4">SL</text>
</svg>'''

data_uri = f"data:image/svg+xml,{quote(svg)}"
print(data_uri)

URL encoding is more readable than base64 for SVG content and produces similar file sizes.

Fallback for Older Browsers

Not all browsers support SVG favicons. Provide a PNG fallback for comprehensive support:

<!-- SVG for modern browsers -->
<link rel="icon" href="/favicon.svg" type="image/svg+xml">

<!-- PNG fallback -->
<link rel="icon" href="/favicon-32x32.png" sizes="32x32" type="image/png">

<!-- Apple touch icon -->
<link rel="apple-touch-icon" href="/apple-touch-icon.png">

Browsers that understand SVG favicons will use the first link. Older browsers fall back to the PNG. Apple devices use the touch icon for home screen bookmarks.

Generating PNG Fallbacks from SVG

If you need PNG versions, generate them from the SVG with a simple script:

from cairosvg import svg2png

with open('favicon.svg', 'r') as f:
    svg_content = f.read()

# Generate multiple sizes
for size in [16, 32, 48, 180, 192, 512]:
    svg2png(
        bytestring=svg_content.encode(),
        write_to=f'favicon-{size}x{size}.png',
        output_width=size,
        output_height=size
    )

This generates all the PNG sizes you might need from a single SVG source, ensuring consistency across all versions.

Design Tips for Favicons

Favicons are typically displayed at 16x16 to 32x32 pixels. At these sizes, detail disappears. Keep these principles in mind:

  • Simplify ruthlessly: One or two letters, a simple shape, or a bold icon. No detailed illustrations.
  • Use bold weights: Thin text disappears at small sizes. Use bold or extra-bold font weights.
  • Test at actual size: View your favicon at 16x16 pixels. If you cannot identify it instantly, simplify further.
  • Avoid fine lines: Lines thinner than 2px at the favicon's native size will alias badly on non-retina screens.
  • Choose distinctive colours: Your favicon competes with dozens of others in a browser tab bar. A distinctive colour helps it stand out.

Beyond the Browser Tab

Favicons appear in more places than you might expect:

  • Browser tabs and tab stacks
  • Bookmark lists and bars
  • Browser history
  • Desktop shortcuts and PWA icons
  • Search engine results (Google sometimes shows favicons)
  • Social media link previews (some platforms)

A good favicon builds recognition across all these touchpoints. It is a small detail, but in a world of small details, the ones you get right distinguish a professional site from an amateur one.

My SVG Favicon Checklist

  • SVG with proper viewBox attribute
  • System font stack (no external font dependencies)
  • Dark mode media query for adaptive colour
  • Inline data URI to eliminate HTTP requests
  • PNG fallbacks for older browsers
  • Apple touch icon for iOS
  • Tested at 16x16, 32x32, and 180x180 sizes

Total implementation time: about 20 minutes. Worth every second.