Shopifont

Shopify Dawn · Free, no signup · Last updated

Fix Custom Font Layout Shift on Shopify Dawn

Layout shift on Dawn after a custom font installs is almost always a missing `font-display: swap`, an unpreloaded WOFF2, or a JS-driven font swap that fires after first paint — fix all three and your CLS drops to zero.

Dawn ships clean Core Web Vitals out of the box, but a poorly configured custom font can knock CLS up by 0.10 or more. Because the Shopify OS 2.0 reference theme that ships with every new store and powers the largest install base of any free theme., the merchant audience tends to research these issues directly on mobile — making CLS a conversion-impacting metric, not just an SEO one.

Generator

Formats
WOFF2 covers ~97% of modern traffic. Add WOFF / TTF only if you need legacy fallbacks.
Apply to
Controls which Dawn typography roots the CSS variable block overrides.

Live preview

Add to cart · Free shipping · 30-day returns

Drop a WOFF2 / WOFF / TTF file here to preview your actual font. The file stays in your browser — nothing is uploaded.

Paste these three blocks in order. They're independent files in your theme — copying one without the others won't break the store.

Step 1: @font-face CSS

Paste at the bottom of assets/base.css. Uses Liquid's asset_url filter — Shopify resolves the path at render time.

@font-face {
font-family: "My Brand Sans";
src: url({{ 'my-brand-sans.woff2' | asset_url }}) format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}

How to use this on Dawn

  1. Three fixes cover almost every case.

  2. First, set `font-display: swap` on every @font-face declaration so the browser renders fallback metrics immediately and swaps in your custom face when ready.

  3. Second, preload the WOFF2 with `<link rel="preload" as="font" type="font/woff2" crossorigin>` from Dawn's `theme.liquid` head — preloading saves the round-trip the browser would otherwise make after parsing CSS.

  4. Third, override `--font-heading-family` instead of swapping classes via JavaScript: Dawn's headings (.section-header__heading, .product__title) read the variable at first paint, eliminating the post-load reflow that JS-driven swaps cause.

  5. Verify with the Performance panel in DevTools — the CLS bar should be flat across the load.

Frequently asked questions

  • Why does my custom font cause layout shift on Dawn?

    Almost always one of three causes: `font-display` defaults to `auto` which blocks rendering and then swaps, the WOFF2 isn't preloaded so the browser fetches it after parsing CSS, or a Liquid block is toggling a class via JavaScript after first paint. Dawn's Assistant fallback has different metrics than most custom faces, which exaggerates the shift if any of those three are in play.

  • How do I preload a font on Dawn to fix CLS?

    Open Dawn's `layout/theme.liquid` and insert `<link rel="preload" href="{{ 'yourfont.woff2' | asset_url }}" as="font" type="font/woff2" crossorigin>` inside the `<head>` block, above the main stylesheet link. Preloading tells the browser to fetch the font in parallel with the HTML, eliminating the wait that otherwise happens between CSS parse and font request.

  • Should I use font-display: swap or font-display: optional on Dawn?

    `swap` for nearly all Dawn stores. `optional` is theoretically zero-CLS because it skips the swap if the font isn't ready in 100ms — but on a general-purpose site, brand consistency matters, and `swap` plus a preload is functionally CLS-free without sacrificing the custom face. The generator above defaults to `swap`.

  • What size budget should I aim for to keep CLS at zero on Dawn?

    Aim for sub-50KB WOFF2 per face. Dawn's critical render path expects the font to arrive before the layout settles — at 50KB on 4G that's well within the LCP window. If your face is larger (heavy display or icon-loaded), subset it to Latin-only and only include the weights your store actually uses, which often cuts file size by 60-70%.