fix(places): align the measure column's heading with its values #120

Merged
tudor merged 1 commits from fix/place-table-alignment into main 2026-08-21 21:21:04 +00:00
Owner

The heading sat on the right edge of the column and every value on the left. It looked like a layout problem; it was a CSS specificity collision in the stylesheet I wrote.

The cause

The heading and the value were aligned by two different selectors, and only one of them won:

Selector Specificity Declares Outcome
.table td (0,1,1) text-align: left won for the value
.num (0,1,0) text-align: right lost
.table th:last-child (0,2,1) text-align: right won for the heading

So the heading went right, the numbers stayed left, and the column read as broken on every place page.

The fix

The heading cell and the value cell now carry the same class, matched by one rule. They cannot drift apart again regardless of what else changes around them — which is a stronger guarantee than getting the specificity right twice.

The column also stretched to half the table, because nothing constrained it. It now hugs its content with width: 1% and white-space: nowrap, so the school name takes the remaining width. That is what made the gap between heading and value read as misalignment on desktop, and what crowded the name column on mobile.

Verification

Frontend 255 · tsc --noEmit clean · next build green · backend 100 unaffected.

Two new tests. One asserts the heading and value cells share a class — the specific thing that was wrong, rather than the symptom. The other asserts the name column stays unclassed so it keeps taking the spare width.

Note

Worth saying plainly: a unit test cannot see a specificity collision, because jsdom does not apply CSS module rules. What the new test pins is the invariant that prevents it — one class, one rule — which is checkable. The collision itself was only ever going to be caught by looking at the page.

🤖 Generated with Claude Code

https://claude.ai/code/session_015mWQnpye9F299NVRCCSRvj

The heading sat on the right edge of the column and every value on the left. It looked like a layout problem; it was a **CSS specificity collision** in the stylesheet I wrote. ## The cause The heading and the value were aligned by two different selectors, and only one of them won: | Selector | Specificity | Declares | Outcome | |---|---|---|---| | `.table td` | (0,1,1) | `text-align: left` | **won** for the value | | `.num` | (0,1,0) | `text-align: right` | lost | | `.table th:last-child` | (0,2,1) | `text-align: right` | **won** for the heading | So the heading went right, the numbers stayed left, and the column read as broken on every place page. ## The fix The heading cell and the value cell now carry **the same class**, matched by **one rule**. They cannot drift apart again regardless of what else changes around them — which is a stronger guarantee than getting the specificity right twice. The column also stretched to half the table, because nothing constrained it. It now hugs its content with `width: 1%` and `white-space: nowrap`, so the school name takes the remaining width. That is what made the gap between heading and value read as misalignment on desktop, and what crowded the name column on mobile. ## Verification Frontend 255 · `tsc --noEmit` clean · `next build` green · backend 100 unaffected. Two new tests. One asserts the heading and value cells share a class — the specific thing that was wrong, rather than the symptom. The other asserts the name column stays unclassed so it keeps taking the spare width. ## Note Worth saying plainly: a unit test cannot see a specificity collision, because jsdom does not apply CSS module rules. What the new test pins is the *invariant that prevents it* — one class, one rule — which is checkable. The collision itself was only ever going to be caught by looking at the page. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_015mWQnpye9F299NVRCCSRvj
tudor added 1 commit 2026-08-21 21:15:03 +00:00
fix(places): align the measure column's heading with its values
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m3s
PR Checks / Backend Smoke (pull_request) Successful in 7s
PR Checks / Build Backend (no push) (pull_request) Successful in 11s
PR Checks / Build Frontend (no push) (pull_request) Successful in 44s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 10s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 14s
dbb74d9b60
The heading sat on the right edge of the column and every value on the left.
A specificity collision, not a layout problem: the two were aligned by
different selectors and only one of them won.

  .table td            (0,1,1)  text-align: left    <- won for the value
  .num                 (0,1,0)  text-align: right   <- lost
  .table th:last-child (0,2,1)  text-align: right   <- won for the heading

The heading and the value cell now share one class and one rule, so they
cannot drift apart again whatever else changes around them.

The column also stretched to half the table. It now hugs its content with
width:1% and nowrap, so the school name takes the remaining width — which is
what made the gap read as misalignment on a wide screen, and what crowded the
name column on a narrow one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015mWQnpye9F299NVRCCSRvj

🤖 AI Code Review (Claude Code)

This PR fixes a CSS specificity bug where the measure column's header and values were misaligned due to differing selector specificity, by unifying them under a single shared class .num applied to both the th and td elements, plus adding width:1%/nowrap so the column hugs its content. Tests are added to verify alignment and that the school-name column remains unclassed. The change is low-risk, purely presentational, and well-tested.

✅ No issues found.

## 🤖 AI Code Review (Claude Code) This PR fixes a CSS specificity bug where the measure column's header and values were misaligned due to differing selector specificity, by unifying them under a single shared class `.num` applied to both the th and td elements, plus adding width:1%/nowrap so the column hugs its content. Tests are added to verify alignment and that the school-name column remains unclassed. The change is low-risk, purely presentational, and well-tested. ✅ No issues found.
tudor merged commit 4cea26b813 into main 2026-08-21 21:21:04 +00:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: tudor/school_compare#120