Skip to content

Measure label widths instead of guessing them - #13

Merged
odiwr merged 2 commits into
mainfrom
feat/measure-label-widths
Aug 30, 2026
Merged

odiwr merged 2 commits into
mainfrom
feat/measure-label-widths

Conversation

@odiwr

@odiwr odiwr commented Aug 30, 2026

Copy link
Copy Markdown
Owner

What this changes

Two things.

1. Label widths are measured, not estimated.

Rows on the axis are assigned from how wide each label is, and the width was a
flat 7.2 pixels per character — a number measured once against one sans-serif
at one size, then applied to every theme and every headline.

Measured against the real thing it was 15–25% too wide across the board,
including in the default font:

Headline Estimated Actual
The printing press 130px 103px
Writing spreads through Greece 216px 183px
Bartlett's Remembering 158px 134px

An overestimate does not overlap labels — it wastes rows. The packer shoves
apart neighbours that would have fitted, so the stack grows taller than it
needs to and the shorter label budget kicks in earlier than it should.

Now measured with canvas.measureText in the font the labels actually render
in, read from a live label so a page theming --bt-font is measured in its own
font. Cached per string, dropped when the font changes. Falls back to the old
estimate where canvas is unavailable.

Also re-lays-out on document.fonts.ready — a web font arriving after first
paint changes every width, and without this the layout stays committed to
measurements taken in the fallback face.

2. An issue seeder.

node scripts/seed-issues.mjs files the starter issues in one command. Safe to
re-run; --dry-run and --print included.

Verification

Checked in a browser at 1100px: 13 events across 8 lanes, 0 overlapping
labels
, 24 ticks. All 87 tests pass. Bundle 15.9 KB gzipped.

Screenshots

Not attached — the change is a layout correction rather than a visual redesign;
the axis looks the same, with tighter rows.


  • npm test passes
  • npm run build passes
  • Behaviour changes in packages/core have a test — n/a, this is packages/element
  • Comments explain why

odiwr added 2 commits August 29, 2026 19:51
Rows on the axis are assigned from how wide each label is, and the width was
a flat 7.2 pixels per character. That number was measured once, against one
sans-serif at one size, and then applied to every theme and every headline.

Measured against the real thing it was 15-25% too wide across the board --
"The printing press" was estimated at 130px and actually renders at 103. An
overestimate does not overlap labels, it wastes rows: the packer pushes
neighbours apart that would have fitted, so the stack grows taller than it
needs to and the shortest label budget kicks in earlier than it should.

Now measured with canvas measureText in the font the labels actually render
in, read from a live label so a page theming --bt-font is measured in its own
font. Results are cached per string and dropped when the font changes.

Also re-lays-out on document.fonts.ready: a web font arriving after first
paint changes every width, and without this the layout stays committed to
measurements taken in the fallback face.

Falls back to the old estimate where canvas is unavailable.

Verified in the browser: 13 events over 8 lanes, 0 overlapping labels.
Files the starter issues in one command instead of a dozen browser forms.
An empty tracker tells a visitor there is nothing to do here; a dozen scoped
issues tells them where to start, and that difference is worth automating so
it actually gets done.

  node scripts/seed-issues.mjs            create everything
  node scripts/seed-issues.mjs --dry-run  show what would be created
  node scripts/seed-issues.mjs --print    markdown, to file by hand

Creating a label that already exists is treated as success, so the script is
safe to re-run.
@odiwr
odiwr merged commit 7cfcfff into main Aug 30, 2026
3 checks passed
@odiwr
odiwr deleted the feat/measure-label-widths branch August 30, 2026 00:26
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.

1 participant