例1: 表头固定
- html
<div class="wrap">
<table>
<thead>
<tr>
<th>序号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>身高 (cm)</th>
<th>体重 (kg)</th>
</tr>
</thead>
<tbody>
<tr>
<td>01</td>
<td>德莱厄斯</td>
<td>31</td>
<td>男</td>
<td>180</td>
<td>80</td>
</tr>
<tr>
<td>02</td>
<td>安妮</td>
<td>14</td>
<td>女</td>
<td>150</td>
<td>35</td>
</tr>
<tr>
<td>03</td>
<td>阿狸</td>
<td>22</td>
<td>女</td>
<td>165</td>
<td>40</td>
</tr>
<tr>
<td>04</td>
<td>卢锡安</td>
<td>28</td>
<td>男</td>
<td>172</td>
<td>55</td>
</tr>
<tr>
<td>05</td>
<td>艾克</td>
<td>25</td>
<td>男</td>
<td>168</td>
<td>60</td>
</tr>
</tbody>
</table>
</div>
- css
table {
border-collapse: collapse;
text-align: center;
tr {
height: 0.44rem;
td,th {
width: 1rem;
border-right: 0.01rem solid rgba(81, 159, 241, 0.2);
}
th {
border-right: 0.01rem solid rgba(160, 216, 226, 0.5);
}
}
thead {
tr {
background: #519FF1;
font-size: 0.15rem;
color: #FFFFFF;
th {
font-weight: normal;
}
}
}
tbody {
height: 1.32rem;
overflow: auto;
tr:nth-child(odd) {
background: #FFFFFF;
}
tr:nth-child(even) {
background: #DCECFC;
}
}
}
例2: 首行首列固定
如图所示
上下滚动, 1 2固定; 左右滚动, 1 3固定
方法1 ★★☆☆☆
思路: 1 始终固定; 2 3 利用
position: sticky;
粘性布局
优点: 简单, HTML+CSS 即可实现
缺点: 内容折行会出现问题, 且兼容性不太友好 兼容性查看
- html
<div class="wrap">
<table>
<thead class="t1">
<!-- <tr> -->
<th>序号</th>
<!-- </tr> -->
</thead>
<thead class="t2">
<!-- <tr> -->
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>身高 (cm)</th>
<th>体重 (kg)</th>
<!-- </tr> -->
</thead>
<tbody class="t3">
<tr>
<td>01</td>
</tr>
<tr>
<td>02</td>
</tr>
<tr>
<td>03</td>
</tr>
<tr>
<td>04</td>
</tr>
<tr>
<td>05</td>
</tr>
<tr>
<td>06</td>
</tr>
<tr>
<td>07</td>
</tr>
</tbody>
<tbody class="t4">
<tr>
<td>德莱厄斯</td>
<td>31</td>
<td>男</td>
<td>180</td>
<td>80</td>
</tr>
<tr>
<td>安妮</td>
<td>14</td>
<td>女</td>
<td>150</td>
<td>35</td>
</tr>
<tr>
<td>阿狸</td>
<td>22</td>
<td>女</td>
<td>165</td>
<td>40</td>
</tr>
<tr>
<td>卢锡安</td>
<td>28</td>
<td>男</td>
<td>172</td>
<td>55</td>
</tr>
<tr>
<td>艾克</td>
<td>25</td>
<td>男</td>
<td>168</td>
<td>60</td>
</tr>
<tr>
<td>努努</td>
<td>8</td>
<td>男</td>
<td>30</td>
<td>20</td>
</tr>
<tr>
<td>提莫</td>
<td>11</td>
<td>女</td>
<td>40</td>
<td>20</td>
</tr>
</tbody>
</table>
</div>
- css
注: 如果是全屏滚动的话, 得先设置最最外层的 div 高度为 100%; 建议整体用 fixed布局, 否则可能出现问题
.wrap {
width: 100%;
height: 2.2rem;
overflow: scroll;
table {
position: relative;
border-collapse: collapse;
text-align: center;
td, th {
height: 0.44rem;
width: 1rem;
}
thead {
display: block;
width: 100%;
th {
font-weight: normal;
background: #519FF1;
font-size: 0.15rem;
color: #FFFFFF;
}
}
tbody {
width: 100%;
tr:nth-child(odd) {
background: #FFFFFF;
}
tr:nth-child(even) {
background: #DCECFC;
}
}
.t1 {
position: sticky;
width: 1rem;
z-index: 9;
float: left;
left: 0;
top: 0;
}
.t2 {
position: sticky;
width: 5rem;
top: 0;
margin-left: 1rem;
z-index: 8;
}
.t3 {
position: sticky;
width: 1rem;
left: 0;
float: left;
z-index: 8;
}
.t4 {
position: absolute;
width: 5rem;
left: 1rem;
z-index: 7;
}
}
}
方法2 ★★★☆☆
思路: 让 3 随着 4 上下移动; 2 随着 4 左右移动
优点: 兼容性好
缺点: 内容折行会出现问题
- vue
<template>
<div>
<div class="wrap">
<table>
<div class="table-left">
<thead class="t1">
<tr>
<th>序号</th>
</tr>
</thead>
<tbody class="t3">
<tr>
<td>01</td>
</tr>
<tr>
<td>02</td>
</tr>
<tr>
<td>03</td>
</tr>
<tr>
<td>04</td>
</tr>
<tr>
<td>05</td>
</tr>
<tr>
<td>06</td>
</tr>
<tr>
<td>07</td>
</tr>
</tbody>
</div>
<div class="table-right">
<thead class="t2">
<tr>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>身高 (cm)</th>
<th>体重 (kg)</th>
</tr>
</thead>
<tbody class="t4">
<tr>
<td>德莱厄斯</td>
<td>31</td>
<td>男</td>
<td>180</td>
<td>80</td>
</tr>
<tr>
<td>安妮</td>
<td>14</td>
<td>女</td>
<td>150</td>
<td>35</td>
</tr>
<tr>
<td>阿狸</td>
<td>22</td>
<td>女</td>
<td>165</td>
<td>40</td>
</tr>
<tr>
<td>卢锡安</td>
<td>28</td>
<td>男</td>
<td>172</td>
<td>55</td>
</tr>
<tr>
<td>艾克</td>
<td>25</td>
<td>男</td>
<td>168</td>
<td>60</td>
</tr>
<tr>
<td>努努</td>
<td>8</td>
<td>男</td>
<td>30</td>
<td>20</td>
</tr>
<tr>
<td>提莫</td>
<td>11</td>
<td>女</td>
<td>40</td>
<td>20</td>
</tr>
</tbody>
</div>
</table>
</div>
</div>
</template>
<script>
export default {
methods: {
// 监听滚动事件
tableScroll() {
let _t4 = document.getElementsByClassName("t4")[0];
let _t4_top = this.scrollTop;
// let _t4_teft = this.scrollLeft;
document.getElementsByClassName("t3")[0].scrollTop = _t4_top;
// document.getElementsByClassName("t2")[0].scrollLeft = _t4_teft;
}
},
mounted() {
window.addEventListener('scroll', this.tableScroll, true);
},
destroyed() {
window.removeEventListener('scroll', this.tableScroll);
}
}
</script>
<style scoped lang="less">
.wrap {
table {
width: 100%;
height: 2.2rem;
display: block;
overflow: hidden;
text-align: center;
border-collapse: collapse;
th, td {
width: 1rem;
height: 0.44rem;
}
thead {
th {
font-weight: normal;
background: #519FF1;
font-size: 0.15rem;
color: #FFFFFF;
}
}
tbody {
tr:nth-child(odd) {
background: #FFFFFF;
}
tr:nth-child(even) {
background: #DCECFC;
}
}
.table-left {
width: 25%;
float: left;
}
.table-right {
width: 75%;
float: left;
overflow: auto;
}
}
.t1 {
display: block;
width: 1rem;
}
.t2 {
display: block;
width: 5rem;
}
.t3 {
display: block;
width: 1rem;
height: 1.76rem;
overflow: hidden;
}
.t4 {
width: 5rem;
height: 1.76rem;
display: block;
overflow: auto;
}
}
</style>
方法3 ★★★★★
Element UI 受到的启发
思路: 两层 div 嵌套
优点: 兼容性好, 并且数据折行后高度灵活改变
缺点: 暂无
<template>
<div class="table">
<div class="table-header">
<table>
<thead>
<tr>
<th>
<div class="cell">日期</div>
</th>
<th>
<div class="cell">姓名</div>
</th>
<th>
<div class="cell">省份</div>
</th>
<th>
<div class="cell">市区</div>
</th>
<th>
<div class="cell">地址</div>
</th>
<th>
<div class="cell">邮编</div>
</th>
</tr>
</thead>
</table>
</div>
<div class="table-body">
<table>
<tbody>
<tr>
<td>
<div class="cell">1111</div>
</td>
<td>
<div class="cell">2222</div>
</td>
<td>
<div class="cell">3333</div>
</td>
<td>
<div class="cell">4444</div>
</td>
<td>
<div class="cell">5555</div>
</td>
<td>
<div class="cell">6666</div>
</td>
</tr>
<tr>
<td>
<div class="cell">1111</div>
</td>
<td>
<div class="cell">2222</div>
</td>
<td>
<div class="cell">3333</div>
</td>
<td>
<div class="cell">4444</div>
</td>
<td>
<div class="cell">5555</div>
</td>
<td>
<div class="cell">6666</div>
</td>
</tr>
<tr>
<td>
<div class="cell">1111</div>
</td>
<td>
<div class="cell">2222</div>
</td>
<td>
<div class="cell">3333</div>
</td>
<td>
<div class="cell">4444</div>
</td>
<td>
<div class="cell">5555</div>
</td>
<td>
<div class="cell">6666</div>
</td>
</tr>
<tr>
<td>
<div class="cell">1111</div>
</td>
<td>
<div class="cell">2222</div>
</td>
<td>
<div class="cell">3333</div>
</td>
<td>
<div class="cell">4444</div>
</td>
<td>
<div class="cell">5555</div>
</td>
<td>
<div class="cell">6666</div>
</td>
</tr>
<tr>
<td>
<div class="cell">1111</div>
</td>
<td>
<div class="cell">2222</div>
</td>
<td>
<div class="cell">3333</div>
</td>
<td>
<div class="cell">4444</div>
</td>
<td>
<div class="cell">5555</div>
</td>
<td>
<div class="cell">6666</div>
</td>
</tr>
<tr>
<td>
<div class="cell">1111</div>
</td>
<td>
<div class="cell">2222</div>
</td>
<td>
<div class="cell">3333</div>
</td>
<td>
<div class="cell">4444</div>
</td>
<td>
<div class="cell">5555</div>
</td>
<td>
<div class="cell">6666</div>
</td>
</tr>
<tr>
<td>
<div class="cell">1111</div>
</td>
<td>
<div class="cell">2222</div>
</td>
<td>
<div class="cell">3333</div>
</td>
<td>
<div class="cell">4444</div>
</td>
<td>
<div class="cell">5555</div>
</td>
<td>
<div class="cell">6666</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="table-fixed">
<div class="table-fixed-header">
<table>
<thead>
<tr>
<th>
<div class="cell">日期</div>
</th>
<th>
<div class="cell">姓名</div>
</th>
<th>
<div class="cell">省份</div>
</th>
<th>
<div class="cell">市区</div>
</th>
<th>
<div class="cell">地址</div>
</th>
<th>
<div class="cell">邮编</div>
</th>
</tr>
</thead>
</table>
</div>
<div class="table-fixed-body">
<table>
<tbody>
<tr>
<td>
<div class="cell">1111</div>
</td>
<td>
<div class="cell">2222</div>
</td>
<td>
<div class="cell">3333</div>
</td>
<td>
<div class="cell">4444</div>
</td>
<td>
<div class="cell">5555</div>
</td>
<td>
<div class="cell">6666</div>
</td>
</tr>
<tr>
<td>
<div class="cell">1111</div>
</td>
<td>
<div class="cell">2222</div>
</td>
<td>
<div class="cell">3333</div>
</td>
<td>
<div class="cell">4444</div>
</td>
<td>
<div class="cell">5555</div>
</td>
<td>
<div class="cell">6666</div>
</td>
</tr>
<tr>
<td>
<div class="cell">1111</div>
</td>
<td>
<div class="cell">2222</div>
</td>
<td>
<div class="cell">3333</div>
</td>
<td>
<div class="cell">4444</div>
</td>
<td>
<div class="cell">5555</div>
</td>
<td>
<div class="cell">6666</div>
</td>
</tr>
<tr>
<td>
<div class="cell">1111</div>
</td>
<td>
<div class="cell">2222</div>
</td>
<td>
<div class="cell">3333</div>
</td>
<td>
<div class="cell">4444</div>
</td>
<td>
<div class="cell">5555</div>
</td>
<td>
<div class="cell">6666</div>
</td>
</tr>
<tr>
<td>
<div class="cell">1111</div>
</td>
<td>
<div class="cell">2222</div>
</td>
<td>
<div class="cell">3333</div>
</td>
<td>
<div class="cell">4444</div>
</td>
<td>
<div class="cell">5555</div>
</td>
<td>
<div class="cell">6666</div>
</td>
</tr>
<tr>
<td>
<div class="cell">1111</div>
</td>
<td>
<div class="cell">2222</div>
</td>
<td>
<div class="cell">3333</div>
</td>
<td>
<div class="cell">4444</div>
</td>
<td>
<div class="cell">5555</div>
</td>
<td>
<div class="cell">6666</div>
</td>
</tr>
<tr>
<td>
<div class="cell">1111</div>
</td>
<td>
<div class="cell">2222</div>
</td>
<td>
<div class="cell">3333</div>
</td>
<td>
<div class="cell">4444</div>
</td>
<td>
<div class="cell">5555</div>
</td>
<td>
<div class="cell">6666</div>
</td>
</tr>
<tr>
<td>
<div class="cell">1111</div>
</td>
<td>
<div class="cell">2222</div>
</td>
<td>
<div class="cell">3333</div>
</td>
<td>
<div class="cell">4444</div>
</td>
<td>
<div class="cell">5555</div>
</td>
<td>
<div class="cell">6666</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
window.addEventListener('scroll', this.tableScroll, true);
},
beforeDestroy() {
window.removeEventListener('scroll', this.tableScroll);
},
methods: {
tableScroll() {
let _t2 = document.getElementsByClassName('table-header')[0];
let _t3 = document.getElementsByClassName('table-fixed-body')[0];
let _t4 = document.getElementsByClassName('table-body')[0];
_t2.scrollLeft = _t4.scrollLeft;
_t3.scrollTop = _t4.scrollTop;
}
}
}
</script>
<style scoped lang="less">
table {
width: 6rem;
text-align: center;
table-layout: fixed; /* 为表设置表格布局算法 */
border-collapse: collapse; /* 合并边框 */
flex: 1; /* 让所有弹性盒模型对象的子元素都有相同的长度,且忽略它们内部的内容 */
user-select: none; /* 文本不可选 */
font-size: 0.15rem;
tr {
&:nth-child(odd) {
background: #FFFFFF;
}
&:nth-child(even) {
background: #DCECFC;
}
th, td {
// padding: 0.15rem 0;
height: 0.44rem;
overflow: hidden;
white-space: nowrap; /* 文本不换行 */
}
th {
background: #519FF1;
color: #FFFFFF;
border-right: 0.01rem solid rgba(81, 159, 241, 0.2);
.cell {
position: relative;
word-wrap: normal; /* 只在允许的断字点换行 */
text-overflow: ellipsis; /* 超出部分省略号 */
vertical-align: middle;
width: 100%;
box-sizing: border-box;
display: inline-block;
}
}
td {
border-right: 0.01rem solid rgba(81, 159, 241, 0.2);
.cell {
box-sizing: border-box;
white-space: normal; /* 文本不换行 */
word-break: break-all;
}
}
}
}
.table {
position: relative;
width: 100%;
height: 2.2rem;
overflow: hidden;
box-sizing: border-box;
max-width: 100%;
color: #606266;
.table-header {
width: 100%;
overflow: hidden;
}
.table-body {
position: relative;
width: 100%;
height: 1.76rem;
overflow: auto;
}
.table-fixed {
position: absolute;
top: 0;
left: 0;
overflow: hidden;
width: 1.01rem;
height: 2.2rem;
.table-fixed-header {
position: absolute;
left: 0;
top: 0;
z-index: 3;
}
.table-fixed-body {
position: absolute;
left: 0;
top: 0.44rem;
width: 100%;
height: 1.76rem;
overflow: hidden;
}
}
}
</style>
小技巧:
- 表格自动折行处理
td {
white-space: nowrap;
}
/* <td nowrap="nowrap"></td> */