Understanding CSS text wrapping
When text doesn’t fit in its container, CSS gives you precise control over wrapping, breaking, and whitespace. The challenge: five different properties that interact in non-obvious ways.
Without explicit control, browsers make unpredictable choices. A product title might wrap mid-word. Code samples lose their indentation. URLs break at awkward spots. Long words overflow and break your layout.
white-space: Two Properties in One
The white-space property is shorthand for two modern CSS properties:
white-space-collapse: How whitespace sequences are handledtext-wrap-mode: Whether text wraps to multiple lines
Mapping Shorthand Keywords to Longhand
The six common white-space values are convenience keywords that set both longhand properties:
| white-space-collapse | text-wrap-mode | |
|---|---|---|
| normal | collapse | wrap |
| nowrap | collapse | nowrap |
| pre | preserve | nowrap |
| pre-wrap | preserve | wrap |
| pre-line | preserve-breaks | wrap |
| break-spaces | break-spaces | wrap |
white-space-collapse
Controls how whitespace sequences (spaces, tabs, newlines) are treated:
| New lines | Spaces and tabs | End-of-line spaces | Use case | |
|---|---|---|---|---|
| collapse | Collapse | Collapse | Remove | Normal text flow (default) |
| preserve | Preserve | Preserve | Preserve | Code, preformatted text |
| preserve-breaks | Preserve | Collapse | Remove | Poetry, line breaks matter but extra spaces don’t |
| break-spaces | Preserve | Preserve | Preserve & wrap | Like preserve, but allows wrapping at preserved spaces |
Key terms:
- Collapse: Multiple whitespace characters become a single space
- Preserve: Whitespace appears exactly as written in the source
- Remove: Trailing spaces at line ends are deleted entirely
- Preserve & wrap: Spaces are kept and can become break opportunities
text-wrap-mode
Controls whether text breaks across multiple lines:
| Behavior | Use case | |
|---|---|---|
| wrap | Wraps | Text flows naturally across lines |
| nowrap | No wrap | Single-line containers (ellipsis, single labels) |
All Six Values in Context
Here’s the complete behavior of the six white-space keyword values:
| New lines | Spaces and tabs | Text wrapping | End-of-line spaces | End-of-line other space separators | |
|---|---|---|---|---|---|
| normal | Collapse | Collapse | Wrap | Remove | Hang |
| nowrap | Collapse | Collapse | No wrap | Remove | Hang |
| pre | Preserve | Preserve | No wrap | Preserve | No wrap |
| pre-wrap | Preserve | Preserve | Wrap | Hang | Hang |
| pre-line | Preserve | Collapse | Wrap | Remove | Hang |
| break-spaces | Preserve | Preserve | Wrap | Preserve | Wrap |
Key terms from the table:
- Hang
- When a space falls at the end of a line, it “hangs” in the margin—invisible but preserved. Prevents spaces from affecting line-end alignment.
- Other space separators
- Unicode characters like ideographic spaces (U+3000) in CJK (Chinese, Japanese, Korean) typography. Behave differently from ASCII spaces at line boundaries. For Western text, ignore this column and focus on the first four.
.text {
white-space: normal;
}
The six white-space keyword values have broad browser support. The two-value syntax (e.g., white-space: preserve-breaks wrap) and explicit longhand properties are newer with limited support. Check caniuse.com for current compatibility.
Long Words: word-break and overflow-wrap
Text normally wraps at word boundaries. When a single word is too long to fit, these properties control what happens:
word-break: Forces breaks regardless of word boundariesoverflow-wrap: Breaks words only when necessary to prevent overflow
word-break
| Break behavior | Use case | |
|---|---|---|
| normal | Only at word boundaries (default) | Natural text flow |
| break-all | Anywhere, even mid-word | Ensure content fits, prioritize container over readability |
| keep-all | Never break words | Preserve word integrity, especially for CJK text |
overflow-wrap
| Break behavior | Use case | |
|---|---|---|
| normal | Only at word boundaries (default) | Natural text flow |
| break-word | Break long words only if needed | Graceful handling of unexpected long words |
| anywhere | Like break-word, affects sizing | More aggressive breaking, affects min-content calculations |
.text {
width: 192px; /* w-48 */
word-break: normal;
overflow-wrap: normal;
}
Use overflow-wrap: break-word for handling unexpected long words gracefully. Use word-break: break-all only when you absolutely must prevent overflow, even if it looks aggressive.
Use white-space-collapse and text-wrap-mode separately when you need fine-grained control or custom combinations not covered by the six keywords. For most cases, the shorthand keywords (normal, nowrap, pre, etc.) are simpler and have better browser support.
Custom Combinations
You can combine white-space-collapse and text-wrap-mode directly using two-value syntax:
.preserve-breaks-no-wrap { white-space: preserve-breaks nowrap; /* Preserves line breaks but prevents wrapping */ } .preserve-with-wrapping { white-space: preserve wrap; /* Preserves all whitespace and allows wrapping */ }
This allows you to create combinations beyond the six standard keywords.
Two-value syntax and explicit longhand properties have limited support. Always test or provide fallbacks.
Practical Scenarios
Single-line labels that overflow
Context: Navigation items, table headers, or badges that must stay on one line
.label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
Uses white-space: nowrap to prevent wrapping, paired with overflow/text-overflow.
Code blocks should preserve formatting
Context: Code snippets, terminal output, or preformatted data
.code { white-space: pre-wrap; overflow-wrap: break-word; }
Uses white-space: pre-wrap to keep indentation and line breaks, with overflow-wrap: break-word for long identifiers that would otherwise overflow.
Handle unexpectedly long words gracefully
Context: User-generated content, international text, or technical documentation
.paragraph { white-space: normal; overflow-wrap: break-word; }
Preserve intentional line breaks, collapse other whitespace
Context: Poetry, addresses, or formatted text blocks where authors control line breaks
.poem { white-space: pre-line; }
E-commerce product descriptions
Context: Product cards with varying content lengths across multiple languages
.product-description { white-space: normal; word-break: normal; overflow-wrap: break-word; hyphens: auto; }
Allows natural wrapping, breaks long words only when necessary, and enables hyphenation for better readability.
Common Mistakes
Setting overflow-wrap: break-word won’t help if you also have white-space: nowrap—the text simply won’t wrap. Always check that your white-space value allows wrapping (wrap, pre-wrap, pre-line, or break-spaces).
While word-break: break-all prevents overflow, it breaks words aggressively, making text harder to read. Reserve it for situations where fitting content is more important than readability (e.g., URLs, hashes, technical IDs).
Interactions with Flexbox and Grid
Text breaking properties interact with flex and grid layouts in important ways:
Flexbox overflow behavior
.flex-container { display: flex; } .flex-item { /* Without min-width: 0, flex items won't shrink below content size */ min-width: 0; overflow-wrap: break-word; }
Flex items have an implicit min-width: auto, which means they won’t shrink below their content’s minimum size. Long words create a minimum size that prevents wrapping. Setting min-width: 0 allows the flex item to shrink, enabling text to wrap.
Grid overflow behavior
.grid-container { display: grid; grid-template-columns: repeat(3, 1fr); } .grid-item { /* Grid items also need min-width: 0 to allow overflow wrapping */ min-width: 0; word-break: break-word; }
Grid items have the same min-width: auto behavior as flex items. Without resetting it, long words will cause the grid track to expand beyond 1fr, breaking your layout.
Preventing layout breaks
.card { display: flex; flex-direction: column; min-width: 0; /* Allow shrinking */ } .card-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .card-body { overflow-wrap: break-word; min-width: 0; /* Nested flex/grid also needs this */ }
This pattern ensures text never breaks your card layout, regardless of content length.