Revealing text-overflow: ellipsis

A wide flat landscape

One of the curses of building "enterprise applications" is the usual scenario of dealing with interfaces with too much data in them. "Must show all fields" and "needs more columns" are typical requests that make UX designers and front-end developers die a little on the inside. 😱

Uncritically adding more content is in general a bad approach: it increases the cognitive load of users, creates more intimidating interfaces for newcomers, makes performance worse, and many other negative effects. Adding a piece of information to your interface should be an exercise in weighing costs and benefits.

But what to do when you must display more data? If the design does not accommodate it, you can break the whole layout. Especially with smaller screens and user-generated data, a single long name or label can introduce awkward wrapping or the tragicomedy of horizontal scrolling. In despair, the "what if we just trim it with dot-dot-dot" suggestion comes up.

Enter text-overflow: ellipsis. Set this on a container with a specific width and overflow: hidden, and any text content will be trimmed with an elegant ellipsis character "…"

Let's look at a simple example; a flex container with three items:

<div class="parent">
<div class="container">This is some content</div>
<div class="container">This is some content, a bit longer</div>
<div class="container">This fits</div>
</div>
.parent {
border: 0.75rem solid rebeccapurple;
display: flex;
gap: 0.5rem;
width: fit-content;
}

.container {
border: 0.75rem solid lightsteelblue;
display: inline-block;
padding: 0.5rem;
}
This is some content
This is some content, a bit longer
This fits

When we provide a specific width or max-width to our containers (or otherwise limit their size), we can see the overflow problem (this is the defining behaviour of CSS).

.container {
white-space: nowrap;
width: 10rem;
}
This is some content
This is some content, a bit longer
This fits

The sensible solution here is to go back to the drawing board and consider our options: limit the size of the content, expand the available space by moving other elements, wrap content into multiple lines… We're not doing sensible things here. 🧨 Let's rush a fix through: the ellipsis to the rescue! (Seriously, if you call it "dot-dot-dot" we'll need to sit down and have a conversation.)

.container {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: 10rem;
}
This is some content
This is some content, a bit longer
This fits

So, we had a problem before, we have a different problem now! It looks visually better, but it conveys even less information. I can't event select the whole text, copy, and paste it somewhere else to read it. This really doesn't solve much unless the whole content is not very interesting. For instance, a listing of emails can display the first few words of each message body and truncates the rest with ellipsis. But for other scenarios, especially those where it's not possible to navigate to the full data view, this is Not Good Enough.

We could re-evaluate and redesign; instead, let's dig deeper. One suggestion that usually comes up is "just place the full content in the title attribute; it shows up on hover". Indeed, the browser will display a tooltip when hovering over such an element. This is worse than it sounds:

  • The "hover" behaviour doesn't work without an appropriate pointing device. Touchscreen and keyboard users will remain sad/angry and without a tooltip
  • Tooltips can be slow to appear
  • The content will be truncated at different lengths in different browsers
  • You can't style the tooltips. At all
  • This is abusing the title attribute. It is meant to provide "advisory information related to the element"
  • It duplicates data
  • In short, it's an accessibility no-no

Here's the same example, with mistreated title attributes; try to read those on your phone. 😏

This is some content
This is some content, a bit longer
This fits

OK, fine. What else can we do? Redesign? Nah! Let's keep at this on-hover idea. We could pull in a big tooltip Javascript library to bypass most of the concerns above. Or… we could CSS our way out. Let's add one more wrapper element (in this case a <span> but it's not important) to create our own on-hover behaviour.

<div class="parent">
<div class="container">
<span>This is some content</span>
</div>
<div class="container">
<span>This is some content, a bit long</span>
</div>
<div class="container">
<span>This fits</span>
</div>
</div>
.container {
width: 10rem;
}

.container > span {
display: block;
overflow: hidden;
padding: 0.5rem;
text-overflow: ellipsis;
white-space: nowrap;
}

.container:hover > span {
background-color: inherit;
contain: paint;
display: inline-flex;
outline: 1px solid;
min-width: 100%;
}

If you look carefully you'll notice that we moved the overflow and text-overflow properties to the inner wrapper, instead of keeping them on .container. This allows .container to use the default of overflow: visible (i.e. the behaviour on the very first example).

The inner wrapper is now responsible for hiding the overflow… until it's hovered. When it is, we change its display to inline-flex, which forces its layout to expand and wrap the full contents. Since the parent is still locked at width: 10rem it does not change dimensions, and the overflow simply spills out.

Here's how it looks (try hovering):

This is some content
This is some content, a bit long
This fits

Why inline-flex? We could use inline-block, but that positions the element along the baseline, changing the parent's line-height, and we'd need to start playing with vertical-align. The default behaviour of inline-flex or inline-grid does what we want.

A drawback here is that every element that has this behaviour applied will have the :hover effect, even if it fits perfectly well within its container. Maybe Container Queries will allow addressing this problem. In the meantime, styling the hover state so that it looks good in both cases is advisable.

We still haven't addressed the issue with keyboard and touchscreen users. We need to make the elements focusable, but there is currently no way to make this happen with CSS (and probably there won't be for a while). The way to do this is to add the tabindex="0" attribute to every relevant element.

<span tabindex="0">This is some content, a bit long</span>

We use the value of 0 to allow the browser to keep the tabbing order in accordance with source order. Now we just need to add a selector to the rule targeting the wrapper so it triggers also on focus.

.container:focus-within > span,
.container:hover > span
{
/* … */
}

The final result is focusable both via keyboard navigation and touch interface. If you're using a mouse, try clicking this paragraph of text and then tabbing into the elements below.

This is some content
This is some content, a bit long
This fits

There's a bonus for mouse users, too: since focus remains after clicking, you can click-to-focus and then move the cursor freely without losing the "tooltip".

So, should you use this "Reveal text-overflow: ellipsis" technique? Probably not. In most cases the right solution is to reconsider the design and find a better way to surface the relevant content. Move what's not relevant into a different component or page. But if you're already using ellipsis in some minor places, this technique might offer some improvement.

The one scenario where it can make sense to use this technique is in a table with high variability of cell content size. The example below shows this — and if you look at it in a phone screen you'll also see why this is not a good overall solution to making your content responsive. It can help at certain breakpoints, though.

First name
Last name
Role
Company
City
Country
IP Address
Department
Cristine
Polding
Supervisor
Beer-Cruickshank
Smolyaninovo
Russia
184.97.171.254
Services
Tito
O' Mara
Engineer
Ryan Inc
Essang
Indonesia
185.88.223.177
Training
Sheffie
Hellwig
Estimator
Bergstrom-Donnelly
Myshkin
Russia
84.148.213.10
Accounting
Ree
Whines
Estimator
Nader Group
Solna
Sweden
40.171.71.148
Services
Fionnula
Fibbings
Architect
Parker-Ankunding
Fukumitsu
Japan
236.94.63.183
Accounting
Gaby
Caldairou
Architect
Harber-Kessler
Borne Sulinowo
Poland
137.119.243.204
Support
Sawyer
Ocheltree
Construction Expeditor
Powlowski-Littel
Xinghua
China
10.24.67.242
Sales
Aurore
Crimin
Surveyor
Schulist-Stiedemann
Sever do Vouga
Portugal
161.155.137.252
Business Development
Gregoor
Thonger
Engineer
McGlynn, Schulist and Gutkowski
Lawrenceville
United States
207.154.165.2
Engineering
Ronnie
Dockwray
Electrician
Considine, Satterfield and Murray
Seshcha
Russia
238.107.64.105
Services

Mock data from Mockaroo