Repository navigation
feat(pixel-peeper), feat(garage): the share card and a pretext panel draw real HTML into canvas - #1649
Conversation
…draw real HTML into canvas Chrome 157 turned on HTML-in-Canvas (ctx.drawElementImage) by default on 2026-11-03. One canvas on the site was rebuilding what HTML already does, and one explainer was missing the other half of its argument. /pixel-peeper's share card was about 70 lines of fillRect, gradient stops and 16 fillText calls at hardcoded positions, in hex copied from luna.css. It's now HTML on the page's own tokens and classes, and it reuses the share grid and key the page shows above it. A hidden holder paints it, and drawElementImage copies it into the 1200x630 canvas that Copy image, Save PNG and Preview already used. drawCard stays as the fallback for Safari, Firefox and Chrome before 157, and for any draw that throws or reads back blank. Measured in Chrome 157 on 2026-11-10: a 1px clipping box at the viewport origin paints the whole card, even on a 390px phone and below the fold. visibility:hidden, display:none, a zero-size box and every off-screen position tried throw "No cached paint record". A canvas shrunk by CSS clips its drawable child, so the card draws in the holder and the finished canvas moves into the preview. /garage/pretext section 3 gets a second panel: the same paragraph wrapped around a real CSS float, drawn into a canvas on each paint event, driven by the same slider. It breaks line for line with pretext's layoutNextLine panel at 1280 and 390px. Browsers without the API hide the panel and say why. Brotli at q11: /pixel-peeper +967 B, /garage/pretext +589 B. No /a/ asset re-mints against origin/main 100efe6.
Wire-size diff vs merge base
Brotli q11, the quality the edge serves. Every number here is deterministic: Client assetsNo change. 40 files, 245.02 KiB Brotli total. PagesTotal Brotli: 718.80 KiB → 720.32 KiB (+1.52 KiB, +0.2%) across 77 files, 2 changed.
Worker bundle299.34 KiB → 299.38 KiB gzip (+0.04 KiB, +0.0%) Largest module deltas (raw bytes in bundle):
Dictionary transportFamily dictionary acquisition: no change, 14.50 KiB q11.
Head tags vs merge baseNo change. 77 documents, every title, description, canonical, robots, |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
aadhar-sh | b043712 | Commit Preview URL Branch Preview URL |
Nov 10 2026, 07:46 PM |
Chrome 157 turned on HTML-in-Canvas (
ctx.drawElementImage) by default on 2026-11-03. This puts it in the two places on the site where it earns its bytes./pixel-peeper: the share card is HTML
drawCardhand-painted the 1200x630 card: about 70 lines offillRect, gradient stops and 16fillTextcalls at fixed positions, in hex copied from luna.css.cardHTMLnow writes it with the page's own tokens and classes, and it reusesshareGridHTMLandshareKeyHTML, so the card and the page can't drift.cardCanvaspaints it in a hidden holder and copies it into the canvas that Copy image, Save PNG and Preview already used.drawCardstays as the fallback: for Safari, Firefox and Chrome before 157, and for any draw that throws or reads back a blank title bar. Its needle labels and footer line now shareneedleLabelsandcardFootwith the HTML card.What the holder has to be, measured in Chrome 157 on 2026-11-10:
opacity:0/clip-pathvisibility:hidden,display:none, zero sizeleft:-10000px,left:200vw, a translate)So the card draws in the 1px holder, and the finished canvas moves into the preview.
/garage/pretext: the other way into a canvas
Section 3 gets a second panel. It shows the same paragraph wrapped around a real CSS float, drawn into a canvas on each
paintevent and driven by the same slider. It breaks line for line with thelayoutNextLinepanel at 1280 and 390px. The copy says what the trade costs: a layout pass per tick, in exchange for all of CSS. Browsers without the API hide the panel and say why.Checked
bun run dev):wireShareproduces the Save PNG blob, Preview shows the drawn canvas, and the holder cleans itself up.drawCard, and pretext hides its panel and shows the note. No console errors.cardCanvasreject, and the card falls back.check:fastgreen. The first run had 1 failing test that I couldn't reproduce in two reruns, so I don't know which one it was.pages:checkandderive:checkare clean.bun run buildagainstorigin/main100efe6: no/a/asset re-mints. Brotli q11: /pixel-peeper +967 B, /garage/pretext +589 B.Known limit: Safari and Firefox users get the old card until they ship the API, so both card paths live in the page for now. Deleting
drawCardbecomes possible once they do.