What CSS ellipsis really is

When people say “CSS ellipsis”, they usually mean this behavior: text gets cut off when it doesn’t fit, and the browser shows at the end.

The important bit: CSS does not “add dots to any overflowing text” automatically. You have to set up a few conditions so the browser knows: “This text must stay on one line, it’s allowed to be clipped, and if it’s clipped, show an ellipsis.”

We’ll start with the classic single-line ellipsis, then move into the real-world stuff where it tends to break (flex, grid, tables), and finally multi-line truncation with line-clamp.

.title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
  
.title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: clip;
}
  
.title {
  white-space: normal;
  overflow: hidden;
  text-overflow: ellipsis;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.demo {
  width: 320px;
  border: 3px solid #111;
  padding: 14px;
  font-family: ui-sans-serif, system-ui, sans-serif;
  background: #f2f2f2;
}

.title {
  font-size: 18px;
  border: 2px dashed #111;
  padding: 10px;
  background: #fff;
}
  
This is a very long title that absolutely refuses to fit inside this container, and that’s exactly the point.

In the first snippet, the browser is allowed to clip overflowing text and replace the “hidden” tail with an ellipsis. In the second snippet, we switch to text-overflow: clip, meaning “just cut it off”. In the third snippet, we remove white-space: nowrap, and you’ll notice the ellipsis stops doing what you want, because the text is now allowed to wrap.

The three ingredients for single-line ellipsis

Single-line ellipsis requires three things working together:

  • A single line: usually white-space: nowrap
  • Clipping: usually overflow: hidden
  • A reason to overflow: a constrained size (like a set width, max-width, or a layout that gives it a limited space)

If you forget the constraint, nothing overflows, so nothing gets ellipsized. If you forget overflow: hidden, the text can spill out, so the browser doesn’t “need” an ellipsis. If you forget white-space: nowrap, the text wraps instead of overflowing in one line.

.demo {
  width: 320px;
}

.title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.demo {
  border: 3px solid #111;
  padding: 14px;
  font-family: ui-sans-serif, system-ui, sans-serif;
  background: #f2f2f2;
}

.title {
  font-size: 18px;
  border: 2px dashed #111;
  padding: 10px;
  background: #fff;
}
  
Resize the container and watch the ellipsis kick in.

Drag the slider: when the container becomes too narrow, the overflow happens, and the ellipsis appears. When you make it wide enough, the full line fits again, so the ellipsis disappears.

Common reasons CSS ellipsis doesn’t work

Ellipsis failing is almost always one of these:

  • The element has no constrained width (it just grows to fit the text).
  • The element is display: inline (many inline elements don’t behave like a box with overflow rules).
  • The element is a flex or grid child with default min sizing that prevents shrinking.
  • You’re trying to ellipsize multiple lines using text-overflow (it’s single-line only).
.title {
  display: inline;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
  
.title {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.demo {
  width: 320px;
  border: 3px solid #111;
  padding: 14px;
  font-family: ui-sans-serif, system-ui, sans-serif;
  background: #f2f2f2;
}

.title {
  font-size: 18px;
  border: 2px dashed #111;
  padding: 10px;
  background: #fff;
}
  
Inline elements can be tricky for overflow rules. Block is usually the easiest fix.

With display: inline, the browser often treats the content more like “text flow” than a box that can clip. Switching to display: block (or inline-block) gives you a real box to constrain and clip.

Ellipsis in flex layouts: the min-width: 0 rule

Welcome to the #1 “why is my ellipsis broken?” situation: flexbox.

In a flex row, a flex item has a default min-width behavior that often prevents it from shrinking smaller than its content. Meaning: instead of the text overflowing and ellipsizing, the flex item can refuse to shrink, and the layout overflows.

The fix is usually simple: put min-width: 0 on the flex child that contains the text.

.row .text {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
  
.row .text {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.row {
  width: 410px;
  border: 3px solid #111;
  padding: 12px;
  font-family: ui-sans-serif, system-ui, sans-serif;
  background: #f2f2f2;
  display: flex;
  gap: 10px;
  align-items: center;
}

.avatar {
  width: 42px;
  height: 42px;
  border: 3px solid #111;
  background: #fff;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  font-weight: 700;
}

.text {
  border: 2px dashed #111;
  background: #fff;
  padding: 10px;
  flex: 1 1 auto;
  font-size: 16px;
}

.badge {
  flex: 0 0 auto;
  border: 3px solid #111;
  background: #fff;
  padding: 6px 10px;
  font-weight: 700;
}
  
A
This is the flex item that should shrink and show an ellipsis instead of forcing the whole row to overflow.
NEW

Try the first snippet: you might see the text not ellipsize properly depending on the exact browser/layout behavior. Switch to the second snippet: min-width: 0 lets the flex item actually shrink, so the ellipsis can happen.

Ellipsis with flex and buttons/icons

A common UI pattern is “title on the left, actions on the right”. Your action buttons should keep their size, while the title truncates.

Try resizing the container below from its lower right corner.

.toolbar .title {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.toolbar {
  width: 520px;
  border: 3px solid #111;
  padding: 10px;
  font-family: ui-sans-serif, system-ui, sans-serif;
  background: #f2f2f2;
  display: flex;
  align-items: center;
  gap: 10px;
}

.title {
  flex: 1 1 auto;
  border: 2px dashed #111;
  background: #fff;
  padding: 10px;
  font-size: 16px;
}

.actions {
  display: flex;
  gap: 8px;
  flex: 0 0 auto;
}

.actions button {
  border: 3px solid #111;
  background: #fff;
  padding: 8px 10px;
  font: inherit;
  cursor: pointer;
}
  
A very long document name that should politely get out of the way when the action buttons need room

Ellipsis in grid layouts: minmax(0, 1fr)

Grid has a similar “minimum size” story. If you have a column like 1fr, it can behave like it has a minimum based on content, which can prevent the text box from becoming smaller than its content.

Two popular fixes:

  • Put min-width: 0 on the grid child that needs to shrink, or
  • Use minmax(0, 1fr) for the column that should be shrinkable.
.grid {
  grid-template-columns: 46px 1fr 80px;
}

.name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
} 
.grid {
  grid-template-columns: 46px minmax(0, 1fr) 80px;
}

.name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.grid {
  width: 520px;
  border: 3px solid #111;
  padding: 12px;
  font-family: ui-sans-serif, system-ui, sans-serif;
  background: #f2f2f2;
  display: grid;
  gap: 10px;
  align-items: center;
}

.icon {
  width: 46px;
  height: 46px;
  border: 3px solid #111;
  background: #fff;
  display: grid;
  place-items: center;
  font-weight: 700;
}

.name {
  border: 2px dashed #111;
  background: #fff;
  padding: 10px;
  font-size: 16px;
}

.price {
  border: 3px solid #111;
  background: #fff;
  padding: 10px;
  text-align: center;
  font-weight: 700;
}
  
Grid item text that should truncate nicely without breaking the whole grid layout into horizontal scrolling sadness
$49

Switch between the two snippets. They might look the same, however the second one (with minmax(0, 1fr)) is the “grid-friendly” way to guarantee that the text column can actually shrink and overflow.

Multi-line ellipsis with line-clamp

Now for the plot twist: text-overflow: ellipsis is really meant for a single line.

For multi-line truncation, the modern approach is line-clamp. It’s like saying: “show only N lines, then clip the rest.” Most implementations also show an ellipsis-like ending, but technically it’s a clamped box, not the same as text-overflow.

The common pattern looks like this:

  • display: -webkit-box
  • -webkit-box-orient: vertical
  • -webkit-line-clamp: 3 (or whatever number)
  • overflow: hidden
.desc {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
}
  
.desc {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 5;
  overflow: hidden;
}
  
.desc {
  display: block;
  overflow: visible;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.card {
  width: 520px;
  border: 3px solid #111;
  padding: 14px;
  font-family: ui-sans-serif, system-ui, sans-serif;
  background: #f2f2f2;
}

.card h4 {
  margin: 0 0 10px;
  font-size: 18px;
}

.desc {
  border: 2px dashed #111;
  background: #fff;
  font-size: 16px;
  line-height: 1.35;
}
  

Multi-line description

This paragraph is intentionally long. The goal is to show how clamping lets you keep a tidy layout while still having content that could otherwise be a small novel. With line-clamp you choose how many lines get displayed, and the rest is clipped so your cards remain consistent in height and don’t turn your layout into a scrolling museum.

Use the first snippet to clamp to 3 lines, the second to 5 lines, and the third to remove clamping. This is the “multi-line ellipsis” technique you’ll see in card grids, blog lists, product descriptions, and so on.

Line-clamp that expands on hover

A friendly UI trick is: clamp by default, but expand when the user hovers or focuses the card. That way your layout stays tidy, but the full content is still easily accessible.

.card .desc {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
}

.card:hover .desc,
.card:focus-within .desc {
-webkit-line-clamp: unset;
overflow: visible;
} 
*,
::before,
::after {
  box-sizing: border-box;
}

.card {
  width: 520px;
  border: 3px solid #111;
  padding: 14px;
  font-family: ui-sans-serif, system-ui, sans-serif;
  background: #f2f2f2;
}

.card h4 {
  margin: 0 0 10px;
  font-size: 18px;
}

.desc {
  border: 2px dashed #111;
  background: #fff;
  font-size: 16px;
  line-height: 1.35;
  margin: 0 0 10px;
}

.card a {
  display: inline-block;
  border: 3px solid #111;
  background: #fff;
  padding: 8px 10px;
  text-decoration: none;
  color: #111;
}
  

Hover or focus to expand

This is clamped to three lines by default. Hover the card (or focus the link) to expand the whole text. It’s a neat compromise: clean layout, but still readable content without a “Read more” click in simple cases.

Focusable link

The :focus-within part matters for keyboard users: if someone tabs into the card, the text expands too.

Ellipsis in tables and long identifiers

Tables and “technical strings” (IDs, URLs, filenames) are ellipsis magnets. You often want to clamp the middle column and keep the table from exploding horizontally.

.cell {
  max-width: 240px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
  
.cell {
  max-width: 240px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: inline-block;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  width: 520px;
  border: 3px solid #111;
  padding: 14px;
  font-family: ui-sans-serif, system-ui, sans-serif;
  background: #f2f2f2;
}

table {
  width: 100%;
  border-collapse: collapse;
  background: #fff;
}

th,
td {
  border: 2px solid #111;
  padding: 10px;
  text-align: left;
  font-size: 14px;
}

th {
  background: #f2f2f2;
}

.mono {
  font-family: ui-monospace, SFMono-Regular, monospace;
}
  
Order Transaction ID Total
#1042 txn_7f3c2d9b0a1e4f8c9d2a1234567890_long_on_purpose $89.00
#1043 https://example.com/some/really/really/really/long/url/that/does/not/want/to/fit $129.00

In tables, it can help to wrap the text in a span that you control. If it doesn’t ellipsize as expected, switching that span to inline-block is often the missing piece.

Practical patterns you’ll use all the time

Ellipsis in card lists

A common pattern: a list of cards where the title is single-line ellipsis, but the description is multi-line clamped.

.item-title {
  width: 440px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.item-desc {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
} 
*,
::before,
::after {
  box-sizing: border-box;
}

.list {
  width: 520px;
  border: 3px solid #111;
  padding: 14px;
  font-family: ui-sans-serif, system-ui, sans-serif;
  background: #f2f2f2;
  display: grid;
  gap: 12px;
}

.item {
  border: 3px solid #111;
  background: #fff;
  padding: 12px;
}

.item-title {
  font-size: 16px;
  font-weight: 700;
  margin: 0 0 6px;
}

.item-desc {
  margin: 0;
  font-size: 14px;
  line-height: 1.35;
}
  

A long title that should stay on one line and politely end with an ellipsis

A slightly longer description that we clamp to two lines so the list stays neat and every card feels consistent.

Another very long title that tries very hard to push everything else off the screen

If you have a grid of cards, clamping descriptions keeps the heights consistent and makes scanning easier. The full content can still be revealed on click, hover, or on the detail page.

Ellipsis for breadcrumbs

Breadcrumbs are basically “tiny horizontal space with unexpectedly long text”. A typical trick is: let the middle crumb shrink and ellipsize, while the first and last stay visible.

.crumbs {
  display: flex;
  gap: 8px;
  align-items: center;
}

.crumb-mid {
min-width: 0;
flex: 1 1 auto;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
} 
*,
::before,
::after {
  box-sizing: border-box;
}

.bar {
  width: 520px;
  border: 3px solid #111;
  padding: 12px;
  font-family: ui-sans-serif, system-ui, sans-serif;
  background: #f2f2f2;
}

.crumb {
  border: 3px solid #111;
  background: #fff;
  padding: 6px 10px;
  flex: 0 0 auto;
  font-size: 14px;
  white-space: nowrap;
}

.sep {
  font-weight: 700;
}
  
Home
/
Very long category name that should not steal the whole breadcrumb bar for itself
/
Article

The secret sauce again is min-width: 0 on the flex child you want to shrink.

Accessibility and UX tips

Ellipsis is convenient, but it hides information. For beginners (and future-you), these rules help:

  • Don’t hide critical info: if the text is essential, consider showing it fully or adding a “Show more”.
  • Support keyboard users: if content expands on hover, also expand on :focus or :focus-within.
  • Prefer readable truncation: clamp descriptions to a couple lines, but keep titles short when possible.
.title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.box {
  width: 360px;
  border: 3px solid #111;
  padding: 14px;
  font-family: ui-sans-serif, system-ui, sans-serif;
  background: #f2f2f2;
}

.title {
  border: 2px dashed #111;
  background: #fff;
  padding: 10px;
  font-size: 16px;
}
  
This is the complete text that was truncated visually

The title attribute is not perfect UX, but it’s a simple safety net. For important content, a real “expand” UI is usually better.

Recap: CSS Ellipsis checklist

  • Single line: white-space: nowrap
  • Clip overflow: overflow: hidden
  • Show dots: text-overflow: ellipsis
  • Make sure it can actually overflow (constrain width somehow)
  • Flex child not shrinking? Add min-width: 0
  • Grid column not shrinking? Use minmax(0, 1fr) (or min-width: 0 on the child)
  • Need multiple lines? Use -webkit-line-clamp style clamping instead of text-overflow

Learn more about Text Wrapping in the CSS Text Wrap Interactive Tutorial.