Guide 03 · Developer docs

The theme repo and the asset pipeline

Everything a developer changes on a Core dna site lives in its theme repository. This guide covers the repository and its build, printing records in templates, stylesheets and client-side code, and the parts of a site around the main content.

L1–L2
Unit 04 · Client-side code

SVG sprites, icon fonts and web fonts

Icons belong in an SVG sprite referenced from components; icon fonts are the heavier, older choice. Building and referencing a sprite in both engines, keeping an icon font small, and loading web fonts without invisible text or layout shift: preload, crossorigin and font-display.

Who this is for. The developer adding icons or fonts to a theme. Afterwards you can reference an icon from any component, keep icon and font weight under control, and load fonts so that text appears at once and does not jump when the font arrives.

SVG sprites

A sprite is one SVG file holding every icon as a <symbol> with an id. The gulp builds assemble it from a folder of single SVGs with gulp-svg-sprite; a webpack build can do the same with a sprite plugin, or the sprite can be a hand-kept file. A component then references a symbol by id:

Template code components/search-button.html
<svg class="icon" aria-hidden="true" focusable="false">
  <use href="/static/images/sprite.svg?v={$_currentSite->getLastVcsHash()}#ico-search"></use>
</svg>
<svg class="icon" aria-hidden="true" focusable="false">
  <use href="/static/images/sprite.svg?v={{ _currentSite.getLastVcsHash() }}#ico-search"></use>
</svg>
  • Use href, not the older xlink:href still common in production templates; current browsers support both, and href is the standard.
  • Version the sprite URL like any other asset. Production templates that reference sprite.svg#ico-chevron without a cache-buster show old icons to returning visitors for a year after an icon changes.
  • The sprite must come from the site's own host. Browsers do not follow <use> to another origin.
  • A decorative icon gets aria-hidden="true"; an icon that is the only content of a button needs a text label on the button.

A production Twig repository puts its sprite inline instead, in a block at the top of the base template, and references symbols as <use href="#close"/>. That saves a request and costs the sprite's bytes in every page's HTML; it suits a small set of icons.

Icon fonts

An icon font ships every glyph in the set, and its stylesheet a class for every icon. One production stylesheet imports seven Font Awesome styles and is 146 KB gzipped, partly because of it. Another site builds Font Awesome with only the icons it uses, and its whole font stylesheet is about 1 KB. If a site uses an icon font, trim it to the icons in use; for new icons, add them to the sprite.

Web fonts

Serve fonts from the site's own build or assets/ folder (woff2, woff, ttf and otf are served types), preload the one or two used above the fold, and declare them with font-display: swap so text shows at once in a fallback font:

Template code In the <head> of the base template
<link rel="preload" href="/dist/fonts/Figtree-Variable.woff2" as="font" type="font/woff2" crossorigin>
<style>
  @font-face {
    font-family: 'Figtree';
    src: url('/dist/fonts/Figtree-Variable.woff2') format('woff2');
    font-weight: 300 900;
    font-display: swap;
  }
</style>
<link rel="preload" href="/dist/fonts/Figtree-Variable.woff2" as="font" type="font/woff2" crossorigin>
<style>
  @font-face {
    font-family: 'Figtree';
    src: url('/dist/fonts/Figtree-Variable.woff2') format('woff2');
    font-weight: 300 900;
    font-display: swap;
  }
</style>

The snippet is the same in both engines: it holds no template code. A production base template follows the same pattern, preloading its two main weights and declaring its @font-face rules inline.

  • A font preload needs crossorigin, even on your own domain: fonts are fetched in CORS mode, and a preload without it does not match, so the browser downloads the font twice.
  • Preload only what the first screen uses. Every preload competes with the stylesheet and the main image for bandwidth.
  • A variable font replaces several weight files with one.
  • Reduce the shift when the font swaps in by matching the fallback's metrics: a second @font-face for a local font with size-adjust, ascent-override and descent-override, listed after the web font in font-family. Measure the result as layout shift: Decide by measurement.

A font hosted by a third party, such as Google Fonts, adds a connection to another host on the critical path. Self-hosting removes it; if you keep it, add <link rel="preconnect"> for both of its hosts.

Go deeper

Was this page helpful?

Your answer goes to the docs team.