Skip to content

fix(icons): give inline svgs intrinsic size for unstyled paint - #330

Merged
thiras merged 1 commit into
mainfrom
fix/svg-intrinsic-size
Oct 21, 2026
Merged

thiras merged 1 commit into
mainfrom
fix/svg-intrinsic-size

Conversation

@thiras

@thiras thiras commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Problem

On reload, Firefox (seen on Linux) sometimes paints decdn.org for ~250ms before the stylesheet applies. The inline icons carried their size only in a Tailwind class (size-[1.05em] etc.), so that unstyled paint drew them at full container width — the hero's litepaper glyph showed as a screen-wide blue block (link colour), which read as a "fullscreen icon flash". The icons landed in #316, which is why the flash became noticeable now; before that an early unstyled paint was only plain text.

Fix

Every inline <svg> repeats its size class as width/height attributes. Presentation attributes rank below every author rule, so the class still wins once CSS loads — styled rendering is unchanged. With the CSS blocked entirely, the litepaper glyph now renders at text size instead of filling the row.

  • components/ui/icons.tsx — a shared iconProps (class + 1.05em width/height) for all six glyphs
  • TryIt chevron (20 = size-5), SelectMenu check (14 = size-3.5), PostRow pin (0.64em)

Guards

  • components/ui/icons.test.ts — each exported icon has non-empty width, height equal to it, and a matching size-[…] class
  • components/ui/SelectMenu.test.ts — the check mark (mounts after hydration, so it never reaches out/)
  • scripts/check-out.mjs check 8 — every prerendered inline <svg> in every built page has non-empty width/height; the homepage must yield at least one so the scan can't pass on nothing. Verified it fails on a stripped attribute, on width="", and on a homepage with no svg.

Not in this PR

Why Firefox paints before the stylesheet is not confirmed: a script forcing layout mid-load is its documented trigger, but headless Chromium and Playwright Firefox both held the paint until CSS arrived. This PR makes that paint harmless rather than preventing it. A possible follow-up: /_next/static/* is served max-age=14400, must-revalidate, so every reload revalidates the CSS; the hashed files could be immutable via public/_headers, shrinking the window.

Verification

pnpm build (incl. check:out, check:og-image), pnpm typecheck, pnpm lint, pnpm test (706 passed), pnpm format:check.

🤖 Generated with Claude Code

On reload Firefox can paint decdn.org before the stylesheet applies. The
inline icons carried their size only in a Tailwind class, so that paint drew
them at full container width — the hero's litepaper glyph showed as a
screen-wide blue block for ~250ms.

Every inline <svg> now repeats its size class as width/height attributes.
CSS still overrides them once it loads, so styled rendering is unchanged.
Why Firefox paints early is not confirmed; this makes that paint harmless.

- icons.tsx: shared iconProps; icons.test.ts pins attributes to the class
- TryIt chevron, SelectMenu check, PostRow pin: matching attributes
- check-out.mjs check 8: every prerendered <svg> in out/ has non-empty
  width/height, and the homepage yields at least one
- SelectMenu.test.ts covers the post-hydration check mark check 8 can't see

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 21, 2026 13:54
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying website with  Cloudflare Pages  Cloudflare Pages

Latest commit: e4f1837
Status: ✅  Deploy successful!
Preview URL: https://26cab67a.website-70y.pages.dev
Branch Preview URL: https://fix-svg-intrinsic-size.website-70y.pages.dev

View logs

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The dimensions match existing sizing classes, regression guards cover the changes, and no blocking issues remain.

No open issues 🎉

What changed in this PR

Adds explicit SVG dimensions to prevent oversized icons during an unstyled paint, without changing their styled appearance.

Changes:

  • Adds width and height attributes matching existing icon sizes.
  • Adds component tests and an export-wide SVG sizing guard.
  • Documents the new build check.
File Description
scripts/​check-out.mjs Checks SVG dimensions across exported pages.
components/​ui/​SelectMenu.tsx Sizes the selection check mark.
components/​ui/​SelectMenu.test.ts Verifies check mark dimensions.
components/​ui/​icons.tsx Shares explicit dimensions across six icons.
components/​ui/​icons.test.ts Checks dimensions match sizing classes.
components/​home/​try/​TryIt.tsx Sizes the dropdown chevron.
components/​blog/​PostRow.tsx Sizes the pin icon.
AGENTS.md Documents the SVG export guard.

Review effort: Balanced

@thiras
thiras merged commit cf22197 into main Oct 21, 2026
7 checks passed
@thiras
thiras deleted the fix/svg-intrinsic-size branch October 21, 2026 13:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants