关于如何使用原生实现表格固定列,纯 CSS 实现

10 篇文章 0 订阅

在使用 HTML 的表格标签时,当表格项过多时,左右拉动时,希望固定几列不随水平滚动条滚动,表头也不随竖直方向滚动而滚动。在使用组件库的时候,通常都有成熟的API。
思路一: 是在查找资料中发现的,创建多个 table 将首尾需要固定的列使用单独的表格,然后对需要固定的列所在表格添加position: absolute,本人想通过一个表格实现,未使用该方法。
思路二: 通过position: sticky 实现

<!DOCTYPE html>
<html lang="zh-CN">

<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<link rel="stylesheet" href="./css.css">
	<script src="https://cdn.bootcss.com/xlsx/0.11.5/xlsx.core.min.js"></script>

</head>


<body>
	<div id="table-to-excel">导出Excel</div>
	<div class="contain">
		<div class="table-self" id="table-outlayer">
			<table class="table">
				<thead class="tb-thead">
					<tr class="tr-th">
						<th class="th">
							<div>列一</div>
						</th>
						<th class="th" id="th-2">
							<div>列二</div>
						</th>
						<th class="th">
							<div>列三</div>
						</th>
						<th class="th">
							<div>列四</div>
						</th>
						<th class="th">
							<div>列五</div>
						</th>
						<th class="th">
							<div>列六</div>
						</th>
						<th class="th">
							<div>列七</div>
						</th>
						<th class="th">
							<div>列八</div>
						</th>
						<th class="th">
							<div>列九</div>
						</th>
						<th class="th">
							<div>列十</div>
						</th>
						<th class="th" id="th-11">
							<div>列十一</div>
						</th>
					</tr>
				</thead>
				<tbody class="tb-tbody">
					<tr class="tr-tb">
						<td class="td">行一列一</td>
						<td class="td" id="1-2">行一列二</td>
						<td class="td">行一列三</td>
						<td class="td">行一列四</td>
						<td class="td">行一列五</td>
						<td class="td">行一列六</td>
						<td class="td">行一列七</td>
						<td class="td">行一列八</td>
						<td class="td">行一列九</td>
						<td class="td">行一列十</td>
						<td class="td" id="1-11">行一列十一</td>
					</tr>
					<tr class="tr-tb">
						<td class="td">行二列一</td>
						<td class="td" id="2-2">行二列二</td>
						<td class="td">行二列三</td>
						<td class="td">行二列四</td>
						<td class="td">行二列五</td>
						<td class="td">行二列六</td>
						<td class="td">行二列七</td>
						<td class="td">行二列八</td>
						<td class="td">行二列九</td>
						<td class="td">行二列十</td>
						<td class="td" id="2-11">行二列十一</td>
					</tr>
					<tr class="tr-tb">
						<td class="td">行三列一</td>
						<td class="td" id="3-2">行三列二</td>
						<td class="td">行三列三</td>
						<td class="td">行三列四</td>
						<td class="td">行三列五</td>
						<td class="td">行三列六</td>
						<td class="td">行三列七</td>
						<td class="td">行三列八</td>
						<td class="td">行三列九</td>
						<td class="td">行三列十</td>
						<td class="td" id="3-11">行三列十一</td>
					</tr>
					<tr class="tr-tb">
						<td class="td">行四列一</td>
						<td class="td" id="4-2">行四列二</td>
						<td class="td">行四列三</td>
						<td class="td">行四列四</td>
						<td class="td">行四列五</td>
						<td class="td">行四列六</td>
						<td class="td">行四列七</td>
						<td class="td">行四列八</td>
						<td class="td">行四列九</td>
						<td class="td">行四列十</td>
						<td class="td" id="4-11">行四列十一</td>
					</tr>
					<tr class="tr-tb">
						<td class="td">行五列一</td>
						<td class="td" id="5-2">行五列二</td>
						<td class="td">行五列三</td>
						<td class="td">行五列四</td>
						<td class="td">行五列五</td>
						<td class="td">行五列六</td>
						<td class="td">行五列七</td>
						<td class="td">行五列八</td>
						<td class="td">行五列九</td>
						<td class="td">行五列十</td>
						<td class="td" id="5-11">行五列十一</td>
					</tr>
					<tr class="tr-tb">
						<td class="td">行六列一</td>
						<td class="td" id="6-2">行六列二</td>
						<td class="td">行六列三</td>
						<td class="td">行六列四</td>
						<td class="td">行六列五</td>
						<td class="td">行六列六</td>
						<td class="td">行六列七</td>
						<td class="td">行六列八</td>
						<td class="td">行六列九</td>
						<td class="td">行六列十</td>
						<td class="td" id="6-11">行六列十一</td>
					</tr>
					<tr class="tr-tb">
						<td class="td">行七列一</td>
						<td class="td" id="7-2">行七列二</td>
						<td class="td">行七列三</td>
						<td class="td">行七列四</td>
						<td class="td">行七列五</td>
						<td class="td">行七列六</td>
						<td class="td">行七列七</td>
						<td class="td">行七列八</td>
						<td class="td">行七列九</td>
						<td class="td">行七列十</td>
						<td class="td" id="7-11">行七列十一</td>
					</tr>
					<tr class="tr-tb">
						<td class="td">行八列一</td>
						<td class="td" id="8-2">行八列二</td>
						<td class="td">行八列三</td>
						<td class="td">行八列四</td>
						<td class="td">行八列五</td>
						<td class="td">行八列六</td>
						<td class="td">行八列七</td>
						<td class="td">行八列八</td>
						<td class="td">行八列九</td>
						<td class="td">行八列十</td>
						<td class="td" id="8-11">行八列十一</td>
					</tr>
					<tr class="tr-tb">
						<td class="td">行九列一</td>
						<td class="td" id="9-2">行九列二</td>
						<td class="td">行九列三</td>
						<td class="td">行九列四</td>
						<td class="td">行九列五</td>
						<td class="td">行九列六</td>
						<td class="td">行九列七</td>
						<td class="td">行九列八</td>
						<td class="td">行九列九</td>
						<td class="td">行九列十</td>
						<td class="td" id="9-11">行九列十一</td>
					</tr>
					<tr class="tr-tb">
						<td class="td">行十列一</td>
						<td class="td" id="10-2">行十列二</td>
						<td class="td">行十列三</td>
						<td class="td">行十列四</td>
						<td class="td">行十列五</td>
						<td class="td">行十列六</td>
						<td class="td">行十列七</td>
						<td class="td">行十列八</td>
						<td class="td">行十列九</td>
						<td class="td">行十列十</td>
						<td class="td" id="11-11">行十列十一</td>
					</tr>
				</tbody>
			</table>
		</div>
	</div>

	<script>
		document.getElementById('table-to-excel').addEventListener('click', function () {
			console.log('click');
			let tableDom = document.getElementById("table-outlayer");
			let blob = toSheet(XLSX.utils.table_to_sheet(tableDom));
			let a = document.createElement("a"); // 创建a标签
			a.download = "下载表格.xlsx"; // 设置下载的表格名
			a.href = window.URL.createObjectURL(blob); // 设置a标签的链接
			document.body.appendChild(a); // 将a标签添加到页面
			a.click(); // 设置a标签触发点击事件
			document.body.removeChild(a); //移除a标签
		})

		function toSheet(sheet, sheetName) {
			sheetName = sheetName || "sheet1";
			var workbook = {
				SheetNames: [sheetName],
				Sheets: {},
			};
			workbook.Sheets[sheetName] = sheet;
			// 生成excel的配置项
			var wopts = {
				bookType: "xlsx", // 要生成的文件类型
				bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
				type: "binary",
			};
			var wbout = XLSX.write(workbook, wopts);
			var blob = new Blob([s2ab(wbout)], {
				type: "application/octet-stream;charset=utf-8",
			});
			// 字符串转ArrayBuffer
			function s2ab(s) {
				var buf = new ArrayBuffer(s.length);
				var view = new Uint8Array(buf);
				for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
				return buf;
			}
			return blob;
		}
		window.addEventListener("scroll", function scroll() {
				console.log(document.getElementById("table-outlayer").clientWidth);
				console.log(document.getElementById("table-outlayer").scrollWidth);
				console.log(document.getElementById("table-outlayer").scrollLeft);
				if (document.getElementById("table-outlayer").clientWidth ===
					document.getElementById("table-outlayer").scrollWidth) {
					// 不存在 水平方向的滚动
					return
				} else {
					// 滚动条在最左边时
					if (document.getElementById("table-outlayer").scrollLeft === 0) {
						document.getElementById("th-2").style.boxShadow = "none"
						for (let tbLine = 0; tbLine <= 10; tbLine++) {
							document.getElementById(`${tbLine+1}-2`) ? document.getElementById(`${tbLine+1}-2`).style.boxShadow = "none" : ""
						}
					} else {
						document.getElementById("th-2").style.boxShadow = "4px 0 4px -2px #ccc"
						for (let tbLine = 0; tbLine <= 10; tbLine++) {
							document.getElementById(`${tbLine+1}-2`) ? document.getElementById(`${tbLine+1}-2`).style.boxShadow = "4px 0 4px  -2px #ccc" :
								""
						}
					}
					// 滚动条在最右边时
					if (document.getElementById("table-outlayer").scrollLeft +
						document.getElementById("table-outlayer").clientWidth ===
						document.getElementById("table-outlayer").scrollWidth) {
						document.getElementById("th-11").style.boxShadow = "none"
						for (let tbLine = 0; tbLine <= 10; tbLine++) {
							document.getElementById(`${tbLine+1}-11`) ? document.getElementById(`${tbLine+1}-11`).style.boxShadow = "none" : ""
						}
					} else {
						document.getElementById("th-11").style.boxShadow = "-4px 0 4px -2px #ccc"
						for (let tbLine = 0; tbLine <= 10; tbLine++) {
							document.getElementById(`${tbLine+1}-11`) ? document.getElementById(`${tbLine+1}-11`).style.boxShadow =
								"-4px 0 4px -2px #ccc" : ""
						}
					}
				}
			},
			true)

	</script>
