You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于表格宽度按百分比设置td与th的宽度?固定表头滚动表格列宽失效及自动适配列数解决方案

Fixed Header Table with Scrollable Tbody: Column Width Issues & Dynamic Column Auto-Resize

Problem Description

I've implemented a table with a fixed header and scrollable tbody, but setting width: 50% on <th> and <td> isn't working as expected. Here's my code:

<div id="wrapper"> 
 <table> 
 <thead> 
 <tr> 
 <th>column1</th> 
 <th>column2</th> 
 </tr> 
 </thead> 
 <tbody> 
 <tr> 
 <td>row1</td> 
 <td>row1</td> 
 </tr> 
 <tr> 
 <td>row2</td> 
 <td>row2</td> 
 </tr> 
 <tr> 
 <td>row3</td> 
 <td>row3</td> 
 </tr> 
 <tr> 
 <td>row4</td> 
 <td>row4</td> 
 </tr> 
 </tbody> 
 </table> 
</div>
#wrapper { width: 100%; } 
table { border: 1px solid black; width: 100%; table-layout: fixed; } 
th, td { width: 50%; border: 1px solid black; } 
thead > tr { position: relative; display: block; } 
tbody { display: block; height: 80px; overflow: auto; } 

Two questions:

  1. Why isn't the 50% column width taking effect?
  2. How can I make columns automatically divide the table width evenly if I add a 3rd (or more) columns later?

Answers

1. Why the 50% width isn't working

The core problem is that you’ve set <thead> tr and <tbody> to display: block. This breaks the table’s native layout system—tables depend on their internal elements (thead, tbody, tr, th, td) using their default table-specific display values (like table-header-group, table-row) to keep columns aligned and widths synchronized.

When you switch these elements to block, the <th> and <td> lose their connection to the unified table column structure. Their width: 50% now calculates relative to their immediate block parent (either <thead> or <tbody>) instead of the full table width, and there’s no mechanism left to keep header and body columns matched.

2. Fixed header + dynamic equal-width columns solution

Instead of using display: block to force scrolling, use position: sticky on the table headers. This preserves the table’s native layout, so column widths will automatically sync and adjust as you add more columns. Here’s the revised code:

CSS:

#wrapper { width: 100%; }
table {
  border: 1px solid black;
  width: 100%;
  table-layout: fixed; /* Guarantees equal column widths */
  border-collapse: collapse; /* Optional: cleans up border spacing */
}
th, td {
  border: 1px solid black;
  padding: 8px; /* Optional: adds padding for readability */
}
th {
  position: sticky;
  top: 0;
  background: white; /* Prevents scrollable content from showing through the header */
}
tbody {
  display: block; /* Keeps tbody scrollable */
  height: 80px;
  overflow-y: auto;
}
tbody tr {
  display: table; /* Resets row to table layout to match header columns */
  width: 100%;
  table-layout: fixed; /* Matches the main table's layout rule */
}

HTML: (works with any number of columns)

<div id="wrapper"> 
 <table> 
 <thead> 
 <tr> 
 <th>column1</th> 
 <th>column2</th>
 <th>column3</th> <!-- Add/remove columns here as needed -->
 </tr> 
 </thead> 
 <tbody> 
 <tr> 
 <td>row1</td> 
 <td>row1</td>
 <td>row1</td>
 </tr> 
 <tr> 
 <td>row2</td> 
 <td>row2</td>
 <td>row2</td>
 </tr> 
 <!-- More rows -->
 </tbody> 
 </table> 
</div>

Key details about this approach:

  • position: sticky on <th> locks the header at the top while scrolling the tbody, no hacks needed.
  • table-layout: fixed on the main table ensures columns automatically split the full table width evenly—no need to set explicit percentages for each column.
  • We keep tbody as display: block for scrolling, but reset <tbody tr> to display: table to maintain alignment with the header columns.
  • Adding a white background to <th> prevents scrollable content from peeking through the fixed header.

内容的提问来源于stack exchange,提问作者peckoski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 10:24:10