HTML word wrap in a table

A table sizes its columns from the widest cell in each. Until you set table-layout to fixed, wrapping rules on the cells have little effect.

HTML word wrap in a table does not work the way it does elsewhere, because a table sizes its columns from their content before any wrapping rule is considered.

A table where one column of long paths has pushed every other column narrow.
A table where one column of long paths has pushed every other column narrow.

The default is table-layout: auto. The browser reads every cell, finds the widest content in each column, and allocates width accordingly.

So a single long file path in row 40 decides the width of that column, and squeezes everything else.

The fix is two declarations

table { table-layout: fixed; width: 100%; }

fixed tells the browser to stop measuring content. Column widths come from the first row, or from a <colgroup>, and cells wrap to fit.

Now the wrapping rules you write on cells actually apply.

Declaring column widths properly

Put the widths in a colgroup rather than on individual cells. It keeps the sizing in one place and is read before any row.

<table>
  <colgroup>
    <col style="width: 18%">
    <col style="width: 46%">
    <col style="width: 18%">
    <col style="width: 18%">
  </colgroup>
  <thead>
    <tr><th>File</th><th>Note</th><th>Owner</th><th>Updated</th></tr>
  </thead>
  <tbody>
    <tr><td>report.html</td><td>Rebuilt after the schema change</td><td>Sam</td><td>2026-09-16</td></tr>
  </tbody>
</table>

Percentages keep the table usable at any width. Pixel widths plus table-layout: fixed produce a table that overflows on a phone.

The same table with fixed layout and declared widths. The note column wraps to three lines.
The same table with fixed layout and declared widths. The note column wraps to three lines.

Wrapping rules per column

Once the layout is fixed, decide per column what should happen to content that does not fit.

Column type Rule Result
Descriptions, notes overflow-wrap: anywhere Wraps, including long URLs
File paths, ids nowrap + text-overflow: ellipsis One line, cut off with a title
Dates, amounts white-space: nowrap Never splits across lines
Code snippets white-space: pre-wrap Keeps spacing, still wraps
Dense hashes in a narrow column word-break: break-all Fills the column, breaks anywhere

The CSS:

td.note { overflow-wrap: anywhere; }
td.path {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
td.date { white-space: nowrap; }

text-overflow: ellipsis needs overflow: hidden and white-space: nowrap alongside it. Any one alone does nothing.

When you truncate, keep the value recoverable:

<td class="path" title="/var/log/application/error.log">/var/log/application/error.log</td>

The title shows on hover and is read by assistive technology. Without it the truncated value is simply lost.

Dates and numbers that should never split

A date breaking across two lines reads as two separate values. So does a currency amount split after the symbol.

white-space: nowrap on those columns costs nothing and removes a recurring irritation. It is one of the few places where turning wrapping off is the right choice.

For a value with an internal space you want to keep together, a non breaking space in the markup works too. 12&nbsp;GB will not split.

Wide tables on narrow screens

A table with seven columns is not going to fit a phone, and no wrapping rule changes that.

Contain the overflow rather than letting it stretch the page:

.table-scroll { overflow-x: auto; }
<div class="table-scroll">
  <table> ... </table>
</div>

The table scrolls sideways inside its own box and the surrounding page stays the width of the screen. Without this the whole layout gains a horizontal scrollbar, which is the symptom described in HTML text not wrapping.

Consider also which columns a phone reader needs. Hiding two of seven in a narrow media query often beats scrolling.

A table inside a scrolling container on a narrow viewport, with the page itself not scrolling sideways.
A table inside a scrolling container on a narrow viewport, with the page itself not scrolling sideways.

Why the first row matters under fixed layout

Under table-layout: fixed the browser reads widths from the colgroup if there is one, and otherwise from the cells of the first row only.

Every later row is laid out to those widths, whatever it contains. That is what makes the layout predictable.

It also means a width set on a cell in row five is ignored entirely. If a column is the wrong size, look at the colgroup or the first row, not the cell you were staring at.

/* has no effect under fixed layout */
tbody tr:nth-child(5) td:first-child { width: 300px; }

A second consequence: a header row hidden with display: none on a narrow screen takes its widths with it. Hide the header text, not the row.

Content that still overflows the cell

Fixed layout constrains the column, and it does not force the content inside to cooperate. An image or a <pre> block wider than the column will still spill.

td img { max-width: 100%; height: auto; }
td pre { white-space: pre-wrap; overflow-wrap: anywhere; }

Both are worth setting once for every table rather than per case. They are the table equivalent of the flex min-width: 0 rule.

Header cells

Headers are usually short labels, and a header wrapping to two lines while its neighbours do not makes a ragged row.

Set a consistent alignment and let them wrap rather than forcing nowrap, which reintroduces the width problem you just fixed.

th { vertical-align: bottom; text-align: left; overflow-wrap: anywhere; }

Checklist

  1. table-layout: fixed and width: 100% on the table.
  2. Widths declared in a colgroup, in percentages.
  3. A wrapping rule chosen per column rather than globally.
  4. Truncated cells carry a title with the full value.
  5. Dates and amounts set to nowrap.
  6. The table wrapped in an overflow-x: auto container.

HTML word break compares the wrapping properties in more detail, including when break-all is the right choice.

Editing and sending the table

Tables are the thing people most often need to correct after sending. A number changes and the file has to be rebuilt and resent.

Paste the table into a NOS document and it renders as written at an address of its own, with the text clickable so a value can be corrected in place.

Turning HTML into a link is that step, and the link you already sent points at the corrected version.

If the table needs to stay editable by other people, editable HTML tables and table to link cover that path.

Questions people ask

Why does my table ignore word-wrap in cells?

The default table-layout is auto, which measures the content and sizes each column to fit it. Wrapping rules cannot make a column narrower than the algorithm decided. Set table-layout: fixed and give the columns widths, then the wrapping rules apply.

How do I set column widths reliably?

Use a colgroup with a col element per column and a width on each, together with table-layout: fixed. Widths on individual cells are inconsistent, because only the first row is consulted under fixed layout.

Should long values wrap or be cut off?

Wrap anything a reader needs to read, such as descriptions and notes. Truncate values they only scan, such as file paths and identifiers, and put the full value in a title attribute.

How do wide tables behave on a phone?

Badly, unless you plan for it. Wrap the table in a container with overflow-x: auto so it scrolls sideways inside the page instead of stretching the whole layout.

Keep reading