v150 · developer trial · css · typography

CSS4 text-decoration-skip-spaces

A new CSS property that controls whether text-decoration lines (underline, overline, line-through) draw under whitespace characters or hop over them. Lets authors get tight, typographically-correct decorations without resorting to splitting text at spaces.

concepts

  1. Decoration Toggle

    Toggle between all, none, start, end, and start end on a paragraph of multi-word linked text. See exactly which spaces the decoration line skips.

    .stage[data-skip="all"] u { text-decoration-skip-spaces: all; }
    .stage[data-skip="none"] u { text-decoration-skip-spaces: none; }
    .stage[data-skip="start"] u { text-decoration-skip-spaces: start; }
    .stage[data-skip="end"] u { text-decoration-skip-spaces: end; }
    .stage[data-skip="both"] u { text-decoration-skip-spaces: start end; }
  2. Wrapped Inline

    The motivating case from CSSWG issue 3393: two adjacent underlined links wrap to two lines. Compare none, all, start, and end side by side and watch how the joining underline disappears.

    .underline-none { text-decoration-skip-spaces: none; }
    .underline-all { text-decoration-skip-spaces: all; }
    .underline-start { text-decoration-skip-spaces: start; }
    .underline-end { text-decoration-skip-spaces: end; }
  3. Prose Links

    Multi-word inline links in realistic article body text — the primary use case for text-decoration-skip-spaces. Switch between none, all, start, and end and see how spaces inside link text are handled. A zoomed comparison shows the difference at large scale.

    .article-stage[data-skip="none"] a { text-decoration-skip-spaces: none; }
    .article-stage[data-skip="all"] a { text-decoration-skip-spaces: all; }
    .article-stage[data-skip="start"] a { text-decoration-skip-spaces: start; }
    .article-stage[data-skip="end"] a { text-decoration-skip-spaces: end; }
  4. Multiline Link Test

    Long multi-word links that wrap across lines — the canonical motivating case. Resize the container, select a skip-spaces value and decoration type, and see exactly which spaces on which line get the decoration. A static comparison grid shows all five values side by side.

    a.demo-link {
      text-decoration-line: underline;
      text-decoration-color: var(--accent-blue);
      text-decoration-skip-spaces: all;
    }
  5. Inline Element Mix

    Short links, long links, and highlighted spans in one paragraph — each with its own decoration source. Configure text-decoration-skip-spaces independently on each element type and observe that skip-spaces follows the decoration origin, not the final rendered text.

    a.short { text-decoration-skip-spaces: none; }
    a.long { text-decoration-skip-spaces: all; }
    span.hl { text-decoration-skip-spaces: start end; }
  6. RTL & Vertical Text

    start and end are logical keywords — in LTR text start is the left edge, in RTL (Arabic/Hebrew) it is the right, and in vertical writing modes it is the top. Three panels compare the same value across LTR, RTL, and vertical text simultaneously so the direction-awareness of skip-spaces is obvious.

    .ltr-link { text-decoration-skip-spaces: start; }
    .rtl-para { direction: rtl; }
    .rtl-link { text-decoration-skip-spaces: start; }
    .vert-para { writing-mode: vertical-rl; }
    .vert-link { text-decoration-skip-spaces: end; }

why it shipped

Underlines under whitespace look off to most readers: the line breaks visual rhythm and confuses kerning. Typography sites have long wanted "underline the words, not the spaces between them". text-decoration-skip-spaces: all is exactly that. The full property surface (with start, end, and combinations) gives finer control for the cases where authors want to mark word boundaries explicitly.

references

implementation reference

Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