··

HTML Table Overflow Issues

Discover a simple CSS technique to keep HTML tables within their containers by controlling layout and text wrapping.
跳至正文

「Blog CSS 样式修缮」 Part Ⅱ,记录一些常见的博客样式问题及其解决方案。

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

Problem

在移动端或侧边栏等窄屏场景下,屏幕空间非常有限。

默认情况下,当单元格内包含不可换行的长内容(如 URL 链接、长代码)时,表格会忽略父容器的宽度限制,强制撑大容器,导致出现意外的横向滚动条。

CSS Tricks 🎪

下面的示例中,会将表格放置在一个宽度仅为 150px 的.page容器内,表格内容为一个长 URL 链接(约170px宽),以展示不同布局下的表现。应用的 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

首先展示的是默认的自动布局,即table { table-layout: auto }。浏览器会根据内容自动调整列宽[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*1表格来说,列宽由第二行的https://gallery.vluv.space决定,约为170px,因此表格宽度直接溢出父容器。

Gallery Link
https://gallery.vluv.space

一个简单的wordaround,设置word-break[2]The word-break CSS property sets whether line breaks appear wherever the text would otherwise overflow its content box. word-break - CSS | MDN为 break-all,这样URL链接虽然作为一整个单词,但也会进行换行处理,避免撑大表格宽度。

Ok,将表格标签改为<table style="word-break: break-all" data-nowrap="true">,效果如下:

Gallery Link
https://gallery.vluv.space

但是,如果将.page容器宽度进一步缩小到40px,同时把字体大小调大到2em,那么表格依然会溢出容器宽度;不过这种场景也不多见,一个可能的例子是:在手机端查看一个列数非常多的表格

G

Fixed Layout?

对于table溢出容器的问题,StackOverflow 上的经典方案是为表格设置 table-layout: fixed ,同时设置 width: 100%(即父容器宽度)

使用 table-layout: fixed 后,表格严格遵循 width: 100%(即父容器宽度)

Gallery Link
https://gallery.vluv.space

但这个方案的效果,我认为与auto + word-break: all类似,参考下面的效果,单个字符依然无法在40px宽度内完整显示,表格依然溢出容器宽度。

G

此外,如果没为各列指定宽度,table-layout: fixed 会使各列等宽,要得到更协调的布局,那么就得费心为各列指定宽度,这在实际应用中并不方便。

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

1User这是一段非常长的描述文本,在Fixed模式下会被强制压缩到和序号列一样宽。

2. table-layout: auto

1User这是一段非常长的描述文本,在Auto模式下会自动占据剩余的绝大部分空间。

JavaScript Solution

前面用默认布局配置 all-break 可以防止溢出,但在某些场景下(例如展示代码片段、URL),强制换行看起来并不美观。

前面提到表格撑大容器,出现横向滚动条。在滚动查看表格时,容器内的其他内容(标题、按钮、文字)也会跟着一起向左滚动,影响阅读体验。

解决办法也比较简单:为表格单独包一层容器,当表格宽度超出该容器时,容器出现横向滚动条即可。

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 ↩︎