HTML 表格 – 使用 CSS 冻结行和列
在 HTML 表格上实现冻结窗格效果。
引言
本文展示了一种仅使用 CSS 冻结 HTML 表格的列和行的方法,无需 JavaScript 或 JQuery。
背景
我要感谢 Manish Malviya 分享他在这篇博文中关于冻结表格行和列的知识。
以下工作灵感来自他的文章。
Youtube 教程视频演示
示例
示例 1:如 Youtube 教程视频所示
示例 2:固定宽度和高度
示例 3:响应式宽度和高度(通过使用视口调整)
Using the Code
让我们以一个简单的 HTML 表格为例
<div class="div1">
<table>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
<th>Column 4</th>
<th>Column 5</th>
<th>Column 6</th>
</tr>
<tr>
<td>Row Data 1</td>
<td>Row Data 2</td>
<td>Row Data 3</td>
<td>Row Data 4</td>
<td>Row Data 5</td>
<td>Row Data 6</td>
</tr>
<tr>
<td>Row Data 1</td>
<td>Row Data 2</td>
<td>Row Data 3</td>
<td>Row Data 4</td>
<td>Row Data 5</td>
<td>Row Data 6</td>
</tr>
<tr>
<td>Row Data 1</td>
<td>Row Data 2</td>
<td>Row Data 3</td>
<td>Row Data 4</td>
<td>Row Data 5</td>
<td>Row Data 6</td>
</tr>
</table>
</div>
这是实现魔法的 CSS
.div1 { width: 600px; height: 400px; overflow: scroll; border: 1px solid #777777; } .div1 table { border-spacing: 0; } .div1 th { border-left: none; border-right: 1px solid #bbbbbb; padding: 5px; width: 80px; min-width: 80px; position: sticky; top: 0; background: #727272; color: #e0e0e0; font-weight: normal; } .div1 td { border-left: none; border-right: 1px solid #bbbbbb; border-bottom: 1px solid #bbbbbb; padding: 5px; width: 80px; min-width: 80px; } .div1 th:nth-child(1), .div1 td:nth-child(1) { position: sticky; left: 0; width: 150px; min-width: 150px; } .div1 th:nth-child(2), .div1 td:nth-child(2) { position: sticky; /* 1st cell left/right padding + 1st cell width + 1st cell left/right border width */ /* 0 + 5 + 150 + 5 + 1 */ left: 161px; width: 50px; min-width: 50px; } .div1 td:nth-child(1), .div1 td:nth-child(2) { background: #ffebb5; } .div1 th:nth-child(1), .div1 th:nth-child(2) { z-index: 2; }
解释
首先,使用 DIV
标签包含 TABLE
,提供固定的宽度和高度,将一个非常长和宽的 HTML 表格变成可滚动的表格。
.div1 {
width: 600px;
height: 400px;
overflow: scroll;
border: 1px solid #777777;
}
“overflow: scroll
”属性将使表格可滚动。
为了构建一个响应式表格,可以使用 CSS 函数 “CALC
” 来自动计算宽度,例如
.div1 {
height: calc(100vh - 250px);
width: calc(100vw - 100px);
overflow: scroll;
border: 1px solid #777777;
}
请注意,CALC
值之间需要空格。
例如,这是错误的
height: calc(100vh-250px);
这是正确的
height: calc(100vh - 250px);
“vh
” 或 “vw
” 是 “视口” 单位。
100vh
= 100% 可见高度,它类似于窗口大小,指的是可见区域。100vw
= 100% 可见宽度。
表格样式
.div1 table {
border-spacing: 0;
}
border-spacing: 0
,消除单元格之间的空白距离
请注意,在这种情况下不能使用 "border-collapse: collapse
" 属性。 这是因为边框线在使用 "position: sticky
" 时会表现不正确,我们将在下面讨论。
TH (标题) 样式
.div1 th {
border-left: none;
border-right: 1px solid #bbbbbb;
padding: 5px;
width: 80px;
min-width: 80px;
position: sticky;
top: 0;
background: #727272;
color: #e0e0e0;
font-weight: normal;
}
position: sticky
,这将使TH
单元格始终保持在顶部位置top: 0
,这告诉TH
单元格始终保持在从顶部测量的 位置 0(零)background
,如果没有背景颜色,底部的TD
单元格将会“撞”到TH
单元格,导致它们相互重叠width, min-width
:这用于固定列宽,如果没有这些属性,单元格列将会变形和压缩
这将冻结“标题”。
冻结第一列
.div1 th:nth-child(1),
.div1 td:nth-child(1) {
position: sticky;
left: 0;
width: 150px;
min-width: 150px;
}
nth-child(1)
表示每个“TR”块中的第一个元素。 指的是第一列。left: 0
告诉单元格从左侧“冻结”在位置零。
冻结第二列
.div1 th:nth-child(2), .div1 td:nth-child(2) { position: sticky; /* 1st cell left/right padding + 1st cell width + 1st cell left/right border width */ /* 0 + 5 + 150 + 5 + 1 */ left: 161px; width: 50px; min-width: 50px; }
下一个单元格位置的计算是:边框宽度 + 内边距 + 单元格宽度
在这种情况下,0 左边框宽度 + 5px 左内边距 + 150px (第一个单元格宽度) + 5px 右内边距) + 1px 右边框宽度 = 161px。
因此,left: 161px
接下来,当表格向右滚动时,非粘性单元格将撞到并覆盖第一和第二列冻结的单元格。
为第一和第二列冻结的单元格提供背景颜色以解决重叠问题
.div_maintb td:nth-child(1),
.div_maintb td:nth-child(2) {
background: #ffebb5;
}
现在,前两个冻结的 "TH
" 和 "TD
" 都是 "sticky"。 由于 "TD" 是在 "TH" 之后创建的,因此当表格向下滚动时,"TD
" 将保持在顶部并覆盖 "TH
",使 "TH
" 隐藏在 "TD
" 下面。
因此,我们可以设置 "TH
" 的 CSS 值 "z-index
" 以覆盖它的层,使其位于前面/顶部,以便 "TD
" 现在位于 "TH
" 之下/之后。
默认情况下,所有元素的默认值都是 "z-index=0
"。
.div1 th:nth-child(1),
.div1 th:nth-child(2) {
z-index: 2;
}