svg-icon-experiment

This project demos two SVG icon approaches:

Inline

A SVG sprite sheet with some manual optimizations. HTML is minified with html-minifier.

localhost, Fast 3G

  • TTFB: ~570 ms
  • DOMContentLoaded: ~620 ms

GitHub Pages, Slow 3G

  • TTFB: ~2.00 s
  • DomContentLoaded: ~2.00 s

External

SVGs in individual img elements. SVGs are minified with svgo, HTML is minified with html-minifier.

Loading experience:

simulated external loading

localhost, Fast 3G

  • TTFB: ~570 ms
  • DOMContentLoaded: ~620 ms

GitHub Pages, Slow 3G

  • TTFB: ~2.00 s
  • DomContentLoaded: ~2.00 s

Setup

  1. Ensure Node.js (>=12.16) is installed.
  2. Install dependencies:
npm install

Build

npm run clean && npm run build

Tips for small icons

This projects icons were created in Sketch, exported as SVGs, then hand-tuned for minimal size. Here's a set of guidelines for producing assets that minify well:

Graphics editor

  • Ensure every border position is set to "center" in the border position setting. SVG doesn't offer border positioning; matching SVG's center border position ensures shape and line points don't have to be recalculated.
  • Set shapes and points on the pixel grid (ex: 1 or 1.5 instead of arbitrary values like 1.051664). This outputs smaller files and ensures that SVG point optimization doesn't alter the icon.
  • Prefer basic shapes, like the Rectangle and Oval, and Vector-drawn shapes. These are often easy to group into a single SVG path.
  • Avoid shape combinations (Union, Subtract, etc.) and shape flatten.
  • Minimize grouping.
  • Set the artboard size such that the most common border width among icons is 1. This takes advantage of SVG's default and ensures the stroke-width property can be omitted.
  • If an icon can be made up entirely with Vector tool lines, do it. A good example is the classic hamburger menu icon: it can be created with three rounded rectangles, but it can be optimized better if its made of three lines.

Manual tuning

  • Remove Sketch's Artboard groups if possible:

    <g id="My Artboard" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
      <!-- ... -->
    </g>

    These often aren't needed but aren't possible to optimize with svgo.

  • If your icon set is monochromatic, change the stroke and fill colors to currentColor.

    - <path stroke="#000000" />
    + <path stroke="currentColor" />

    The SVG icon will take on the color of its parent when used inline. (ref).

  • Ensure that elements of similar type have the same attributes. For example:

    <svg viewBox="0 0 12 12" version="1.1" xmlns="http://www.w3.org/2000/svg">
      <polyline
        fill="none"
        points="6 3 6 9"
        stroke-linecap="round"
        stroke-linejoin="round"
        stroke="currentColor"
      />
      <polyline
        fill="none"
        points="2.5 6.5 6 9.5 9.5 6.5"
        stroke-linecap="round"
        stroke-linejoin="round"
        stroke="currentColor"
      />
    </svg>

    svgo will optimize both polylines into a path, but hey have to have the same stroke* attributes.

  • You might be tempted to pull common attributes to a parent g, but be careful: this can prevent svgo from optimizing many elements into a path in most cases.

  • Experiment! Try a few options and run it through svgo to see what works best.