CSS Text Effects: text-wrap balance, line-clamp, Ellipsis and More
CSS Text Effects: text-wrap balance, line-clamp, Ellipsis, Shadows and Gradients
CSS text effects make text look polished and stay readable at any width. Modern CSS gives you native tools that used to need JavaScript: text-wrap: balance for even headings, text-wrap: pretty for better paragraph endings, line-clamp for multi-line truncation, plus shadows, gradient text, outlines and more. This lesson covers the most useful effects with practical code and browser support notes.
What You Will Learn
- Balanced and pretty line breaking with
text-wrap - Single-line ellipsis and multi-line
line-clamp text-shadowfor depth, glow and outlines- Gradient text with
background-clip: text - Text stroke with
-webkit-text-strokeandpaint-order - Drop caps with
initial-letterand::first-letter - Vertical text with
writing-modeand text selection styling - Accessibility and performance guidelines for text effects
text-wrap: balance
Headings often end with a single short word on the last line (a widow). text-wrap: balance asks the browser to spread words evenly across all lines so they are similar in length.
h1, h2, h3 { text-wrap: balance; }- It is best for headings, captions, blockquotes and short text, because the browser limits balancing to a small number of lines (about 6 in Chromium and 10 in Firefox).
- It does not change the width of the box, only where lines break. Combine it with
max-widthto control the overall block. - Browsers that do not support it simply ignore it, so it is a safe progressive enhancement.
text-wrap: pretty
text-wrap: pretty asks the browser to favor better-looking line breaks in paragraphs, mainly by avoiding very short last lines. It is more relaxed than balance and suitable for body text, at a small layout cost. Support is newer and limited to some browsers, so treat it as an enhancement.
text-wrap Shorthand and Other Values
text-wrap: wrap: normal wrapping (default).text-wrap: nowrap: no wrapping, same aswhite-space: nowrapfor wrapping behavior.text-wrap: stable: keeps earlier lines from changing while the user edits, useful in editable content.text-wrapis the shorthand fortext-wrap-modeandtext-wrap-style.
Single-Line Ellipsis
.ellipsis {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}All three properties are required, and the element needs a constrained width. In Flexbox or Grid children also add min-width: 0.
Multi-Line Truncation: line-clamp
The widely supported pattern uses the legacy box model together with the prefixed property:
.clamp {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
line-clamp: 3;
overflow: hidden;
}- The number is how many lines to show before adding an ellipsis.
- The standard unprefixed
line-clampis being rolled out and will work without the-webkit-boxdisplay, but keep the prefixed version for compatibility. - Clamped content remains in the DOM, so screen readers still read the whole text. Offer a way to see the full text, such as a Read more button.
- Tailwind CSS provides this as
line-clamp-3.
text-shadow
Syntax: text-shadow: x-offset y-offset blur color; and you can stack many shadows separated by commas.
- Soft depth:
text-shadow: 0 2px 4px rgb(0 0 0 / 0.3); - Glow:
text-shadow: 0 0 8px #0ff, 0 0 20px #0ff; - Fake outline: four shadows with 1px offsets in each direction.
- Readability on images: a subtle dark shadow helps white text over photos, but an overlay is usually the more reliable fix.
Gradient Text
.gradient {
background: linear-gradient(90deg, #ff6a00, #ee0979);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
}Always keep a fallback color before the gradient rules for browsers that do not support clipping, and make sure the lightest part of the gradient still has enough contrast with the page background.
Text Stroke and paint-order
-webkit-text-stroke: 2px #222; draws an outline around glyphs and is supported in all modern browsers. The stroke is centered on the glyph edge, so it eats into the fill. Add paint-order: stroke fill; to draw the stroke underneath the fill for a cleaner outer outline. Use -webkit-text-fill-color: transparent; for hollow text.
Drop Caps
The initial-letter property makes a large first letter that spans several lines: p::first-letter { initial-letter: 3; }. Since support is limited, a float based fallback is common: float: left; font-size: 3.2em; line-height: 0.9; padding-right: 0.08em;.
Vertical Text: writing-mode
writing-mode: vertical-rl; turns text to run top to bottom. text-orientation: upright; keeps letters upright in vertical text. It is essential for East Asian vertical typography and also great for sidebar labels and rotated table headers without transforms.
Styling Text Selection
The ::selection pseudo-element styles highlighted text: ::selection { background: #ffe066; color: #000; }. Keep contrast high.
Other Handy Text Effects
text-decorationvariants: wavy red underline for errors, or a thick offset underline for links.text-underline-position: undermoves the underline below descenders.hyphens: autoreduces ragged edges in narrow columns.text-emphasisadds marks above characters, used in East Asian typography.mix-blend-modeandbackdrop-filtercan create advanced overlay text, but test performance on mobile.
Accessibility and Performance
- Text effects must not reduce contrast below 4.5:1 for normal text and 3:1 for large text.
- Gradient and stroke text can be unreadable in Windows High Contrast (forced colors) mode, so test it.
- Do not use heavy animated effects on large blocks of text. Respect
prefers-reduced-motionfor moving text effects. - Use real text, never text inside images, so it stays selectable, translatable and searchable.
- Avoid large blur radii on many elements, since they are costly to paint.
Common Mistakes
- Using
text-wrap: balanceon long paragraphs and expecting it to work. - Forgetting
white-space: nowrapwithtext-overflow: ellipsis. - Missing
overflow: hiddenon a clamped element. - Making gradient text with a transparent fill and no fallback color.
- Expecting
line-clampto hide the text from screen readers. - Stacking too many text shadows, which hurts readability.
Frequently Asked Questions
What does text-wrap: balance do?
It balances the line lengths of a block of text so headings do not end with one lonely word.
What is the difference between balance and pretty?
balance equalizes all lines in short text. pretty mostly fixes bad last lines in long paragraphs.
How do I truncate text after two lines?
Use the line-clamp pattern with a value of 2, including display: -webkit-box and overflow: hidden.
How do I make gradient text?
Set a gradient as the background, clip it to the text with background-clip: text and make the text fill transparent.
Key Takeaways
- Use
text-wrap: balanceon headings andtext-wrap: prettyon paragraphs as progressive enhancements. - Ellipsis needs nowrap + overflow hidden + text-overflow. Multi-line truncation uses
line-clamp. - Gradient text needs
background-clip: textand a transparent fill. - Stack
text-shadowvalues for depth or glow, but protect contrast. - Test accessibility, forced colors and reduced motion for every effect.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Press Run to execute.
The headline below leaves one short word on the last line. Using a single CSS property on .headline, make the browser balance the line lengths. Also limit its width to 22em.
Press Run to execute.
Show expected output
The headline uses text-wrap: balance and max-width: 22em so the lines are even.This is a self-check — compare your result with the expected output above.
Truncate the .desc text to exactly two lines with an ellipsis at the end using the line-clamp pattern. The text should be hidden after the second line.
Press Run to execute.
Show expected output
Only two lines are visible and the second line ends with an ellipsis.This is a self-check — compare your result with the expected output above.
Make the h1 text show a horizontal gradient from #ff6a00 to #ee0979. Use background-clip for text and make the fill transparent. Keep a fallback color.
Press Run to execute.
Show expected output
The heading text is filled by a gradient from #ff6a00 to #ee0979.This is a self-check — compare your result with the expected output above.
Write a function truncate(text, maxChars) that returns the text unchanged if its length is at most maxChars. Otherwise return the first maxChars - 1 characters followed by the ellipsis character (…), so the total length equals maxChars.
Press Run to execute.
Show expected output
Short
This is a…
Exactly tenThis is a self-check — compare your result with the expected output above.
Was this page helpful?