When the important text is the one that disappears
A UI/UX pass on Greenhouse (my creative-project manager app) turned up a card in the kanban board that had no name on it. Just a stage tag, a “neglected for 300 days” chip, and an “Available” badge - the one piece of information that actually identifies the project was gone.
The card’s markup puts the name and a row of metadata chips side by side in a flexbox row. The chips don’t shrink (flex-shrink: 0) because nobody wants “Neglected for 12d” clipped into “Neglected for 1…”. The name truncates with an ellipsis, which is normal - names are supposed to shrink to fit. But flexbox doesn’t know “shrink gracefully” and “shrink to nothing” are different outcomes. Once the metadata’s own width ate up more room than the container had, all of the missing space came out of the name, and it kept shrinking past “still readable” straight down to zero.
The fix is one line: flex-wrap: wrap on the row. Now, when both pieces don’t fit on one line, the non-shrinking metadata drops down to its own line instead of stealing width from the name. The name gets the full row and truncates down to something you can actually read, or doesn’t need to truncate at all. No JS, no magic minimum-width numbers to tune per view - I checked it against all four places this card renders (a kanban column, a normal-width dashboard list, and two others) and it self-adjusts to each one.
While I was in there I also noticed the kanban board was showing a redundant stage chip on every card, even though the column itself is already labeled by stage - pure clutter. And there was no visual hint that a board with six stages had two columns scrolled off the right edge at a normal window width. Fixed the first by hiding the chip specifically on the board (a plain prop), and the second with a neat trick I hadn’t used before: two overlapping background gradients, one that scrolls with the content and one that’s pinned to the edge, so a subtle shadow appears exactly when there’s more to scroll to and disappears when there isn’t. Pure CSS, no scroll listeners.
The part that actually slowed me down was proving any of this worked. My test suite runs on jsdom, which does zero layout - it can tell you a component rendered a <span> with the right text in it, but it has no idea whether that span is 400 pixels wide or 0. A layout bug like this is invisible to a green test suite. I ended up driving the actual compiled app through the WebDriver harness, seeding a project with a long name, pushing it into the board’s narrowest column, and screenshotting it for real. Even then I hit a wall trying to prove the scroll-shadow updates live - the screenshot tool wasn’t picking up a scrollLeft change I’d just set and confirmed via a live DOM query. Pixel-sampling the static screenshot (the shadow’s color band was sitting exactly where it should, right at the edge with more content) ended up being the more trustworthy check than the “scroll and reshoot” attempt.
Small bug, but a good reminder: anything that touches “how much room does this element get” needs to be checked with actual layout, not just “did the right text end up in the DOM.”
Related reading
Fixing a CSS grid panel that silently hid behind another panel
Three flat siblings, two columns, and auto-placement doing exactly what it was told - which put the Touch history under the wrong panel entirely.
Six small UI items, and the two near-misses hiding inside them
A CSS block that grep said was dead but a test depended on, and a single line of localStorage that broke thirty-nine unrelated tests because of a Node upgrade.
A focus ring that shouldn't have been full-strength
A bright green line under the topbar on every launch, a screenshot attempt that captured the wrong windows entirely, and a swatch that proved the color math but not the answer.