Stop inlining the Newsreader faces into the render-blocking stylesheet
/static/app.css was 305 KB because APP_CSS base64-embedded both woff2
faces into it at runtime, and the browser cannot paint until it has the
whole sheet. Lighthouse mobile put FCP and LCP at 2.4 s for it.
The inlining was justified by a Firefox font-flash theory that the later
FOUC investigation (239125a) disproved: the flash came from theme.js
running ahead of the stylesheet, not from fonts arriving late. So point
the faces back at /static/Newsreader*.woff2, versioned with ASSET_VERSION
so the immutable one-year max-age stays safe. Gzipped, the sheet goes
from 304 KB to 12 KB.
That leaves first paint waiting on a font, so switch both faces from
font-display: block to swap and give them metric-matched local fallbacks
(Georgia, Times New Roman, Noto Serif, DejaVu Serif). The overrides are
computed from Newsreader's own metrics at the body optical size against
@capsizecss/metrics widths, so the fallback occupies the same box and the
swap changes glyph shapes and nothing else: every block on the page lands
at the same y-position either way, and CLS stays at 0.001.
Preload the regular face so it starts with the stylesheet rather than
after it parses; italic stays on demand. theme.js keeps its place after
the stylesheet link.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MD4VWGq6mGcd8Bg67qyx9k
This commit is contained in:
@@ -5,6 +5,12 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>{{ page.title }} · The Daily EPUB</title>
|
||||
{# Start the regular face downloading with the stylesheet rather than after
|
||||
it parses. `crossorigin` is required even same-origin: font fetches are
|
||||
CORS-mode, so without it the preload would not match the @font-face
|
||||
request and the file would be fetched twice. Only the regular face —
|
||||
italic is rare enough that on-demand loading is the right trade. #}
|
||||
<link rel="preload" href="/static/Newsreader.woff2?v={{ page.asset_version }}" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="stylesheet" href="/static/app.css?v={{ page.asset_version }}">
|
||||
{# Keep this synchronous script *after* the stylesheet: Gecko will not run a
|
||||
parser-blocking script while a stylesheet is pending, so the parser stalls
|
||||
|
||||
Reference in New Issue
Block a user