</body>

</html>

css 代码

.contain {
	position: relative;
	width: 1400px;
	height: 600px;
}

.contain .table-self {
	position: relative;
	left: 0;
	top: 0;
	width: 100%;
	height: 500px;
	overflow: auto;
	border: 1px solid #e8e8e8;
	background-color: #fff;
}

.contain .table-self .table {
	position: relative;
	left: 0;
	top: 0;
	width: 100%;
	border-top-left-radius: 4px;
	border-top-right-radius: 4px;
	border-spacing: 0;
	border-collapse: separate;
	text-align: center;
}

.contain .table-self .table .tb-thead {
	position: relative;
	left: 0;
	top: 0;
}

/* // 表格表头第一行 不随竖直方向滚动条滚动 */

.contain .table-self .table .tb-thead .tr-th .th {
	z-index: 99;
	position: sticky;
	left: 0;
	top: 0;
	padding: 16px;
	border-left: 1px solid #e8e8e8;
	border-bottom: 1px solid #e8e8e8;
	color: #000000d9;
	font-size: 14px;
	line-height: 1.5;
	font-weight: 500;
	background-color: #fafafa;
	word-break: break-word;
	overflow-wrap: break-word;
}

.contain .table-self .table .tb-thead .tr-th .th div {
	width: 200px;
}

