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

Playground Link →

<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

Playground Link →

<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.

Playground Link →

<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

Playground Link →

<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.

Playground Link →

<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.

Playground Link →

<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.

Playground Link →

<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 fieldsets 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.

Playground Link →

<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!