Four Stages of the Same Google Fonts Line in One Evening

The same line of markup — a Google Fonts reference for Open Sans — went through four distinct states in one evening: deleted by accident, restored plainly, rewritten for performance, and finally replaced outright. Each stage is a real commit with a real, stated reason. Read in sequence, they're a fast-forward tour through every stage of optimizing a third-party font load, ending somewhere most sites never bother to go.

Stage one: gone by accident

A template rename — moving html.html.twig for Drupal 11 compatibility — dropped three hardcoded lines along with an unrelated AdSense script tag, none of which had anything to do with the rename itself:

  • <link rel="preconnect" href="https://fonts.googleapis.com">
  • <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  • <link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600&display=swap" rel="stylesheet">

Nobody meant to remove font loading. It just wasn't carried over when the template file was effectively rewritten for its new location.

Stage two: restored, plainly

The same three lines came back close to two hours later, unchanged, just moved from static template markup into a PHP hook (hook_page_attachments_alter()) instead of the template file directly — a straightforward "put back what was lost" fix, with no optimization attempted yet.

Stage three: rewritten to stop blocking render

Three minutes after that, the same restored lines got replaced with a different pattern:

  • <link rel="preload" href="...css2?family=Open+Sans:wght@400;600&display=swap" as="style" onload="this.rel='stylesheet'">
  • <noscript><link rel="stylesheet" href="...css2?family=Open+Sans:wght@400;600&display=swap"></noscript>

A plain <link rel="stylesheet"> blocks the browser from rendering the page until that stylesheet has been fetched and parsed. The preload-plus-onload pattern fetches the same CSS as a lower-priority preload instead, then flips it to an active stylesheet only once it's arrived, so the browser never has to pause rendering waiting on it — with a <noscript> fallback so the font still loads normally if JavaScript is unavailable. This is a well-known, standard technique for exactly this problem: real optimization, not just restoration.

Stage four: skip Google's CSS layer entirely

The commit message calls this one "Tip #4" — bypassing the Google Fonts loader by inlining @font-face CSS directly. Instead of requesting fonts.googleapis.com/css2?family=Open+Sans... at all — a request that itself just returns a small stylesheet pointing at the actual font files — two @font-face rules were hardcoded straight into style.css, pointing directly at specific font file URLs on Google's font-serving CDN:

  • src:url(https://fonts.gstatic.com/s/opensans/v44/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0C4n.ttf)

This removes an entire request-response round trip: instead of fetching Google's CSS, parsing it, then fetching the font files it references, the browser goes straight to the font files. It's a real, meaningful reduction in requests for something this small.

The tradeoff stage four actually makes

The URL above has a version segment in it — v44 — and a long file-specific hash. Google's dynamic css2 endpoint resolves "Open Sans, weights 400 and 600" to whatever the current font file happens to be, automatically, including any future re-hint or hosting change on Google's end. A hardcoded URL to a specific versioned file doesn't get that for free. If Google ever restructures how it serves that particular font build, or deprecates the v44 path, the direct link breaks silently — the CSS rule still loads, just against a URL that may no longer resolve, with no dynamic layer left to route around it. The dynamic API traded a small amount of overhead for staying current automatically. The hardcoded version traded that safety net for speed, on the assumption that a specific Google Fonts CDN path is stable enough, for long enough, to be worth pinning to directly.

Reading the four stages as one arc

None of the four commits second-guesses the one before it — each is a legitimate step further than the last: fix the accident, restore correctly, stop blocking render, then cut a request. What's notable is that a mistake (stage one) and a genuine optimization campaign (stages three and four) both moved through the same three lines of markup in the same evening, and only reading all four commits together — not just the last one — shows which parts of the final state exist because they were deliberately chosen and which exist only because something upstream broke first and had to be un-broken before optimizing could even start.

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.
Please share this article on your favorite website or platform.