多列复合的响应表格设计案例

作者: 铁甲万能狗 | 来源:发表于2019-08-05 14:02 被阅读4次

如果你对网格布局模拟表格不太熟悉的话,可以我之前写的文章,传送门如下:
https://www.jianshu.com/p/308d6f793893

前文提要

多列复合就是描述一个对象的同一个数据属性的细分出多个明细的数据列,这在很多业务场合都会碰到,那么本文要做的就是根据屏幕的大小将多个子列合并成一个列数据列,最省心的设计方案就是通过网格布局系统来实现,flex布局也可以实现,但相比较为复杂,本文以一个订单明细表为例。

多列复合响应布局示例.gif

示例代码分析

首先用ol元素定一个我们表的整体轮廓,第一个 li模拟 thead 放置div的列标题,第二个li用来模拟tbody,在里面在嵌套一个于外层ol结构拥有相同的class属性的ol结构,然后下面的li元素用于放置各数据行的div单元格。

值得注意的是
数据行:用class属性row-container表示
数据列:用div元素和class属性cell-container表示
单元格:用div元素和class属性cell表示

<ol class="collection collection-container">
    <!--第一个 li模拟 thead-->
    <li class="item row-container header">
            <div>列标题1</div>
            .....
            <div>列标题n</div>
    </li>
    <!--第二个 li 模拟 tbody-->
     <li class="order-details">
          <ol class="collection">
              <li class="row-container">
                  <div class="cell-container">data 1</div>
                     .....
                  <div class="cell-container">data n</div>
              </li>
              ....
              <li class="row-container">
                  <div class="cell-container">data 1</div>
                    .....
                  <div class="cell-container">data n</div>
             </li>
          </ol>
     </li>
</ol>

使用二层嵌套ol列表的目的是实现tbody部分的数据行的上下滚动。它的基本样式控制如下

    .details-container{
        height: 150px;
        overflow-y: auto;
        scrollbar-width:none;
        border-bottom: 1px solid #ccc;
    }
    

多列复合响应的实现

首先,多列复合的基本思想就是父列容器(div),下面包裹多个子列容器(div),并且他们都用相同的class属性"cell-container"来控制。

<div class="cell-container purchase-info">
      <div class="cell-container part-id">
          <div class="cell" data-name="purchase-number">编号</div>
          <div class="cell" data-name="purchase-desc">描述</div>
     </div>
      <div class="cell-container vendor-info">
             <div class="cell">供应商编号</div>
             <div class="cell">供应商名称</div>
      </div>
</div>

然后,css样式方面,通过网格布局系统的minmax函数在屏幕尺寸变化的时候在auto-fit和各个子列所设置的最小宽度自适应预定的的列数设置。

@media screen and (min-width:737px){
    .cell-container{
        display: grid;
        grid-template-columns: repeat(auto-fit,minmax(var(--column-width-min),1fr));
    }
    
    /*必须为各个子列预定于最小宽度*/
    .purchase-info{
        --column-width-min:10em;
    }
    
    .part-id{
        --column-width-min:10em;
    }
    
    .vendor-info{
        --column-width-min:8em;
    }
    
    .quantity {
        --column-width-min: 5em;
    }

    .cost {
        --column-width-min: 5em;
    }

    .duty {
        --column-width-min: 5em;
    }

    .freight {
        --column-width-min: 5em;
    }
}

从列表模式到卡牌模式

如果你有看我前文,应该知道移动设备的屏幕宽度限制是无法容纳全部数据行的内容的,因此要充分利用好屏幕的高度.卡牌模式是非常适合移动设备显示的,如下图效果

由两列卡牌网格布局到单列的卡牌网格布局

首先,卡牌模式的主要思想是对thead部分进行隐藏,由以下css代码控制样式

