Fixed-height containers collide with Dynamic Type
Aliases: dead height · intrinsic height · locked row height
What it is
A card is nailed at 72 tall, cropped for two lines of 16-pixel body. The user lifts type to about one and a half times; two lines become roughly 48 of face plus leading; the box is still 72; the arithmetic has already run out. When a fixed height and a size that moves are both in force, this is not a matter of who yields politely. Two constraints are fighting for the same pixels, and one of them breaks. Almost always it is the type: squashed, clipped, or scaled back down.
Reflow says where the extra words should go. Fixed height says the box has already refused to make room. The collision is at the box, and even a correct wrapping rule will have its result cropped if height is nailed.
Why it happens
Height nails in interfaces come from motives that look decent: lists should line up, skeletons should reserve space, the mockup grid is multiples of 8, image and type should “optically align” inside one card. Those motives hold while type size is constant. Once size is a variable, height is no longer a neutral layout number. It is a hidden cap on line count: 72 pixels only afford about two lines of 16 plus leading. The cap was computed on the designer’s default rung; the user’s rung is not in the equation.
The forms of the collision are specific. height is harder than min-height: the first refuses to grow, the second only guarantees a floor. line-clamp paired with a pixel max-height is a double nail. Table row heights, tab bars, the diameter of a round floating button, were all counted at one rung; after a change of rung either type overflows or the control itself bursts. Nail both axes — width already narrow, height dead — and type has no dimension left to escape into.
“Visually even” becomes a false evenness under Dynamic Type: the card on the left still has two lines, the user’s card on the right already has three, and forcing the heights equal crops the third. What can still align is the gap between cards, and the radius — not the pixel height of the content well.
Where it stops holding
Rules, colour bars, and progress tracks that hold no type should have their height nailed. An icon button whose type sits beside the circle, not in it, can nail the diameter; the label next to it must be able to grow. Media (image, video, map) have an aspect ratio of their own, so height can be nailed in proportion; a title stacked on top cannot share that nail. A splash or a launch ad has a fixed frame because that is the content, not because it is a type container. A list that uses fixed row height for virtualisation cannot honour type size without changing the estimate model — that is virtualisation fighting Dynamic Type, not a reason to clip.
Applying it
- Containers that hold type use
min-heightor intrinsic height, not a deadheight. What should align is the gap, not each card’s pixel height. - If a line cap is still wanted, cap “at most N lines” and recompute N with the type size. Do not fake a line count with a pixel
max-height. - Let tab bars, chips, and labelled rows grow with the type, or move the type out of the nailed block.
- Turn the system size up and find every box whose height number no longer matches its content: an inner scrollbar, a chopped glyph, type squashed. Each is a height nail and a type variable still in the same equation.