Skip to main content

Search rules

Search all UI Guides rules by name, category, or source

designjakubkrehel

Underlines From the Font

SHOULD

SHOULD: Take underline geometry from the font: `text-underline-position: from-font`, `text-decoration-thickness: from-font`, `text-decoration-skip-ink: auto` — the browser's default position slices through the descenders of g, y, p and j. Colour is the only part of a real `text-decoration` that animates reliably, so transition `text-decoration-color` for a colour hover and build anything richer (a wipe, a grow, a slide) as a separate element animated on `transform: scaleX()`.

Take underline position and thickness from the font's own metrics, and build any animated underline as a separate element

a { text-underline-position: from-font; text-decoration-thickness: from-font; text-decoration-skip-ink: auto; transition: text-decoration-color 150ms; }

Bad

Good

Why it matters

Two halves, and the second is the one people miss. The first is placement: a default underline is drawn at a position the browser picks, which at large sizes and in serif faces slices straight through the descenders of g, y, p and j. A well-made font ships its own underline position and thickness in its metrics, and `text-underline-position: from-font` plus `text-decoration-thickness: from-font` tells the browser to use them; `text-decoration-skip-ink: auto` then breaks the line around any descender that still crosses it.

The second half is animation. `text-decoration-thickness`, `text-underline-offset` and `text-decoration-line` are not reliably animatable — a hover transition on them either does nothing or steps in visible jumps. Color is the exception, and the only exception. So the rule is conditional, not absolute: if the hover effect is a color change, use a real `text-decoration` and transition `text-decoration-color`; the moment the effect is a wipe, a grow, or a slide, the underline has to be a separate element (a `::after` box, or a `background-image` line) that you can animate on `transform: scaleX()` — which is compositor-friendly, unlike anything `text-decoration` could have given you.

A dotted underline via `text-decoration-style` remains the conventional hint that a word carries extra information, which is why `abbr` gets `text-decoration: underline dotted` by default.

Built by Gleb Stroganov, design engineer at Evil Martians.

The rules come from other people's skills and guidelines — Vercel, Rauno Freiberg, @Ibelick, impeccable, Emil Kowalski, Tailwind, RAMS — each one credited on the Sources page. The work here is extraction and wiring: every rule is pulled into one corpus, given a good and a bad example you can operate, a MUST/SHOULD/NEVER rule an agent can paste, and a link back to where it came from.