A Missing CSS Unit: Between Root and Relative Sizing
CSS gives us two families of units. Root-based units like rem and rlh tie values to what’s set in the :root selector — typically the html element. Relative units like em, lh, and ch resolve against the font-size of the element they’re used on.
There are cases where neither works well. When you need a unit that references a base element’s typography without inheriting it directly, you’re forced into awkward em or lh calculations. A unit that sits between these two extremes would make certain layout patterns much cleaner.
Vertical Rhythm in Prose Layouts
The lh unit is useful for preserving vertical rhythm. You can space paragraphs using margins set in line-height units, and use the “Lobotomized Owl” selector or :not(:first-child) to apply spacing between siblings. These approaches work well when all siblings share a consistent line-height.
That consistency breaks down when your prose contains headings. An h2 has a larger line-height value, so an lh-based margin applied to it is much bigger than for body text. A parent with Flexbox solves the margin sizing problem — gap: 1lh spaces children evenly — but it introduces a different design problem: proximity confusion. Content following a heading belongs with that heading. Content above it belongs with the previous section. With uniform spacing, that relationship is unclear.
Adding extra space above each heading is the natural fix, but you can't use margin-top: 1lh on the h2 — its lh value is larger than the body text. You're forced to apply a margin-bottom to the element above the heading instead. With Flexbox and no margin collapse, 1lh works; using block layout, you'd need 2lh to account for collapsing.
It works, but it's a workaround, not a solution.
Padding Issues in Card Components
Card components have a similar problem. If a card contains a heading and content, where the heading uses a larger font size, padding on the card can't be set to 1lh — the heading's line-height makes that value disproportionately large.
One approach is adding a <header> wrapper around the heading so the padding applies only to a container with a different font-size. But that injects markup purely for styling.
Using a root unit like rlh for the card's padding sidesteps the problem — all card parts share the same base. But then sized variants of the card break, since 1rlh becomes disproportionately large for a smaller card. You can hard-code padding per variant, but that's brittle.
A Proposed Base Unit
An intermediate unit would reference a specified element's font-size or line-height. Think of it as defining a base context:
1bemequals one basefont-sizeunit.1blhequals one baseline-heightunit.
With such a unit, the card padding would be simple. Any nested element, regardless of its own font-size, would resolve 1blh against the base element's line-height, not its own.
Two syntax extensions could enable this in modern CSS.
Container-Query Units
Container queries already introduced units like cqw and cqh that reference container dimensions. A similar cqem or cqlh unit could reference a container's typography.
This has a downside: containers must be declared explicitly on a parent element. That adds markup and makes code less intuitive. Nested containers are manageable via container-name, but mixing different container references for different units risks collisions. A scenario might require one unit inherited from one container and another from a different one — which the current syntax can't express.
Anchor-Positioning Syntax
Another possibility mirrors CSS anchor positioning. Define a base anchor name on a base element — e.g., base-anchor: card — and allow nested elements to refer to it. Elements outside the component could also reference the named anchor explicitly.
An interesting extension is a double anchor: a base component could inherit its reference from a different base or parent. That would let component variations respond to font-size contexts without manual em calculations.
Implementing This With Current CSS
The bem and blh units don't exist today. But you can approximate their behavior with custom properties and calc().
Start by storing the base font-size as a unitless number, since calc() can't divide values with units. Then compute the actual font-size on the base element and, for any heading, divide the intended font-size by the base value.
This produces a CSS variable you can use one step down:
You can filter for these patterns in the code blocks provided at the end of this article — they demonstrate a Tailwind-based implementation that calculates the padding for a card title based on a base font-size.
A Practical Tailwind Set of Utilities
Ideally this logic lives behind a mixin, utility, or function. Using Sass mixins solves the head-ache when you have to write out the calculation yourself. Tailwind utilities can serve the same role.
A base-size utility applies the font-size and saves a CSS variable. The font-size of a child — say an h2 — is set to the derived --base-size times the intended factor.
The second part is reversing the font-size calculation to retrieve the base value. This is a practical case for CSS functions, which aren't fully supported across browsers yet. Using one, a function can accept a target font-size, divide it by the base size, and return a factor ready for multiplication.
Because you cannot use a function in all browsers, a supplementary utility writes --base-font-size straight to CSS. A utility for line-height works the same way, storing the line-height as a computed value passed to a custom property.
The Full Setup
Several utilities must be composed together before you have a working approximation of bem and blh:
The outcome is not as concise as native bem or blh would be, but it does work with what's available and avoids a breakdown in sizing for nested elements.



