Styling Text
Most of the web is text: articles, notices, product descriptions, error messages. A page with good colours but cramped, wide or badly wrapped text is still tiring to read. A few well-chosen text properties make a big difference.
In this lesson you will control alignment, line spacing and line length, style underlines, change letter case and spacing, cut long text with an ellipsis, and balance the lines of headings. Choosing and loading fonts is covered next in Fonts & Web Fonts.
Readable paragraphs
Three properties decide how comfortable a paragraph is to read:
line-heightsets the height of each line. For body text,1.5to1.7works well. Write it without a unit: a unitless value is multiplied by each element's own font size, so it stays right when a child has bigger text.- Line length: lines that are too long make the eye lose its place. Around 60 to 75 characters per line is comfortable, and
max-width: 65chgives you that. text-align: usestart(the default for left-to-right languages) for body text.centersuits short headings and buttons, not paragraphs.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Readable text</title>
<style>
body { font-family: system-ui, sans-serif; padding: 1rem; color: #22272e; }
article { max-width: 65ch; margin-inline: auto; }
p { line-height: 1.65; font-size: 1.0625rem; }
.label {
text-transform: uppercase;
letter-spacing: 0.08em;
font-size: 0.8rem;
font-weight: 600;
color: oklch(50% 0.13 250);
}
h1 { line-height: 1.15; text-align: center; }
a {
color: oklch(48% 0.16 250);
text-decoration-thickness: 2px;
text-underline-offset: 0.2em;
}
</style>
</head>
<body>
<article>
<p class="label">Travel diary</p>
<h1>Two days in Kochi</h1>
<p>Rohan started his first morning at Fort Kochi beach, watching the fishermen lift the huge Chinese fishing nets out of the water. By noon he had walked through Jew Town, tried banana chips straight from the fryer and found a quiet cafe with filter coffee.</p>
<p>On the second day he took the ferry to Vypin Island. The ticket cost only a few rupees, and the view of the harbour was the best part of the trip. <a href="#">Read his full itinerary</a>.</p>
</article>
</body>
</html>The article never grows wider than about 65 characters, even on a big screen. The small "Travel diary" label is written in normal case in the HTML and turned into capitals with text-transform, with a little extra letter-spacing because capitals look cramped otherwise. The link has a thicker underline that sits slightly below the letters.
Underlines and decoration
text-decoration adds lines to text. It is a shorthand for the line type, style, colour and thickness:
a {
text-decoration: underline dotted oklch(55% 0.15 30);
text-underline-offset: 3px;
}
a:hover {
text-decoration-style: solid;
}
.old-price {
text-decoration: line-through;
color: #6b7280;
}Links in running text should stay underlined, so people can spot them without relying on colour. Use text-underline-offset and text-decoration-thickness to make the underline neater rather than removing it. The line-through value is handy for an old price next to a sale price.
Spacing and case
letter-spacingadds or removes space between letters. Use smallemvalues like0.05em, mostly for capitals and small labels.word-spacingchanges the space between words; you will rarely need it.text-indentindents the first line of a block.text-transformchanges case:uppercase,lowercaseorcapitalize(first letter of each word).
Long words and long lines
Long words and URLs can overflow narrow boxes on phones. Two properties help:
.comment {
overflow-wrap: anywhere; /* break long URLs or words if they do not fit */
}
.article {
hyphens: auto; /* add hyphens where the language allows */
}hyphens: auto needs the correct lang attribute on the page, such as <html lang="en">, because hyphenation rules differ by language.
Truncating text with an ellipsis
To keep a product name on one line and show "..." when it is too long, you need three properties together:
.product-name {
white-space: nowrap; /* keep it on one line */
overflow: hidden; /* hide what does not fit */
text-overflow: ellipsis; /* show ... at the cut */
}For several lines, for example a three-line summary on a card, use the line-clamp pattern. Despite the -webkit- prefixes it works in all major browsers:
.summary {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
}Remember that truncated text is hidden from sighted users. Make sure the full text is available somewhere, such as on the product page.
Better line breaks with text-wrap
Headings often wrap badly: a long first line and a single lonely word on the second. text-wrap: balance asks the browser to make the lines roughly equal in length. It is meant for short text such as headings and captions, and it is supported in current versions of all major browsers.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>text-wrap</title>
<style>
body { font-family: system-ui, sans-serif; padding: 1rem; }
h2 { width: 18rem; font-size: 1.6rem; line-height: 1.2; border: 1px dashed #b8c2cf; padding: 0.5rem; }
.balanced { text-wrap: balance; }
.name {
width: 12rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
border: 1px dashed #b8c2cf;
padding: 0.5rem;
}
</style>
</head>
<body>
<h2>Admissions open for the new academic year in Jaipur</h2>
<h2 class="balanced">Admissions open for the new academic year in Jaipur</h2>
<p class="name">Stainless steel pressure cooker, 5 litre, induction base</p>
</body>
</html>The first heading has uneven lines. The second, with text-wrap: balance, spreads the words evenly across its lines. The product name is cut with an ellipsis.
Common mistakes
- Line-height with units.
line-height: 24pxstays 24px even for a 40px heading inside, so lines overlap. Use a number such as1.5. - Very wide paragraphs. Full-width text on a desktop is hard to read. Limit it with
max-width: 65ch. - Justified text on narrow screens.
text-align: justifycreates big gaps between words on phones. Preferstart. - Removing link underlines. Users then have to guess what is clickable from colour alone.
- Ellipsis without
nowrapandoverflow.text-overflowdoes nothing on its own.
Key points
- Use a unitless
line-heightof about 1.5 to 1.7 and limit paragraphs to about65chwide. - Keep body text aligned to
start; centre only short text. - Keep link underlines and refine them with
text-underline-offsetandtext-decoration-thickness. - Use
text-transformfor capitals rather than typing capitals in HTML. text-overflow: ellipsisneedswhite-space: nowrapandoverflow: hidden.text-wrap: balanceevens out heading lines;text-wrap: prettyimproves paragraph endings where supported.
Exercise
Style a short news article about a school sports day in Lucknow. Limit the article to 60ch, give paragraphs a comfortable line height, balance the heading, add an uppercase category label with letter spacing, and show the old entry fee of ₹200 crossed out next to the new fee of ₹150.
Show solution
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Sports day</title>
<style>
body { font-family: system-ui, sans-serif; padding: 1rem; }
article { max-width: 60ch; margin-inline: auto; }
.category { text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.8rem; color: #8a3324; }
h1 { text-wrap: balance; line-height: 1.2; }
p { line-height: 1.6; }
.old { text-decoration: line-through; color: #6b7280; }
</style>
</head>
<body>
<article>
<p class="category">School news</p>
<h1>Annual sports day returns to the city stadium this December</h1>
<p>Students from classes 6 to 12 will compete in athletics, kabaddi and relay races.</p>
<p>Entry fee for parents: <span class="old">₹200</span> ₹150</p>
</article>
</body>
</html>The category text is typed in normal case and shown in capitals by CSS, and the old fee keeps its meaning while looking crossed out.
Quick Quiz
1. Which line-height is the best choice for body text?
A unitless value scales with each element's font size, and 1.5 to 1.7 is comfortable for paragraphs.
2. Which properties are needed together for a single-line ellipsis?
The text must stay on one line and the overflow must be hidden before an ellipsis can appear.
3. What does text-wrap: balance do?
It changes where lines break so they are evenly filled, without changing alignment.
4. Why use text-transform: uppercase instead of typing capitals in HTML?
The style changes the look only; the underlying text stays in normal case.
Learn CSS with a mentor
Free lessons get you started. Our Full Stack Web Development training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
