Let’s talk about the various ways we can control how text wraps (or doesn’t wrap) on a web page. CSS gives us a lot of tools to make sure our text flows the way we want it to, but we’ll also cover some tricks using HTML and special characters.

Box wrapped with long ribbon

Protecting Layout

Normally, text flows to the next line at “soft wrap opportunities”, which is a fancy name for spots you’d expect text to break naturally, like between words or after a hyphen. But sometimes you may find yourself with long spans of text that don’t have soft wrap opportunities, such as really long words or URLs. This can cause all sorts of layout issues. For example, the text may overflow its container, or it might force the container to become too wide and push things out of place.

It’s good defensive coding to anticipate issues from text not breaking. Fortunately, CSS gives us some tools for this.

Getting Overflowing Text to Wrap

Putting overflow-wrap: break-word on an element will allow text to break mid-word if needed. It’ll first try to keep a word unbroken by moving it to the next line, but will then break the word if there’s still not enough room.

See the Pen overflow-wrap: break-word by Will Boyd (@lonekorean) on CodePen.

There’s also overflow-wrap: anywhere, which breaks words in the same manner. The difference is in how it affects the min-content size calculation of the element it’s on. It’s pretty easy to see when width is set to min-content.

.top {
  width: min-content;
  overflow-wrap: break-word;
}

.bottom {
  width: min-content;
  overflow-wrap: anywhere;
}

See the Pen overflow-wrap + min-content by Will Boyd (@lonekorean) on CodePen.

The top element with overflow-wrap: break-word calculates min-content as if no words are broken, so its width becomes the width of the longest word. The bottom element with overflow-wrap: anywhere calculates min-content with all the breaks it can create. Since a break can happen, well, anywhere, min-content ends up being the width of a single character.

Remember, this behavior only comes into play when min-content is involved. If we had set width to some rigid value, we’d see the same word-breaking result for both.

Breaking Words without Mercy

Another option for breaking words is word-break: break-all. This one won’t even try to keep words whole — it’ll just break them immediately. Take a look.

See the Pen word-break: break-all by Will Boyd (@lonekorean) on CodePen.

Notice how the long word isn’t moved to the next line, like it would have been when using overflow. Also notice how “words” is broken, even though it would have fit just fine on the next line.

word-break: break-all has no problem breaking words, but it’s still cautious around punctuation. For example, it’ll avoid starting a line with the period from the end of a sentence. If you want truly merciless breaking, even with punctuation, use line-break: anywhere.

See the Pen word-break: break-all vs line-break: anywhere by Will Boyd (@lonekorean) on CodePen.

See how word-break: break-all moves the “k” down to avoid starting the second line with “.”? Meanwhile, line-break: anywhere doesn’t care.

Excessive Punctuation

Let’s see how the CSS properties we’ve covered so far handle excessively long spans of punctuation.

See the Pen Excessive Punctuation by Will Boyd (@lonekorean) on CodePen.

overflow-wrap: break-word and line-break: anywhere are able to keep things contained, but then there’s word-break: break-all being weird with punctuation again — this time resulting in overflowing text.

It’s something to keep in mind. If you absolutely do not want text to overflow, be aware that word-break: break-all won’t stop runaway punctuation.

Specifying Where Words Can Break

For more control, you can manually insert word break opportunities into your text with <wbr>. You can also use a “zero-width space”, provided by the &ZeroWidthSpace; HTML entity (yes, it must be capitalized just as you see it!).

Let’s see these in action by wrapping a long URL that normally wouldn’t wrap, but only between segments.

  <!-- normal -->
  <p>https://subdomain.somewhere.co.uk</p>

  <!-- <wbr> -->
  <p>https://subdomain<wbr>.somewhere<wbr>.co<wbr>.uk</p>

  <!-- &ZeroWidthSpace; -->
  <p>https://subdomain&ZeroWidthSpace;.somewhere&ZeroWidthSpace;.co&ZeroWidthSpace;.uk</p>

See the Pen Manual Word Break Opportunities by Will Boyd (@lonekorean) on CodePen.

Automatic Hyphenation

