Repository navigation
fix(icons): give inline svgs intrinsic size for unstyled paint - #330
Merged
Merged
Conversation
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>
Deploying website with
|
| 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 |
There was a problem hiding this comment.
🟢 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
This was referenced Oct 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 aswidth/heightattributes. 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 sharediconProps(class +1.05emwidth/height) for all six glyphs20=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 matchingsize-[…]classcomponents/ui/SelectMenu.test.ts— the check mark (mounts after hydration, so it never reachesout/)scripts/check-out.mjscheck 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, onwidth="", 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 servedmax-age=14400, must-revalidate, so every reload revalidates the CSS; the hashed files could beimmutableviapublic/_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