This article is part of a series about building my personal website:

  1. The idea and choosing the right tool
  2. SEO essentials: meta tags and base head element
  3. Content management with Markdown and Frontmatter
  4. Semantic HTML for accessibility and external readers
  5. Minimalist CSS: styling and native-like design
  6. Adding color themes with JavaScript
  7. Astro plugins: RSS, Sitemap, Word count
  8. SVG icons and Favicon
  9. Building resume with XeLaTeX
  10. Extras

SVG basics

SVG is a vector image format that scales infinitely without losing quality. It’s written in XML.

Here’s a minimal template:

<svg
  xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  role="img"
  viewBox="0 0 256 256"
  width="256" height="256"
>
  <title>Your title</title>
  <path d="" />
</svg>

Notes:

Icons

For icons, I used free SVGs from SVG Repo

To make them behave like inline emojis (so they can sit inside text), I set:

<svg role="img" height="1em" width="1em" fill="currentColor">
  <title>Save</title>
  <path d="..." />
</svg>

And a little CSS makes them align better:

svg {
  vertical-align: text-bottom;
  font-size: 1.2em;
}

Favicon

Favicons are the small icons shown in browser tabs, bookmarks, and also used for home screen shortcuts.

I started with an SVG, then generated the required raster versions using rsvg-convert:

# Browser favicon: 32px, no margin, no background
rsvg-convert favicon.svg -w 32 -h 32 -o favicon.ico

# Apple touch icon: 180px canvas, 15% margin, white background
rsvg-convert favicon.svg --page-width 180 --page-height 180 --left 27 --top 27 -w 126 -h 126 -b white -o apple-touch-icon.png

# Android icon: 192px canvas, 20% margin, white background
rsvg-convert favicon.svg --page-width 192 --page-height 192 --left 38 --top 38 -w 116 -h 116 -b white -o favicon-192.png

# Open Graph (link previews): 512px canvas, 20% margin, white background
rsvg-convert favicon.svg --page-width 512 --page-height 512 --left 102 --top 102 -w 308 -h 308 -b white -o favicon-512.png

This covers browsers, iOS, Android, and link previews.

Linking icons in <head>

To make sure browsers actually use these icons, I added the following to my BaseHead.astro component:

{/* Icons */}
<link rel="icon" href="/favicon.ico" sizes="any" />
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />

{/* Manifest */}
<link rel="manifest" href="/manifest.webmanifest" />

This covers:

Manifest

The manifest.webmanifest contains metadata for Progressive Web Apps (PWAs). Even though I don’t fully use PWA features yet, it’s nice to have the icons defined in one place:

{
  "name": "Efim Ishenin",
  "short_name": "Efim.ish",
  "description": "Efim Ishenin's personal website",
  "icons": [
    {
      "src": "/favicon-192.png",
      "type": "image/png",
      "sizes": "192x192",
      "purpose": "maskable"
    },
    {
      "src": "/favicon-512.png",
      "type": "image/png",
      "sizes": "512x512",
      "purpose": "maskable"
    }
  ]
}