如何实现转换表格中的列的?
html代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>转换表格中的列</title>
<style>
@media only screen and (max-width: 800px) {
/* 强制表格为块状布局 */
table, thead, tbody, th, td, tr {
display: block;
}
/* 隐藏表格头部信息 */
thead tr {
position: absolute;
top: -9999px;
left: -9999px;
}
tr { border: 1px solid #ccc; }
td {
/* 显示列 */
border: none;
border-bottom: 1px solid #eee;
position: relative;
padding-left: 50%;
white-space: normal;
text-align:left;
}
td:before {
position: absolute;
top: 6px;
left: 6px;
width: 45%;
padding-right: 10px;
white-space: nowrap;
text-align:left;
font-weight: bold;
}
/*显示数据*/
td:before { content: attr(data-title); }
}
</style>
</head>
<body style="background-image: url(bg.jpg);color:#fff">
<h1 align="center">招聘信息</h1>
<table width="100%" cellspacing="1" cellpadding="5" border="1">
<thead>
<tr>
<th>序号</th>
<th>职位名称</th>
<th>招聘人数</th>
<th>工作地点</th>
<th>学历要求</th>
<th>年龄要求</th>
<th>薪资</th>
</tr>
</thead>
<tbody align="center">
<tr>
<td>1</td>
<td>Java高级工程师</td>
<td>1</td>
<td>北京</td>
<td>本科</td>
<td>30岁以上</td>
<td>面议</td>
</tr>
<tr>
<td>2</td>
<td>Java初级工程师</td>
<td>3</td>
<td>长春</td>
<td>本科</td>
<td>25岁以上</td>
<td>面议</td>
</tr>
<tr>
<td>3</td>
<td>前端UI设计师</td>
<td>2</td>
<td>长春</td>
<td>本科</td>
<td>25岁以上</td>
<td>面议</td>
</tr>
<tr>
<td>4</td>
<td>PHP高级工程师</td>
<td>2</td>
<td>北京</td>
<td>本科</td>
<td>30岁以上</td>
<td>面议</td>
</tr>
<tr>
<td>5</td>
<td>产品经理</td>
<td>1</td>
<td>长春</td>
<td>本科</td>
<td>28岁以上</td>
<td>面议</td>
</tr>
<tr>
<td>6</td>
<td>测试工程师</td>
<td>3</td>
<td>北京</td>
<td>本科</td>
<td>28岁以上</td>
<td>面议</td>
</tr>
<tr>
<td>7</td>
<td>高级用户研究经理</td>
<td>1</td>
<td>北京</td>
<td>本科</td>
<td>30岁以上</td>
<td>面议</td>
</tr>
<tr>
<td>8</td>
<td>高级Android开发工程师</td>
<td>3</td>
<td>长春</td>
<td>本科</td>
<td>30岁以上</td>
<td>面议</td>
</tr>
</tbody>
</table>
</body>
</html>一、核心转换逻辑
这段代码实现的是把二维表格(行×列)转换为"卡片式列表",每行数据变成一张独立的卡片,每列变成卡片中的一行。
转换前后对比
转换前(宽屏):
text
┌────┬────────────────┬────┬────┬────┬────┬────┐ │序号│ 职位名称 │招聘│地点│学历│年龄│薪资│ ├────┼────────────────┼────┼────┼────┼────┼────┤ │ 1 │Java高级工程师 │ 1 │北京│本科│30+ │面议│ └────┴────────────────┴────┴────┴────┴────┴────┘
转换后(手机屏幕 ≤ 800px):
text
┌─────────────────────┐ │ 序号: 1 │ │ 职位名称: Java高级工 │ │ 招聘人数: 1 │ │ 工作地点: 北京 │ │ 学历要求: 本科 │ │ 年龄要求: 30岁以上 │ │ 薪资: 面议 │ └─────────────────────┘
二、Style 标签代码逐行讲解
1. 媒体查询(第 8 行)
css
@media only screen and (max-width: 800px) {作用:当屏幕宽度 ≤ 800px 时(手机/平板竖屏),应用内部样式
only screen:仅针对屏幕设备(排除打印机等)max-width: 800px:最大宽度 800 像素
2. 🔑 关键:强制所有表格元素变为块级(第 10-12 行)
css
/* 强制表格为块状布局 */table, thead, tbody, th, td, tr {
display: block;}作用:打破表格的二维布局模型,所有元素都变成块级(独占一行)
为什么重要:这是"转换"的第一步,让原本复杂的表格结构变得可重新排列
转换逻辑第 1 步:
text
原来:table → 表格布局(二维) 现在:table → 块级布局(一维,可以重新排列)
3. 🔑 关键:隐藏表头(第 14-17 行)
css
/* 隐藏表格头部信息 */thead tr {
position: absolute;
top: -9999px;
left: -9999px;}作用:把表头行移出屏幕可视区域(视觉上隐藏)
position: absolute:绝对定位,脱离文档流top: -9999px; left: -9999px:移动到屏幕左上角很远的地方
为什么不用 display: none?
用
display: none完全删除表头,屏幕阅读器也读不到用绝对定位移走,屏幕阅读器仍然能读取(保持可访问性)
转换逻辑第 2 步:
text
原来:thead 显示在顶部作为列标签 现在:thead 被移走(隐藏),但保留了语义
4. 行边框样式(第 18 行)
css
tr { border: 1px solid #ccc; }作用:给每个数据行添加灰色边框
效果:每行数据变成一张独立的"卡片",卡片之间有分隔线
转换逻辑第 3 步:
text
原来:tr 是表格中的一行,边框由 table 控制 现在:tr 是独立的块级卡片,有独立边框
5. 🔑 关键:单元格样式(第 19-26 行)
css
td {
/* 显示列 */
border: none; /* 移除所有边框 */
border-bottom: 1px solid #eee; /* 只保留下边框作为分隔线 */
position: relative; /* 相对定位,为伪元素提供定位参考 */
padding-left: 50%; /* 左内边距 50%,为标签腾出空间 */
white-space: normal; /* 允许内容换行 */
text-align: left; /* 文字左对齐 */}逐属性讲解:
| 属性 | 值 | 作用 |
|---|---|---|
border | none | 移除默认边框 |
border-bottom | 1px solid #eee | 添加浅灰下边框(列与列之间的分隔线) |
position | relative | 让伪元素可以相对这个 td 定位 |
padding-left | 50% | 左侧留出 50% 空间给标签(列名) |
white-space | normal | 内容过长时允许换行 |
text-align | left | 内容左对齐 |
转换逻辑第 4 步:
text
原来:td 是表格单元格,水平排列 现在:td 是块级元素,垂直堆叠,左侧预留空间给标签
布局示意:
text
┌─────────────────────────────┐ │ ← 50% → │ ← 内容区域 → │ │ (标签区) │ (数据值) │ │ 序号 │ 1 │ └─────────────────────────────┘
6. 🔑 关键:伪元素生成标签(第 27-34 行)
css
td:before {
position: absolute; /* 绝对定位,相对于 td */
top: 6px; /* 距离顶部 6px */
left: 6px; /* 距离左侧 6px */
width: 45%; /* 宽度占 45% */
padding-right: 10px; /* 右侧内边距 10px */
white-space: nowrap; /* 标签文字不换行 */
text-align: left; /* 文字左对齐 */
font-weight: bold; /* 加粗显示 */}:before 伪元素是什么?
CSS 提供的虚拟元素,可以在真实元素内容之前插入内容
必须配合
content属性使用
转换逻辑第 5 步:
text
原来:列名在表头(thead)中 现在:用伪元素在每个 td 前面动态生成列名
7. 🔑 关键:动态读取列名(第 35 行)
css
/*显示数据*/td:before { content: attr(data-title); }content: attr(data-title):读取当前 td 元素上的data-title属性值作为内容
等等!问题来了:HTML 中并没有 data-title 属性!
html
<!-- 当前 HTML 中是这样写的 --><td>1</td><td>Java高级工程师</td><!-- 但 CSS 期望的是这样 --><td data-title="序号">1</td><td data-title="职位名称">Java高级工程师</td>
⚠️ 代码不完整
这个 CSS 依赖于 HTML 中每个 <td> 都有对应的 data-title 属性。正确的 HTML 应该是:
html
<tbody align="center"> <tr> <td data-title="序号">1</td> <td data-title="职位名称">Java高级工程师</td> <td data-title="招聘人数">1</td> <td data-title="工作地点">北京</td> <td data-title="学历要求">本科</td> <td data-title="年龄要求">30岁以上</td> <td data-title="薪资">面议</td> </tr> <!-- 其他行同理 --></tbody>
三、完整的转换流程图
text
屏幕宽度 ≤ 800px ↓ ┌─────────────────────────────────────────────┐ │ 1. display: block(所有表格元素) │ │ → 打破二维表格布局 │ ├─────────────────────────────────────────────┤ │ 2. thead tr 绝对定位移走 │ │ → 隐藏原始表头 │ ├─────────────────────────────────────────────┤ │ 3. tr 添加边框 │ │ → 每行数据变成独立卡片 │ ├─────────────────────────────────────────────┤ │ 4. td 设置 padding-left: 50% │ │ → 左侧预留标签空间 │ ├─────────────────────────────────────────────┤ │ 5. td:before 伪元素生成标签 │ │ → 读取 data-title 显示列名 │ └─────────────────────────────────────────────┘ ↓ 最终效果:每个 td 显示为 "列名: 值" 的格式
四、视觉效果示例
原始表格的一行
html
<tr> <td>1</td> <td>Java高级工程师</td> <td>1</td> <td>北京</td> <td>本科</td> <td>30岁以上</td> <td>面议</td></tr>
转换后(假设有 data-title)
html
<!-- 每个 td 变成这样的结构 --><div class="card"> <!-- tr --> <div class="td-item"> <!-- td --> <span class="label">序号:</span> <!-- td:before --> <span class="value">1</span> <!-- 原始内容 --> </div> <div class="td-item"> <span class="label">职位名称:</span> <span class="value">Java高级工程师</span> </div> <!-- ... 其他列 ... --></div>
实际渲染效果
text
┌─────────────────────────────────┐ │ 序号: 1 │ │ 职位名称: Java高级工程师 │ │ 招聘人数: 1 │ │ 工作地点: 北京 │ │ 学历要求: 本科 │ │ 年龄要求: 30岁以上 │ │ 薪资: 面议 │ └─────────────────────────────────┘
五、代码优缺点分析
✅ 优点
纯 CSS 实现,无需 JavaScript
保留表格语义,屏幕阅读器可读
响应式,只在手机尺寸生效
⚠️ 缺点/问题
HTML 不完整:缺少
data-title属性,实际不会显示标签需要手动添加属性:每个
<td>都要加data-title,工作量大动态表格不适用:如果表格是 JS 动态生成的,需要额外处理
💡 改进方案
方案1:用 JavaScript 自动添加 data-title
javascript
// 自动从 thead 读取列名并添加属性const ths = document.querySelectorAll('thead th');const rows = document.querySelectorAll('tbody tr');rows.forEach(row => {
const cells = row.querySelectorAll('td');
cells.forEach((cell, index) => {
if (ths[index]) {
cell.setAttribute('data-title', ths[index].textContent);
}
});});方案2:用 CSS 的 counter 或固定内容
css
/* 不推荐:只能处理固定列数的表格 */td:nth-child(1):before { content: "序号"; }td:nth-child(2):before { content: "职位名称"; }/* ... 需要为每一列写规则 */六、总结
这个 CSS 实现的是把表格的行转换成卡片:
| 技术 | 作用 |
|---|---|
display: block | 打破表格布局 |
thead 绝对定位 | 隐藏原始表头 |
tr 加边框 | 每行变成卡片 |
td 的 padding-left: 50% | 为标签预留空间 |
td:before 伪元素 | 动态生成标签 |
attr(data-title) | 读取列名作为标签 |
记忆口诀:
"块级化打破表格,隐藏表头自己写;左边留空放标签,伪元素读取 data-title"