Complete CSS Course Module 16: Advanced: Cutting-Edge CSS

Modern Text Styling: text-wrap, line-clamp, writing-mode and hyphens

  • Beginner
  • Lesson 16.4
  • 5 min read
  • 70 of 77 in the course

In short

Modern CSS text styling fixes ugly line breaks with text-wrap, cuts long text with line-clamp, adds hyphens, vertical text and better underlines. Better line breaks with text-wrap: balance and pretty Have you seen a heading where the last line has just one lonely word?

Modern CSS text styling fixes ugly line breaks with text-wrap, cuts long text with line-clamp, adds hyphens, vertical text and better underlines.

Better line breaks with text-wrap: balance and pretty

Have you seen a heading where the last line has just one lonely word? That word is called an orphan. CSS can now fix this for you with text-wrap.

  • text-wrap: balance makes all lines of a block roughly the same length. It is made for short text like headings and captions.
  • text-wrap: pretty mainly avoids a single short word on the last line. It is made for paragraphs.
<h1 class="hero-title">Learn to build beautiful websites from scratch</h1>
<p class="intro">This free course teaches you HTML and CSS step by step, with real examples, practice exercises and friendly explanations for complete beginners.</p>
.hero-title {
  max-width: 600px;
  text-wrap: balance;
}

.intro {
  max-width: 600px;
  text-wrap: pretty;
}

Without balance, the heading might break into one long line and a second line with just "scratch". With it, the browser splits the heading into two lines of similar length. The paragraph keeps its normal wrapping, but the browser adjusts the last few lines so no single word is left alone.

Note: Balancing is extra work for the browser, so it only works on blocks of a few lines (Chrome limits it to six). That is fine, because it is meant for headings. Older browsers just ignore it, which is a perfect progressive enhancement.

How to limit text to 3 lines with line-clamp

Card designs often need the description cut after a few lines, with "…" at the end. That is line clamping.

<article class="post-card">
  <h3>Ten tips for writing clean CSS</h3>
  <p class="excerpt">Clean CSS is easier to read, easier to change and faster to load. In this article we look at naming, file structure, variables, avoiding high specificity and many more simple habits that make a big difference in real projects.</p>
</article>
.excerpt {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
}

The paragraph shows exactly three lines, and the third line ends with "…". The full text is still in the HTML, so screen readers and search engines can read it.

Yes, those are -webkit- properties, but this exact combination works in every modern browser, including Firefox. A standard, unprefixed line-clamp property is being worked on, but at the time of writing you should use the version above. You need all four lines; if one is missing, nothing happens.

Automatic hyphens with hyphens: auto

In narrow columns, long words leave big gaps, especially with text-align: justify. hyphens: auto lets the browser break long words with a hyphen at the end of the line, like in a printed book.

<html lang="en">
  <body>
    <p class="narrow">Internationalization and accessibility are extraordinarily important responsibilities.</p>
  </body>
</html>
.narrow {
  width: 160px;
  hyphens: auto;
}

Long words like "Internationalization" now break with a hyphen, as "Internation-" and "alization", and the column looks neat.

Common mistake: Forgetting the lang attribute. The browser needs to know the language to find the correct places to split words, using a dictionary for that language. Without lang="en" (or the correct language) on <html>, hyphens: auto does nothing.

Vertical text with writing-mode

writing-mode changes the direction in which lines of text flow. It is essential for languages like Japanese and Chinese, which can be written top to bottom, and it is a nice design detail for side labels.

.side-label {
  writing-mode: vertical-rl;
  text-orientation: mixed;
  font-weight: bold;
  letter-spacing: 0.1em;
}

.spine {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
}

vertical-rl makes the text go from top to bottom, with new lines going from right to left. The .spine version is rotated so it reads from bottom to top, like the spine of a book on a shelf. Logical properties like inline-size and margin-block follow the writing mode, which is one reason they are useful.

Nicer underlines and the initial-letter note

Default underlines often cut through letters like "g" and "y" and are too thin. Two properties let you control them:

a {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
  text-decoration-color: color-mix(in oklch, currentColor, transparent 50%);
}

a:hover {
  text-decoration-color: currentColor;
}

The underline is now 2px thick, sits 4px below the text so it doesn't touch the letters, and is half-transparent. On hover it becomes fully solid, which is a soft, modern effect.

For magazine-style drop caps (a big first letter), there is initial-letter:

@supports (initial-letter: 3) {
  .article > p:first-of-type::first-letter {
    initial-letter: 3;
    margin-right: 8px;
    font-weight: bold;
  }
}

The first letter of the article becomes as tall as three lines of text. initial-letter works in Chromium browsers and Safari, but not yet in every browser, so wrap it in @supports. You can check support details on MDN's text-wrap page and the related property pages.

Practice exercise

Build a blog card list with three cards. Balance the card titles, clamp each excerpt to two lines, style the "Read more" link with a thick, offset underline, and add a vertical "NEW" label on the left side of the first card.

Hint: for the label, use writing-mode: vertical-rl on a small element and place it with Flexbox next to the card content.

Key takeaways

  • text-wrap: balance evens out heading lines; text-wrap: pretty avoids orphans in paragraphs.
  • Clamp text with display: -webkit-box, -webkit-box-orient: vertical, -webkit-line-clamp and overflow: hidden.
  • hyphens: auto needs the correct lang attribute.
  • writing-mode: vertical-rl creates vertical text.
  • text-underline-offset and text-decoration-thickness make better underlines; wrap initial-letter in @supports.