HTML Table Overflow Issues

A simple CSS technique to keep HTML tables within their containers by controlling table layout and text wrapping.

“Blog CSS Style Fixes” Part Ⅱ, documenting some common blog styling problems and their solutions.

  1. Fix Markdown Footnote Jump Overlap with CSS scroll-margin-top
  2. Fix HTML Tables from Becoming Too Wide

Problem

On narrow screens such as mobile devices or sidebars, screen space is very limited.

By default, when a cell contains long unbreakable content (like a URL or a long snippet of code), the table ignores its parent container’s width constraint and forces the container to expand, producing an unexpected horizontal scrollbar.

CSS Tricks 🎪

In the examples below, the table sits inside a .page container that is only 150px wide, and the table content is a long URL (about 170px wide), to show how different layouts behave. The applied CSS:

.page {  width: 150px;  border: solid 2px var(--mauve);  margin: 1em auto;  table {    font-size: 1em;    width: 100%;    th, td {      padding: 1em;    }  }}

Auto Layout & Word Break

First up is the default automatic layout, i.e. table { table-layout: auto }. The browser adjusts column widths based on content[1]. For this 2*1 table, the column width is determined by https://gallery.vluv.space in the second row, about 170px, so the table simply overflows its parent container.

Gallery Link
https://gallery.vluv.space

A simple workaround: set word-break[2] to break-all. The URL, even though it is one long word, will then wrap across lines instead of stretching the table.

OK, change the table tag to <table style="word-break: break-all" data-nowrap="true">, and it looks like this:

Gallery Link
https://gallery.vluv.space

However, if we shrink the .page container further to 40px and bump the font size up to 2em, the table still overflows the container. This scenario is rare, though. One plausible example: viewing a table with many columns on a phone.

G

Fixed Layout?

For tables overflowing their container, the classic StackOverflow answer is to set table-layout: fixed on the table, together with width: 100% (the parent container’s width).

With table-layout: fixed, the table strictly honors width: 100% (the parent container’s width).

Gallery Link
https://gallery.vluv.space

But in my view this works about the same as auto + word-break: all. See the result below: a single character still cannot fit within 40px, and the table still overflows the container.

G

Also, if you don’t specify column widths, table-layout: fixed makes all columns equally wide. To get a more balanced layout, you have to carefully assign widths to each column, which is inconvenient in practice.

In the fixed table layout algorithm, the width of each column is determined in this priority:

  1. A column element (<col>) with explicit width.
  2. A cell in the first row with explicit width.
  3. Otherwise, the shared remaining horizontal space.

1. table-layout: fixed

1UserThis is a very long description text; in fixed mode it gets squeezed to the same width as the index column.

2. table-layout: auto

1UserThis is a very long description text; in auto mode it automatically takes up most of the remaining space.

JavaScript Solution

The default layout with all-break prevents overflow, but in some cases (showing code snippets, URLs) the forced line breaks look ugly.

As mentioned earlier, a table can stretch its container and trigger a horizontal scrollbar. While scrolling the table, everything else in the container (headings, buttons, text) scrolls left along with it, hurting readability.

The fix is fairly simple: wrap the table in its own container, and when the table exceeds that container’s width, let the wrapper get the horizontal scrollbar instead.

document.querySelectorAll(".content table").forEach((table) => {  if (table.hasAttribute("data-nowrap") || table.parentElement.classList.contains('table-wrapper')) {    return;  }  // if width exceeds container, wrap it  const wrapper = document.createElement("div");  Object.assign(wrapper.style, {    width: "100%",    overflowX: "auto",  });  table.parentNode.insertBefore(wrapper, table);  wrapper.appendChild(table);});
Gallery Link
https://gallery.vluv.space
G

  1. The automatic table layout algorithm is used. The widths of the table and its cells are adjusted to fit the content. Most browsers use this algorithm by default. ↩︎

  2. The word-break CSS property sets whether line breaks appear wherever the text would otherwise overflow its content box. word-break - CSS | MDN ↩︎