You can tell the browser to break and hyphenate words where appropriate by using hyphens: auto. Hyphenation rules are determined by language, so you’ll need to tell the browser what language to use. This is done by specifying the lang attribute in HTML, possibly on the relevant element directly, or on <html>.

<p lang="en">This is just a bit of arbitrary text to show hyphenation in action.</p>
  p {
    -webkit-hyphens: auto; /* for Safari */
    hyphens: auto;
  }

See the Pen hyphens: auto by Will Boyd (@lonekorean) on CodePen.

Manual Hyphenation

You can also take matters into your own hands and insert a “soft hyphen” manually with the &shy; HTML entity. It won’t be visible unless the browser decides to wrap there, in which case a hyphen will appear. Notice in the following demo how we’re using &shy; twice, but we only see it once where the text wraps.

<p lang="en">Magic? Abraca&shy;dabra? Abraca&shy;dabra!</p>

See the Pen Soft Hyphen by Will Boyd (@lonekorean) on CodePen.

hyphens must be set to either auto or manual for &shy; to display properly. Conveniently, the default is hyphens: manual, so you should be good without any additional CSS (unless something has declared hyphens: none for some reason).

Preventing Text from Wrapping

Let’s switch things up. There may be times when you don’t want text to wrap freely, so that you have better control over how your content is presented. There are a couple of tools to help you with this.

First up is white-space: nowrap. Put it on an element to prevent its text from wrapping naturally.

See the Pen white-space: nowrap by Will Boyd (@lonekorean) on CodePen.

Preformatting Text

There’s also white-space: pre, which will wrap text just as you have it typed in your HTML. Be careful though, as it will also preserve spaces from your HTML, so be mindful of your formatting. You can also use a <pre> tag to get the same results (it has white-space: pre on it by default).

<!-- the formatting of this HTML results in extra whitespace! -->
<p>
  What's worse, ignorance or apathy?
  I don't know and I don't care.
</p>

<!-- tighter formatting that "hugs" the text -->
<p>What's worse, ignorance or apathy?
I don't know and I don't care.</p>

<!-- same as above, but using <pre> -->
<pre>What's worse, ignorance or apathy?
I don't know and I don't care.</pre>
p {
  white-space: pre;
}

pre {
  /* <pre> sets font-family: monospace, but we can undo that */
  font-family: inherit;
}

See the Pen Preformatted Text by Will Boyd (@lonekorean) on CodePen.

A Break, Where Words Can’t Break?

For line breaks, you can use <br> inside of an element with white-space: nowrap or white-space: pre just fine. The text will wrap.

But what happens if you use <wbr> in such an element? Kind of a trick question… because browsers don’t agree. Chrome/Edge will recognize the <wbr> and potentially wrap, while Firefox/Safari won’t.

When it comes to the zero-width space (&ZeroWidthSpace;) though, browsers are consistent. None will wrap it with white-space: nowrap or white-space: pre.

<p>Darth Vader: Nooooooooooooo<br>oooo!</p>

<p>Darth Vader: Nooooooooooooo<wbr>oooo!</p>

<p>Darth Vader: Nooooooooooooo&ZeroWidthSpace;oooo!</p>

See the Pen white-space: nowrap + breaking lines by Will Boyd (@lonekorean) on CodePen.

Non-Breaking Spaces

Sometimes you may want text to wrap freely, except in very specific places. Good news! There are a few specialized HTML entities that let you do exactly this.

A “non-breaking space” (&nbsp;) is often used to keep space between words, but disallow a line break between them.

<p>Something I've noticed is designers don't seem to like orphans.</p>

<p>Something I've noticed is designers don't seem to like&nbsp;orphans.</p>

See the Pen Non-Breaking Space by Will Boyd (@lonekorean) on CodePen.

Word Joiners and Non-Breaking Hyphens

It’s possible for text to naturally wrap even without spaces, such as after a hyphen. To prevent wrapping without adding a space, you can use &NoBreak; (case-sensitive!) to get a “word joiner”. For hyphens specifically, you can get a “non-breaking hyphen” with &#8209; (it doesn’t have a nice HTML entity name).

  <p>Turn right here to get on I-85.</p>

  <p>Turn right here to get on I-&NoBreak;85.</p>

  <p>Turn right here to get on I&#8209;85.</p>