/* // 表格表头第一行, 第一列 不随水平方向滚动条滚动 */

.contain .table-self .table .tb-thead .tr-th .th:first-child {
	position: sticky;
	left: 0;
	top: 0;
	z-index: 999;
	border-left: none;
}

/* // 表格表头第一行, 第二列 不随水平方向滚动条滚动 */

.contain .table-self .table .tb-thead .tr-th .th:nth-child(2) {
	position: sticky;
	left: 232px;
	/* 第二列left 的距离要是第一列的宽度 */
	top: 0;
	z-index: 998;
}

.contain .table-self .table .tb-thead .tr-th .th:nth-last-child(2) {
	border-right: 1px solid #e8e8e8;
}

/* // 表格表头第一行, 最后一列 不随水平方向滚动条滚动 */

.contain .table-self .table .tb-thead .tr-th .th:last-child {
	position: sticky;
	right: 0;
	top: 0;
	z-index: 999;
	border-left: none;
	box-shadow: -4px 0 4px -2px #ccc;
}

.contain .table-self .table .tb-tbody .tr-tb .td {
	padding: 16px;
	border-left: 1px solid #e8e8e8;
	border-bottom: 1px solid #e8e8e8;
	color: #000000a6;
	font-size: 14px;
	line-height: 1.5;
	background-color: #fff;
}

/* // 表格内容第一列不随水平方向滚动条滚动 */

.contain .table-self .table .tb-tbody .tr-tb .td:first-child {
	position: sticky;
	left: 0;
	top: 0;
	z-index: 9;
	border-left: none;
	border-top: none;
}

/* // 表格内容第二列不随水平方向滚动条滚动 */

.contain .table-self .table .tb-tbody .tr-tb .td:nth-child(2) {
	position: sticky;
	left: 232px;
	/* 第二列的 left 的距离要是第一列的宽度 */
	top: 0;
	z-index: 8;
	border-top: none;
}

.contain .table-self .table .tb-tbody .tr-tb .td:nth-last-child(2) {
	border-right: 1px solid #e8e8e8;
}

/* // 表格内容最后一列不随水平方向滚动条滚动 */

.contain .table-self .table .tb-tbody .tr-tb .td:last-child {
	position: sticky;
	right: 0;
	top: 0;
	z-index: 9;
	border-left: none;
	box-shadow: -4px 0 4px -2px #ccc;
}

其中附带了到处excel功能

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值