求助:实现带横向滚动、固定列与固定表头的无JS表格
问题:实现带固定表头、固定首列的横向滚动表格(纯CSS)
我想做一个宽表格,需要满足三个要求:
- 支持横向滚动
- 左侧首列固定不随横向滚动移动
- 顶部表头在页面向下滚动时固定在屏幕顶部
我不确定这几个需求能不能兼容,试了几种方法后写出了下面的代码,现在的问题是表头无法和表格主体同步横向滚动。可以用div或者table元素实现,希望完全不用JavaScript。
我当前的代码
CSS
body { background: #F5F7FA; overflow-x: hidden; } .wrap { position: relative; margin: 10em auto 30em; max-width: 960px; overscroll-behavior: contain; } .headers { top: 0; position: -webkit-sticky; position: sticky; z-index: 1; } .tracks, .scroller { display: flex; overflow-y: hidden; -webkit-overflow-scrolling: touch; } .scroller { overflow-x: hidden; } .tracks { overflow: auto; scroll-snap-type: x mandatory; } .scenes::-webkit-scrollbar, .scroller::-webkit-scrollbar { display: none; } .track { flex: 1 0 calc(22% + 2px); scroll-snap-align: start; } .track.first { position: sticky; left: 0; } .sticky { position: sticky; top: 0; } .track + .track { margin-left: -1px; } .heading { height: 50px; display: flex; justify-content: center; align-items: center; position: -webkit-sticky; position: sticky; top: 0; border: solid #fff; border-width: 0 1px; z-index: 1; background: #efefef; font-weight: 700; } .entry { border: 1px solid #ebebeb; border-top: 0; background: #fff; height: 8em; padding: 1em; } @media (max-width: 767px) { .track { flex: 1 0 calc(50% + 7px); } }
HTML
<div class="wrap"> <div class="headers"> <div class="scroller"> <div class="track"> <div class="heading">Heading 1</div> </div> <div class="track"> <div class="heading">Heading 2</div> </div> <div class="track"> <div class="heading">Heading 3</div> </div> <div class="track"> <div class="heading">Heading 4</div> </div> <div class="track"> <div class="heading">Heading 5</div> </div> </div> </div> <div class="tracks"> <div class="track first"> <div class="entry"> <h3>Lorem, ipsum dolor.</h3> </div> <div class="entry"> <h3>Lorem, ipsum.</h3> </div> </div> <div class="track"> <div class="entry"> <h3>Lorem, ipsum dolor.</h3> </div> <div class="entry"> <h3>Lorem, ipsum.</h3> </div> </div> <div class="track"> <div class="entry"> <h3>Lorem, ipsum dolor.</h3> </div> <div class="entry"> <h3>Lorem, ipsum.</h3> </div> </div> <div class="track"> <div class="entry"> <h3>Lorem, ipsum dolor.</h3> </div> <div class="entry"> <h3>Lorem, ipsum.</h3> </div> </div> <div class="track"> <div class="entry"> <h3>Lorem, ipsum dolor.</h3> </div> <div class="entry"> <h3>Lorem, ipsum.</h3> </div> </div> </div> </div>
效果示意图

需求选项
- 选项1:修复现有代码,让表头随表格其余部分同步横向滚动
- 选项2:换一种纯CSS实现方案达成相同效果
解决方案
问题根源
你当前代码的核心问题是表头容器.scroller和表格主体容器.tracks是两个独立元素,没有共享同一个滚动上下文,导致横向滚动无法同步。
纯CSS解决方案(使用table元素,推荐)
用原生table结合CSS sticky属性可以完美实现所有需求,语义化更好且无需JavaScript:
/* 基础重置 */ * { margin: 0; padding: 0; box-sizing: border-box; } body { background: #F5F7FA; padding: 10em 0 30em; } /* 滚动容器 */ .table-container { max-width: 960px; margin: 0 auto; overflow-x: auto; position: relative; } /* 表格样式 */ .sticky-table { width: max-content; border-collapse: separate; border-spacing: 0; } /* 表头固定 */ .sticky-table th { position: sticky; top: 0; background: #efefef; border: 1px solid #fff; height: 50px; padding: 0 1em; font-weight: 700; } /* 首列固定 */ .sticky-table th:first-child, .sticky-table td:first-child { position: sticky; left: 0; z-index: 2; } /* 首列单元格背景调整 */ .sticky-table th:first-child { background: #efefef; } .sticky-table td:first-child { background: #fff; border-right: 1px solid #ebebeb; } /* 表格内容单元格 */ .sticky-table td { border: 1px solid #ebebeb; border-top: none; padding: 1em; width: 220px; height: 8em; } /* 隐藏滚动条(可选) */ .table-container::-webkit-scrollbar { display: none; } /* 移动端适配 */ @media (max-width: 767px) { .sticky-table td { width: 50%; } }
<div class="table-container"> <table class="sticky-table"> <thead> <tr> <th>Heading 1</th> <th>Heading 2</th> <th>Heading 3</th> <th>Heading 4</th> <th>Heading 5</th> </tr> </thead> <tbody> <tr> <td>Lorem, ipsum dolor.</td> <td>Lorem, ipsum dolor.</td> <td>Lorem, ipsum dolor.</td> <td>Lorem, ipsum dolor.</td> <td>Lorem, ipsum dolor.</td> </tr> <tr> <td>Lorem, ipsum.</td> <td>Lorem, ipsum.</td> <td>Lorem, ipsum.</td> <td>Lorem, ipsum.</td> <td>Lorem, ipsum.</td> </tr> </tbody> </table> </div>
方案说明
- 横向滚动:外层
table-container设置overflow-x: auto,表格设置width: max-content,超出容器宽度时自动触发横向滚动。 - 表头固定:给所有
<th>设置position: sticky; top: 0,页面向下滚动时表头会固定在屏幕顶部。 - 首列固定:给首列的
<th>和<td>设置position: sticky; left: 0,并通过z-index确保首列不会被其他列覆盖。 - 完全基于CSS实现,无需JavaScript,兼容所有现代浏览器。
内容的提问来源于stack exchange,提问作者Radim Němeček
相关产品推荐
相关产品推荐