See the Pen Word Joiners and Non-Breaking Hyphens by Will Boyd (@lonekorean) on CodePen.

CJK Text and Breaking Words

CJK (Chinese/Japanese/Korean) text behaves differently than non-CJK text in some ways. Certain CSS properties and values can be used for additional control over the wrapping of CJK text specifically.

Default browser behavior allows words to be broken in CJK text. This means that word-break: normal (the default) and word-break: break-all will give you the same results. However, you can use word-break: keep-all to prevent CJK text from wrapping within words (non-CJK text will be unaffected).

Here’s an example in Korean. Note how the word “자랑스럽게” does or doesn’t break.

See the Pen CJK Text + word-break by Will Boyd (@lonekorean) on CodePen.

Be careful though, Chinese and Japanese don’t use spaces between words like Korean does, so word-break: keep-all can easily cause long overflowing text if not otherwise handled.

CJK Text and Line Break Rules

We talked about line-break: anywhere earlier with non-CJK text and how it has no problem breaking at punctuation. The same is true with CJK text.

Here’s an example in Japanese. Note how “。” is or isn’t allowed to start a line.

See the Pen CJK Text + line-break by Will Boyd (@lonekorean) on CodePen.

There are other values for line-break that affect how CJK text wraps: loose, normal, and strict. These values instruct the browser on which rules to use when deciding where to insert line breaks. The W3C describes several rules and it’s possible for browsers to add their own rules as well.

Worth Mentioning: Element Overflow

The overflow CSS property isn’t specific to text, but is often used to ensure text doesn’t render outside of an element that has its width or height constrained.

.top {
  white-space: nowrap;
  overflow: auto;
}

.bottom {
  white-space: nowrap;
  overflow: hidden;
}

See the Pen Element Overflow by Will Boyd (@lonekorean) on CodePen.

As you can see, a value of auto allows the content to be scrolled (auto only shows scrollbars when needed, scroll shows them always). A value of hidden simply cuts off the content and leaves it at that.

overflow is actually shorthand to set both overflow-x and overflow-y, for horizontal and vertical overflow respectively. Feel free to use what suits you best.

We can build upon overflow: hidden by adding text-overflow: ellipsis. Text will still be cut off, but we’ll get some nice ellipsis as an indication.

p {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

See the Pen text-overflow: ellipsis by Will Boyd (@lonekorean) on CodePen.

Bonus Trick: Pseudo-Element Line Break

You can force a line break before and/or after an inline element, while keeping it as an inline element, with a little bit of pseudo-element trickery.

First, set the content of a ::before or ::after pseudo-element to '\A', which will give you the new line character. Then set white-space: pre to ensure the new line character is respected.

<p>Things that go <span>bump</span> in the night.</p>
span {
  background-color: #000;
}

span::before, span::after {
  content: '\A';
  white-space: pre;
}

See the Pen Pseudo-Element Line Breaks by Will Boyd (@lonekorean) on CodePen.

We could have just put display: block on the <span> to get the same breaks, but then it would no longer be inline. The background-color makes it easy to see that with this method, we still have an inline element.

Bonus Notes

  • There’s an older CSS property named word-wrap. It’s non-standard and browsers now treat it as an alias for overflow-wrap.

  • The white-space CSS property has some other values we didn’t cover: pre-wrap, pre-line, and break-spaces. Unlike the ones we did cover, these don’t prevent text wrapping.

  • The CSS Text Module Level 4 spec describes a text-wrap CSS property that looks interesting, but at the time of writing, no browser implements it.

    Update: Browsers have implemented it! Read more about how to use it for nicer text wrapping.

Time to “Wrap” Things Up

There’s so much that goes into flowing text on a web page. Most of the time you don’t really need to think about it, since browsers handle it for you. For the times when you do need more control, it’s nice to know that you have a lot of options.

Writing this was definitely a rabbit hole for me as I kept finding more and more things to talk about. I hope I’ve shown you enough to get your text to break and flow just the way you want it.

Thanks for reading!