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:
padding-left: 1emindents every line by one charactertext-indent: -1empulls only the first line back out- 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.