A canvas becomes twice as large on Retina: inset:0 does not stretch it (a bug in a logo that bursts when you tap it)

日本語版

Development log of Koshin Studio / October 2026

The top of this site has a large logo. When you tap a letter, it pops and particles scatter. After I rebuilt the logo with my own typeface, I was told “the particles come out of a strange place, not from the letter” and “it is still shifted to the right.” It took three stages to fix. Here are the cause and how I found it, with measured numbers.

Rebuilding the logo with my own typeface

The old logo was set in Latin letters built on a Mincho skeleton. I replaced it with my own typeface, Koshin Pop (rounded Latin letterforms drawn from scratch). The font is under the SIL Open Font License 1.1, which allows use in a logo.

I extract the outlines of the nine letters K O S H I N T U D from the font file and turn them into SVG paths (tools/logotype_pop.py). The logo is delivered as a picture, so the site does not ship the font file. The font has several shapes for the same letter (base, pop1, pop2), so I lined up three combinations and picked the one with the best rhythm.

Stage 1: after a tap, the letter did not return to its place

I recorded positions over time after a tap. The letters did not return to where they started.

LetterCenter before2 s after
K (top left)(327, 306)(320, 313)
S (bottom left)(331, 442)(323, 435)

That is about 7 px off. A matrix(1, 0, 0, 1, -46, -42) was left over: the scale was back to 1 but the position offset stayed.

Cause: the animation library (GSAP) rewrote the position that was already set on the letter’s SVG <g> (transform="translate(x,0)") using its own calculation, and part of that correction remained afterward.

Fix: I split the element into a layer that holds the position (outer <g transform>) and a layer that moves (inner <g class="ks-ch">), and switched the motion to the browser’s Web Animations (when it ends, the effect disappears and the original state returns). I checked all 12 letters: the centers did not move, and the transform after the animation went back to none.

Stage 2: “it is still to the right”

After that fix I was still told the animation sat to the right. My measurement said particles started within 2 to 13 px of the letter’s center. What I measured and what was seen disagreed.

I had measured on a 1x display, counting particle positions in screen coordinates. When I measured on 2x (Retina) and 3x (phone) displays, the CSS size of the particle canvas (#burst) was wrong.

DisplayViewport widthCanvas width (before)(after)
1280 px, 1x128012801280
1440 px, 2x144028801440
390 px, 3x (phone)390780390

Cause: I positioned the canvas with inset:0 in CSS, but a replaced element such as a canvas does not stretch to fill with inset:0 alone. It keeps its intrinsic size (its pixel count). On a 2x display the pixel count is doubled, so the CSS size doubled too, and particles appeared at twice the coordinates (toward the lower right). On a 1x display the sizes are equal, so you cannot notice.

Fix: set width and height to 100% explicitly. After the fix, the canvas matched the viewport on every pixel ratio.

Stage 3: emit from the letter itself

Finally I was asked whether particles could come from the letter itself. Until then they came from the center of the letter’s box, so for a letter with an empty middle like “O” they seemed to come from nowhere.

I now pick points along the outline of the letter’s path (getPointAtLength), take their on-screen positions, and send particles outward from the letter’s center with some scatter. The bottom row is drawn as “letter = mask”, so I look up the path inside the mask that the rect refers to. In the captures, “O” emits from around its ring and “U” along its shape.

What I learned

When measured numbers and what people see disagree, suspect the conditions of the measurement.

The numbers come from operating this site’s top page in a real browser (Chrome) on October 8, 2026. I have not confirmed the fix on an actual Retina device; I reproduced 2x and 3x pixel ratios with browser settings.

This is the English version of the original Japanese article.

More in English