Browse by section

Web Design 日本語

CSS Hanging Indent: Align Wrapped Lines With the Text

When a line of text starts with a marker such as a bullet or an asterisk, you usually want the wrapped lines to line up with the text rather than sliding back under the marker. That is a hanging indent.

The short answer: there are two ways to do it. padding-left with a negative text-indent works everywhere, and text-indent: 1em hanging does the same job in a single line.

Here is the problem without any CSS. The second line tucks underneath the marker.

And with text-indent applied, the text lines up.

Sponsored

Two ways to write a hanging indent

The long-standing two-line approach, and the hanging keyword from CSS Text Level 4 that does it in one.

▼The two approaches compared

padding-left + negative text-indent text-indent: 1em hanging
Lines of CSS Two One
Browser support Everywhere Chrome 146 / Safari 16.6 / Firefox 122 and later
Changing the width Two values must match One value
Best for Sites that must support older browsers New work targeting current browsers

Chrome shipped the hanging keyword in version 146 in March 2026, which completed support across the major browsers. Older devices still turn up in real projects, so use the two-line version when you need certainty.

padding-left with a negative text-indent

Give every line a one-character left padding, then pull the first line back with text-indent: -1em.

<p class="hanging">* A long note goes here. When it wraps, the second line lines up with the text rather than the asterisk.</p>
.hanging {
	padding-left: 1em;
	text-indent: -1em;
}

Why it works:

  1. padding-left: 1em indents every line by one character
  2. text-indent: -1em pulls only the first line back out
  3. The marker hangs to the left and the wrapped lines align with the text

The two values must match. Pairing padding-left: 1em with text-indent: -2em pushes the first line out past the rest.

Sponsored

The hanging keyword does it in one line

Adding the hanging keyword inverts which lines get indented, so every line except the first moves. No padding is needed.

.hanging {
	text-indent: 1em hanging;
}

Normally text-indent moves the first line only. With hanging, it moves everything else instead. The value stays positive and no separate padding is involved.

Changing the width means editing one number. text-indent: 2em hanging indents by two characters. With the two-line version you had to change both values, which is exactly the kind of edit that gets half-done.

Support:

  • Chrome: 146 and later (March 2026)
  • Safari: 16.6 and later
  • Firefox: 122 and later

Browsers that do not understand hanging discard the whole declaration, so the indent disappears entirely rather than degrading. To support both, write the older version first and override it:

.hanging {
	/* fallback */
	padding-left: 1em;
	text-indent: -1em;
}

@supports (text-indent: 1em hanging) {
	.hanging {
		padding-left: 0;
		text-indent: 1em hanging;
	}
}

Why em rather than px

em is relative to the element’s own font size, so 1em is one character wide at whatever size the text happens to be.

At 16px, 1em is 16px; at 20px it is 20px. The indent tracks the text size automatically, which is what you want here.

It is not the same as the visual width of a character, though. em is derived from the font size, not from the glyph. A full-width marker lines up closely with 1em, but a short marker such as “1.” leaves a gap. Adjust to 1.5em or 2em in that case.

Sponsored

When to use a list instead

If the content is genuinely a list, use <ul> and <li>. Hanging indentation is the default behaviour of list-style-position: outside, so you get it without writing any of the above.

<ul class="notes">
	<li>A long note that lines up when it wraps.</li>
	<li>A second item.</li>
</ul>
.notes {
	/* the default; the marker sits outside the text block */
	list-style-position: outside;
	padding-left: 1.2em;
}

The difference is semantic, not visual:

  • Use a list when there are multiple items that belong together. Screen readers announce it as a list and say how many items it has
  • Use text-indent for a single paragraph that happens to begin with a marker, such as a footnote or a caveat

A note beginning with an asterisk is not a list of one. Use text-indent there.

When the indent does not appear

Almost always it is the wrong selector or the element’s display value.

▼Common causes

Symptom Cause and fix
Nothing happens at all text-indent has no effect on display: inline elements. Use block or inline-block
The first line sticks out too far padding-left and text-indent values do not match
The indent is slightly off A narrow marker is in use. Try 1.5em
The hanging version is ignored The browser does not support it. Keep the fallback in @supports

text-indent inherits. If an indent shows up somewhere you did not expect, walk up the ancestors before adjusting the element itself.

Related CSS for text layout

The same look can be built more than one way in CSS, and knowing both the old and the new version lets you pick based on what the project has to support.

CSS moves quickly, but browser support keeps you from simply always using the newest thing. The hanging keyword took several years from implementation to full availability.

Wrapping behaviour is usually configured alongside indentation. Controlling line breaks and wrapping in CSS covers white-space, overflow-wrap and the newer properties for readable line breaking.

If you would rather not write this kind of CSS by hand, the difference between display, visibility and opacity when hiding elements looks at where Bootstrap and Tailwind each fit.