弹性表格布局不是新主题,并且已经提出了许多解决方案。 “响应表数据综述”由Chris Coyier于2012年首次发布,事情总结得很整齐(包括2018年的更新)。原文连接:https://css-tricks.com/responsive-data-table-roundup/
还有以下一篇文章
Really Responsive Tables using CSS3 Flexbox”。
前文提要:
这里还有一个可选项就是网格响应布局。这不是网格的基础教程,是一个实际的演示案例,对网格布局不熟悉的可以参考国内沅一峰的相关网格文章,本文最后有传送门...谢谢。
HTML表格
HTML中的传统的table是一种布局格式,用于通过行和列矩阵显示项目集合。 项按行布局,在相同列中具有相同的数据属性,行通常按一个或多个可排序属性排序。使用table时,数据的布局生硬地编码为行和列(例如<tr>和<td>)。通常这种布局方式在桌面浏览器中可以正常地陈列数据,但实际上,当你需要在手机浏览器上容纳相同行数的数据表时,往往和发生各行单元格的宽度和列标题单元格宽度不一致的情况,尤其当你的表格是表头固定,表体可以上下滚动的flex表格布局。在手机端浏览器更是如此
造成这种原因主要是来自单元格的字符串长度不确定性而导致的。你可能会做的是固定每个flex单元格的宽度或者对超出单元格宽度的字符串进行类似overflow:hidden的样式设置,或者字体换行等。但那些是非常不好的设置体现。
改善问题
先见一组预览图,在本文中,我使用CSS网格布局模块和CSS属性在没有Javascript的情况下根据屏幕的宽度来模拟一个表格,并且在小屏幕下的行记录切换为卡片模式。主要是规避手机端的宽度过小的问题,充分利用好手机屏幕的高度,容乃足够的信息。如下图效果。
重新定义的表
让我们首先重新定义表格数据应该如何用HTML表示。这里为什么不用回table元素的flex方案呢?我不想废话,如果你要实现flex的布局方案并且有些数据列是多个单元格复合的话,使用table的flex方案写出的html模版会比单纯的ol和div的网格方案会异常的复杂的多。
如前所述,由于表数据本质上是一个有序的项集合,因此使用有序列表似ol元素是顺其自然。 此外,由于表通常用于补充文本描述,因此<div>用于表示单元格的属性,因为HTML5没有为此定义适当的标记。 这里的关键是将语义相似的属性表示为<div>的层次结构。 在定义数据表的grid布局方式时将使用此结构。
<ol class="table-container">
<!--第一个li是模拟thead-->
<li class="table-header row">
<div class="cell sn">#</div>
<div class="cell username">用户名</div>
<div class="cell depart">部门</div>
<div class="cell title">职务</div>
<div class="cell contact">联系方式</div>
<div class="cell avatar">照片</div>
</li>
<!--第二个li是模拟tbody,并且内部在嵌套一个与外层一样的
ol有序列表结构,主要实现数据表的上下滚动效果-->
<li class="table-body">
<ol class="table-container">
<li class="row">
<div class="cell sn" data-title="#">1</div>
<div class="cell username" data-title="用户名">Jack</div>
<div class="cell depart" data-title="部门">品质</div>
<div class="cell title" data-title="职务">主任</div>
<div class="cell contact" data-title="联系方式">137-1341-0192</div>
<div class="cell avatar" data-title="">
<img src="/static/images/male.png">
</div>
.......
</li>
</ol>
</li>
</ol>
如上数据类tbody里的所有<div>元素内的实际数据都是实际数据。
使用ol有序列表+grid布局方案的优点
- 网格模拟的表格的样式轮廓很简洁,对列宽度的定制相对比较灵活,得益于网格的grid-template-columns的属性。
-
只需在不同的media screen语句中,在相邻的两个li元素之间的,可以实现非常复杂的多列复合报表结构。样式控制相对简单。即便无javascript的参与都能实现。
然后是核心的多列复合的网格css样式代码(关于多列复合的响应布局可能需要另外独立写一文)
.cell-container{
display: grid;
grid-template-columns: repeat(auto-fit,minmax(var(--column-width-min),1fr));
}
- 多浏览器支持,目前ie11之后和基于webkit内核的主流浏览器都支持。
缺点:
模拟单元格 div需要过多相同的自定义属性,有些冗余的感觉。
表头固定,表体上下滚动的通用样式
这样的样式还不算简洁的,当然可以进一步简写,当然鉴于这遍是教程。这里写的css略有冗余。
ol.table-container{
list-style: none;
padding:0;
margin: 0;
width:450px;
}
ol.table-container * {
box-sizing: border-box;
}
.table-container >.row{
display: grid;
grid-template-columns: 3em 5em 4em 4em 9em 3em;
border-top:1px solid #ccc;
border-right: 1px solid #ccc;
}
.contact{
grid-column: span 2;
}
.table-header{
background-color: blanchedalmond;
border-bottom: 1px solid #ccc;
}
.table-header >.cell{
/* border-top:1px solid #ccc; */
border-left:1px solid #ccc;
text-align: center;
}
.table-body{
height: 200px;
overflow-y:auto;
border-bottom:1px solid #ccc;
}
.table-body > ol > li >.cell{
text-align: center;
border-left: 1px solid #ccc;
}
.table-header >.cell:last-child,
.table-body > .table-container >.row >.cell:last-child{
display: none;
}
@media screen and (max-width:460px){
ol.table-container{
width: 95%;
height: 450px;
overflow-y: auto;
}
.table-header.row{
display: none;
}
.table-body{
height: 100%;
overflow:hidden;
}
.table-body >.table-container > .row {
display: grid;
grid-template-columns: 1fr;
background-color: blanchedalmond;
border:1px solid #ccc;
margin-bottom: 15px;
border-radius: 15px;
padding:15px;
box-shadow: 10px 10px 10px -5px #ccc;
transition: all .5s ease-in;
line-height: 1.2em;
}
.row{
width:95%;
min-width: 326px;
}
.table-header >.cell:last-child,
.table-body > .table-container >.row >.cell:last-child{
display: inline-flex;
}
.contact{
grid-column: span 1;
}
.table-body > .table-container > .row > .cell:before{
content: attr(data-title);
text-align: left;
}
.table-body > .table-container > .row >.cell{
display: grid;
grid-template-columns:4em 9em .8fr;
padding-left:8px;
grid-gap: 5px;
justify-items: left;
border:1px s÷olid #ccc;
}
.table-body >.table-container > .row > .avatar{
grid-row:1 / 6;
grid-column: 2 / 3;
align-items: center;
}
.table-body > .table-container >.row:hover{
background-color: #ffe066;
box-shadow: 10px 10px 10px -2px #999;
}
}
这里的基本思想是将项目的所有属性显示为普通表,显示宽度允许。 这种布局可以看到尽可能多的项目(行)。table-body里的ol的class样式是二次嵌套使用,虽然略有冗余,但整体来说非常简洁。
卡片样式主要通过隐藏表头,和重置二层嵌套的ol有序表的网格结构实现。
网格参考文章:
http://www.ruanyifeng.com/blog/2019/03/grid-layout-tutorial.html