@media screen and (max-width:736px){
     /*隐藏表头*/
    .collection-container > li:first-child{
        display: none;
    }

    /*其他代码省略*/  
    ......

当屏幕尺寸达到媒体查询语句所指定的736px宽度范围之内,将tbody部分的数据行每2行数据行各自占据一列转为2列网格的布局。并且将tbody部分的高度设置为100%,如下主要样式代码实现。很明显一个数据行就充当一个卡牌

@media screen and (max-width:736px){
    /*其他代码省略*/  
    ......
    .details-container .collection{
        display: grid;
        grid-template-columns: 1fr 1fr;
       
        grid-gap: 20px;
    }
  
    /*其他代码省略*/  
    .....
    .details-container{
        height:100%;
    }
    /*其他代码省略*/  
    ......
}

最后,需要对每个卡牌(数据行)再次进行网格布局设定,每个卡牌中的每个单元格独立表示该数据对象的一个属性的方面,所以从逻辑上来说,每个单元格要独立成"新的数据行",但光有行中的“数据值”,没有行中的“键值(就是列表头)”怎么行呢?所以需要css的伪类语法:before从每个单元格的div容器的data-name属性中读取该值,并在每个单元格div容器起始位置构造一个伪元素,这样每个单元格新的伪元素,和原来每个单元格中的文本节点,就能构建一个每行2列的网格布局。如下图所示。

屏幕快照4.jpg
具体css代码所示
@media screen and (max-width:736px){
    /*其他代码省略*/  
    .....
    .cell::before{
        content:attr(data-name);
    }
    /*其他代码省略*/  
    .....
    .cell{
        display: grid;
        grid-template-columns: minmax(9em,30%) 1fr;
    }
    /*其他代码省略*/  
    .....
}   

最后的每行单列一个卡牌模式的样式代码,请参看如下完整代码,不再熬述。

完整示例代码

html模版,中间某些数据示例行有省略

<ol class="collection collection-container">
        <!--模拟thead-->
        <li class="item row-container header">
            <div class="cell">订单明细</div>
            <div class="cell" data-name="#">#</div>
            <div class="cell-container purchase-info">
                <div class="cell-container part-id">
                    <div class="cell" data-name="purchase-number">商品编号</div>
                    <div class="cell" data-name="purchase-desc">商品描述</div>
                </div>
                <div class="cell-container vendor-info">
                    <div class="cell">供应商编号</div>
                    <div class="cell">供应商名称</div>
                </div>
            </div>
            <div class="cell-container quantity">
                <div class="cell">订购数量</div>
                <div class="cell">接受数量</div>
            </div>
            <div class="cell-container cost">
                <div class="cell">价格(税前)</div>
                <div class="cell">额外费用</div>
            </div>
            <div class="cell-container duty">
                <div class="cell">税率 %</div>
                <div class="cell">税费</div>
            </div>
            <div class="cell-container freight">
                <div class="cell">费率 %</div>
                <div class="cell">运费</div>
            </div>
            <div class="cell">单位</div>
            <div class="cell">商品编号</div>
        </li>
       <!--模拟tbody-->
        <li class="details-container">
            <ol class="collection">
                <li class="item row-container">
                <div class="cell" data-name="Select"><input type="checkbox" name="" id=""></div>
                <div class="cell" data-name="#">1</div>
                <div class="cell-container purchase-info">
                    <div class="cell-container part-id">
                        <div class="cell" data-name="商品编号">100-10001</div>
                        <div class="cell" data-name="商品描述">This is part A</div>
                    </div>
                    <div class="cell-container vendor-info">
                        <div class="cell" data-name="供应商编号">001</div>
                        <div class="cell" data-name="供应商名称">Vendor Name A</div>
                    </div>
                </div>
                <div class="cell-container quantity">
                    <div class="cell" data-name="预定数量">10</div>
                    <div class="cell" data-name="实际数量">20</div>
                </div>
                <div class="cell-container cost">
                    <div class="cell" data-name="费用">¥5,000</div>
                    <div class="cell" data-name="额外费用">$¥200</div>
                </div>
                <div class="cell-container duty">
                    <div class="cell" data-name="税率 %">3.0%</div>
                    <div class="cell" data-name="税费">$¥1,200</div>
                </div>
                <div class="cell-container freight">
                    <div class="cell" data-name="费率 %">3.0%</div>
                    <div class="cell" data-name="运费">¥1,200</div>
                </div>
                <div class="cell" data-name="单位">EA</div>
                <div class="cell" data-name="供应商品编号">100001</div>
            </li>
            <!--其余行省略-->
            </ol>
        </li>
    </ol>
</section>

完整css样式代码

ol.collection{
  padding:0;
  padding:0;
}

li{
  list-style: none;
}

ol.collection * {
  box-sizing: border-box;
}

@media screen and (min-width:737px){
    .row-container{
/*         border:1px solid #ccc; */
        display: grid;
        grid-template-columns: 2em 2em 10fr 2fr 2fr 2fr  2fr 5em 5em;
    }
    
    .header:first-child{
        border-left: 1px solid #ccc;
    }
    
    .details-container{
        height: 150px;
        overflow-y: auto;
        scrollbar-width:none;
        border-bottom: 1px solid #ccc;
    }
    
    .details-container ol li{
        border-left:1px solid #ccc;
    }
    
    .details-container > ol:nth-child(1) > li> div:nth-child(1){
        display: flex;
    }
    
    .details-container > ol:nth-child(1) > li> div:nth-child(2){
        text-align: center;
/*         align-self: center; */
    }
    
    .cell{
        border-bottom: 1px solid #ccc;
        border-right: 1px solid #ccc;
        padding:2px;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
    }
    .cell-container{
        display: grid;
        grid-template-columns: repeat(auto-fit,minmax(var(--column-width-min),1fr));
    }
    
    
    .purchase-info{
        --column-width-min:10em;
    }
    
    .part-id{
        --column-width-min:10em;
    }
    
    .vendor-info{
        --column-width-min:8em;
    }
    
    .quantity {
        --column-width-min: 5em;
    }

    .cost {
        --column-width-min: 5em;
    }

    .duty {
        --column-width-min: 5em;
    }

    .freight {
        --column-width-min: 5em;
    }
    
    .collection{
        border-top:1px solid #ccc;
    }
    
    .collection-container > .row-container:first-child{
        background-color: blanchedalmond;
    }
    
    .row-container:hover{
        background-color: rgb(200,227,252);
    }
    
    /*表头标签居中*/
    .collection-container > .row-container:first-child .cell {
        display: flex;
        align-items: center;
        justify-content: center;
        text-overflow: initial;
        overflow: auto;
        white-space: normal;
    }
    
}

@media screen and (max-width:736px){
    .details-container .collection{
        display: grid;
        grid-template-columns: 1fr 1fr;
        grid-gap: 20px;
    }
    
    .details-container{
        height:100%;
        /*overflow-y: auto;*/
    }

    .item{
        border:1px solid #ccc;
        border-radius: 4px;
        padding:10px;
        background-color: blanchedalmond;
    }
    
    .collection-container > li:first-child{
        display: none;
    }
    
    .cell::before{
        content:attr(data-name);
    }
    
    .cell{
        display: grid;
        grid-template-columns: minmax(9em,30%) 1fr;
    }
}

@media screen and (max-width:580px){
    .details-container .collection{
        display: grid;
        grid-template-columns: 1fr;
    }
}

相关文章

  • 多列复合的响应表格设计案例

    如果你对网格布局模拟表格不太熟悉的话,可以我之前写的文章,传送门如下:https://www.jianshu.co...

  • 每日发现好设计2020-06-09

    超多列表格的终极解决方案 相信大多数设计师都会遇到一个非常头疼的需求,那就是在表格设计中,要展示超多列(超多10列...

  • Bootstrap--常用及实例合集

    栅格系统 列的样式 文本对齐类 表单 表格 响应式表格 按钮 快速浮动 清除样式 Bootstrap3居中处理 垂...

  • 表格多列排序

    效果演示 实现的是点击表格的标题,对应的列按照大小排序,如果是数字,按照大小排序,如果是非数字, 通过 local...

  • CSS3 多列

    CSS3 多列 CSS3 可以将文本内容设计成像报纸一样的多列布局,如下实例: 浏览器支持 表格中的数字表示支持该...

  • python 读写 excel

    参考 读写案例 快速开始 安装excel读写包 xlrd 语法 xlwt语法 案例 - 合并不同表格的某一列

  • 表格绘制_附件_代码

    用法举例:|id||:-:||1||2|id12 壹列表格 俩列表格 叁列表格 肆列表格 伍列表格 陆列表格 柒列...

  • 小程序跨行跨列多列复杂表格实现

    今天来实现个跨行跨列多列表格。 如图,这是个列数不确定,有的单元格还要跨行跨列的复杂表格。 这里暂时最多支持4列,...

  • vue动态编译

    动态编译的需求:如在写一个表格组件时,我们可能需要表格的某一列是可定制化的,比如这一列可实现点击响应一个事件,要实...

  • 如何将EXCEL表按行拆分成多个表

    1、选中表格区域——数据——数据透视表2、将筛选列拖至筛选器——其他列拖至行3、设计——报表布局——选择以表格形式...

网友评论

    本文标题:多列复合的响应表格设计案例

    本文链接:https://www.haomeiwen.com/subject/rygjdctx.html