position: sticky 是现代浏览器固定表头最轻量可靠的方式,但需满足父容器有滚动上下文、tr 无 overflow: hidden、th 显式设置 background-color 和 z-index 三个条件;IE11 及以下需降级为分离表头+JS 同步列宽。
现代浏览器下,position: sticky 是最轻量、最可靠的方式,只要父容器有滚动上下文且 <th> 设置正确,一行 CSS 就能生效;旧版 IE(尤其是 IE11 及以下)不支持 sticky,必须降级处理。
position: sticky 固定 <th> 的前提条件它不是写上就灵——top: 0 要生效,必须满足三个硬性条件:
<table> 或其任意祖先容器需设置 max-height + overflow-y: auto(不能是 hidden 或 visible)<th> 的直接父元素(通常是 <tr>)不能有 overflow: hidden 等阻断粘性行为的样式<th> 必须显式设置 background-color 和 z-index(哪怕只是 z-index: 1),否则滚动时文字会被下方 <td> 盖住或透出底色推荐写法示例:
<div style="max-height: 400px; overflow-y: auto;"> <table style="width: 100%; border-collapse: collapse;"> <thead> <tr> <th style="position: sticky; top: 0; background: white; z-index: 10; border-bottom: 1px solid #ccc;">姓名</th> <th style="position: sticky; top: 0; background: white; z-index: 10; border-bottom: 1px solid #ccc;">城市</th> </tr> </thead> <tbody> <tr><td>张三</td><td>北京</td></tr> <tr><td>李四</td><td>上海</td></tr> </tbody> </table></div>
table-layout: fixed + 显式宽度是关键当内容长度差异大(比如一列全是短文本,另一列是长 URL),sticky 表头容易和下面数据列对不齐。这不是 bug,是表格默认 table-layout: auto 导致各列宽度随内容重算,而 <thead> 和 <tbody> 是两个独立渲染块。
立即学习“前端免费学习笔记(深入)”;
<table> 加 table-layout: fixed
<th> 和对应列的 <td> 设置相同 width 或 min-width(如 width: 20% 或 width: 150px)<td> 的 offsetWidth,再赋给对应 <th> 的 style.width
<thead> + 手动同步列宽IE 完全无视 position: sticky,强行加只会让表头消失或错位。务实做法是把表头抽出来,和表格本体拆成两个独立 <table>:
<div style="max-height: 400px; overflow-y: auto;"> 包裹数据表格<table>,放在数据表格上方table-layout: fixed,并用 JS 监听 window.resize 和 tbody.scroll,同步每列 offsetWidth
<th> 和 <td> 都加 width 内联样式,靠人工对齐真正麻烦的从来不是“怎么写”,而是“为什么写了没反应”——90% 的失败源于父容器没形成滚动上下文,或忘了设 background 和 z-index。IE 降级方案看着重,但比在生产环境里反复调试兼容性更省时间。