Truncation, Flexbox, and Tables
Truncation
When you have a long string of text that you want to restrict to one line, but not let it grow forever and ever, you have to truncate it. Truncating text can be a nightmare. The standard way of truncating text is with a CSS component like this:
.truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
Then you just have to apply it to an element with text.
It Just Works
<div class="max-w-md flex gap-16 w-full mx-auto justify-center">
<p class="truncate">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse sodales
elit quis vulputate pretium. In hac habitasse platea dictumst. Praesent
scelerisque dolor sit amet volutpat aliquam. Phasellus ultrices sollicitudin
metus. Cras sit amet sem nibh. Pellentesque lacinia enim eget lacinia
dignissim. Donec iaculis fringilla suscipit. Phasellus non lobortis quam. Ut
rutrum ex eu suscipit dignissim. Fusce elementum rutrum risus sit amet
posuere. Sed ac sollicitudin arcu. Mauris interdum lorem sed mi sodales
placerat.
</p>
</div>
This just works. All you need is the .truncate
class and for the parent of the text block to have a width or max-width. The browser takes care of everything. This starts to break a little when you’re using flexbox though.
Flexbox Fail
<div class="max-w-md flex gap-16 w-full mx-auto justify-center">
<div>
<p class="truncate">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse
sodales elit quis vulputate pretium. In hac habitasse platea dictumst.
Praesent scelerisque dolor sit amet volutpat aliquam. Phasellus ultrices
sollicitudin metus. Cras sit amet sem nibh. Pellentesque lacinia enim eget
lacinia dignissim. Donec iaculis fringilla suscipit. Phasellus non
lobortis quam. Ut rutrum ex eu suscipit dignissim. Fusce elementum rutrum
risus sit amet posuere. Sed ac sollicitudin arcu. Mauris interdum lorem
sed mi sodales placerat.
</p>
</div>
</div>
Min-Width Trick
If the text you’re trying to truncate is inside a flex child, the truncate trick won’t work. The way around this is to apply min-width: 0px
to the flex child.
<div class="max-w-md flex gap-16 w-full mx-auto justify-center">
<div class="min-w-0">
<p class="truncate">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse
sodales elit quis vulputate pretium. In hac habitasse platea dictumst.
Praesent scelerisque dolor sit amet volutpat aliquam. Phasellus ultrices
sollicitudin metus. Cras sit amet sem nibh. Pellentesque lacinia enim eget
lacinia dignissim. Donec iaculis fringilla suscipit. Phasellus non
lobortis quam. Ut rutrum ex eu suscipit dignissim. Fusce elementum rutrum
risus sit amet posuere. Sed ac sollicitudin arcu. Mauris interdum lorem
sed mi sodales placerat.
</p>
</div>
</div>
Tables
The above methods should let you truncate text in every situation, except tables. Because…tables.
The Problem with Tables
<table>
<thead>
<tr>
<th class="p-2 text-left">Flexible Width</th>
<th class="p-2 text-left">Short Width</th>
</tr>
</thead>
<tbody>
<tr>
<td class="p-2 truncate">
Bacon ipsum dolor amet meatball ground round chicken, hamburger cupim
sirloin doner burgdoggen porchetta capicola kevin ham.
</td>
<td class="p-2">
<div class="flex items-center gap-4">
<button class="bg-blue-600 text-white rounded-md shadow py-1 px-3">
Button
</button>
<button class="bg-blue-600 text-white rounded-md shadow py-1 px-3">
Button
</button>
</div>
</td>
</tr>
</tbody>
</table>
The problem you’ll run into with tables is that when you have a td
, it has no real width. It just takes up the space it’s given. If you apply our .truncate
class, the text in the cell will explode outside of the td
. You can give it a width or give it a max-width, and it works, but you lose the flexible sizing the browser gives you by default.
<table>
<thead>
<tr>
<th class="p-2 text-left">Flexible Width</th>
<th class="p-2 text-left">Short Width</th>
</tr>
</thead>
<tbody>
<tr>
<td class="p-2 max-w-sm truncate">
Bacon ipsum dolor amet meatball ground round chicken, hamburger cupim
sirloin doner burgdoggen porchetta capicola kevin ham.
</td>
<td class="p-2">
<div class="flex items-center gap-4">
<button class="bg-blue-600 text-white rounded-md shadow py-1 px-3">
Button
</button>
<button class="bg-blue-600 text-white rounded-md shadow py-1 px-3">
Button
</button>
</div>
</td>
</tr>
</tbody>
</table>
The Table Cell Fix
The fix for table cells without a width/max-width is not that difficult to implement, but there’s a trick to making it flexible. You need to make the td
a flex container, wrap your content in a div
that has flex: 1 1 0%
and width: 0px
set, and then add your content inside with our .truncate
class. The flex settings might make sense, but the width is weird. You need to tell the width to be 0px
so that it will be as small as possible, but can flex as large as there is space available.
<table class="min-w-full w-full">
<thead>
<tr>
<th class="p-2 text-left">Flexible Width</th>
<th class="p-2 w-0 text-left">Short Width</th>
</tr>
</thead>
<tbody>
<tr>
<td class="mt-1.5 p-2 flex">
<div class="flex-1 w-0 truncate">
Bacon ipsum dolor amet meatball ground round chicken, hamburger cupim
sirloin doner burgdoggen porchetta capicola kevin ham.
</div>
</td>
<td class="p-2">
<div class="flex items-center gap-4">
<button class="bg-blue-600 text-white rounded-md shadow py-1 px-3">
Button
</button>
<button class="bg-blue-600 text-white rounded-md shadow py-1 px-3">
Button
</button>
</div>
</td>
</tr>
</tbody>
</table>
There’s a slight problem with this method. Table cells do not want to be flex containers. They lose their default vertical alignment. They do not know how tall the row they are in is, so you cannot make them fill the tr
’s height. You have to add margin-top
by sight to make the td
’s content vertically centered. It’s not great, but it is the best you can do.
And One More Thing…
If for some reason you have a fieldset
inside your new truncate/flex combo, it will not work.
<td class="mt-1.5 p-2 flex">
<div class="flex-1 w-0">
<fieldset class="">
<span class="block truncate">
Bacon ipsum dolor amet meatball ground round chicken, hamburger cupim
sirloin doner burgdoggen porchetta capicola kevin ham.
</span>
</fieldset>
</div>
</td>
The problem is fieldset
s do not behave like other normal elements. You can make it work though. The trick is making the fieldset
be min-width: 0px
. This will trick the fieldset
into shrinking like other elements can because a fieldset
has a standard min-width
of whatever its content is.
<td class="mt-1.5 p-2 flex">
<div class="flex-1 w-0">
<fieldset class="min-w-0">
<span class="block truncate">
Bacon ipsum dolor amet meatball ground round chicken, hamburger cupim
sirloin doner burgdoggen porchetta capicola kevin ham.
</span>
</fieldset>
</div>
</td>
Truncation is a necessary tool for many UIs. Hopefully, if you find yourself needing it in a table, you’ll be able to handle it without any problem in the future!