Where Lines Break is Complicated. Here’s all the Related CSS and HTML.

Avatar of Chris Coyier
Chris Coyier on (Updated on )

Say you have a really long word within some text inside an element that isn’t wide enough to hold it. A common cause of that is a long URL finding it’s way into copy. What happens? It depends on the CSS. How that CSS is controlling the layout and what the CSS is telling the text to do.

This is what a break-out text situation might be like:

The text hanging out of the box is a visual problem.

One possibility is overflow: hidden; which is a bit of a blunt force weapon that will stop the text (or anything else) from hanging out. Yet, it renders the text a bit inaccessible. In some desktop browsers with a mouse, you might be able to triple-click the line to select the URL and copy it, but you can’t count on everyone knowing that or that it’s possible in all scenarios.

Overflow is the right word here as well, as that’s exactly what is happening. We have overflow: auto; at our disposal as well, which would trigger a horizontal scrollbar. Maybe suitable sometimes, but I imagine we’ll all agree that’s not generally an acceptable solution.

What we want is the dang long URL (or text of any kind) to break to the next line. There are options! Let’s start with a place to attempt figure this stuff out.

Experimental Playground

My idea here is to have a resizeable panel of content combined with a variety of CSS property/values that you can toggle on and off to see the effects on the content.

This isn’t comprehensive or perfectly executed, I’m sure. It’s just some of the properties I’m aware of.

The Sledgehammer: word-break: break-all;

Allows words to be broken anywhere. The word-break property does “solve” the issue:

p {
  word-break: break-all;
}

In an email exchange with fantasi, she explained that this works because the word-break property redefines what a word is. The break-all value essentially treats non-CJK as CJK, which can break just about anywhere (except stuff like periods and close parenthesis). The keep-all value does the reverse, treating CJK as non-CJK.

A Subtle Fix: `overflow-wrap: break-word;`

The overflow-wrap property seems to be the most effective solution for the problems we’ve laid out:

p {
  word-wrap: break-word; /* old name */
  overflow-wrap: break-word;
}

At first glance it might look very similar to the word-break: break-all; demo above, but notice how in the URL rather than breaking “pen” at “pe\n”, it breaks at the end of that word where the slash is. Nicer.

fantasai explained:

“If a word can’t break and would therefore overflow, then it can break anywhere to avoid overflow.”

A Heavier Fix, Sometimes: hyphens: auto;

The hyphens property does what you might expect…allows for hyphenation in line breaks. Hyphens can sometimes do the trick in URLs and long words, but it’s not guaranteed. A long number would trip it up, for example. Plus, hyphens affect all the text, breaking words more liberally to help text hug that right edge evenly.

p {
  hyphens: auto;
}

fantasai told me:

If a ‘word’ straddles the end of the line, we can hyphenate it.

I guess “word” helps put a finger on the issue there. Some problematically long strings aren’t “words” so it can’t be counted on to solve all overflow issues.

Future Sledgehammer: line-break: anywhere;

There is a property called line-break. It’s mostly for punctuation, apparently, but I can’t seem to see it working in any browser. fantasai tells me there will be a new value called anywhere which is:

like word-break: break-all; except it actually breaks everything like a dumb terminal client.

Other HTML Stuff

  • The <br> element will break a line wherever it renders. Unless it’s display: none;!
  • The <wbr> element is a “word-break opportunity” meaning a long word that would normally cause an annoying overflow issue could be told that it’s ok to break at a certain point. Useful! It behaves like a zero-width space.

Other CSS Stuff

  • The &shy; character is just like the <wbr> element.
  • You can inject a line break via pseudo-element like ::before { content: "\A"; } as long as the element isn’t inline (or if it is, it needs white-space: pre;)