美文网首页前端进阶之路让前端飞Web 前端开发
纯CSS实现表格排序-利用CSS 变量和Flexbox

纯CSS实现表格排序-利用CSS 变量和Flexbox

作者: 快乐前端FedFun | 来源:发表于2018-02-24 16:30 被阅读151次

    1.引子

    今天闲逛知名前端资讯站Front-End Front,发现一个比较有意思的效果,给大家分享下,希望可以对大家有所启发。

    纯CSS实现表格排序

    心急的同学,先看效果,我放在codepen上。


    codepen上预览、编辑效果


    本案例用到了以下知识点:

    • CSS变量
    • Flexbox布局
    • grid布局(非必须,可以替代)

    因此,本案例只在现代浏览器中运行良好。

    2.核心原理

    我们利用Flexbox的方式打破表格布局,让表格做Flex容器(container),每一行做Flex子项(item),然后利用CSS变量的方式设置order。

    .table-body {
      display: flex;
      flex-direction: column;
    }
    
    .table-row {
      order: calc(var(--order) * var(--sort-order, -1));
    }
    

    另外,为了实现纯CSS,我们用到了input的:checked伪类模拟实现单击。

    #sort-by-published:checked ~ .table > .table-body > .table-row {
      --order: var(--order-by-published);
    }
    
    #sort-by-views:checked ~ .table > .table-body > .table-row {
      --order: var(--order-by-views);
    }
    
    #sort-ascending:checked + .table {
      --sort-order: 1;
    }
    

    3.实现步骤

    3.1 HTML

    为了实现单击,我们使用input+label的方式调用:checked伪类。首先,我们需要两组input。

      <!--  :checked实现单击,这些input不在网页中显示  -->
      <!--  name为sort的input,用来控制排序字段  -->
      <input type="radio" name="sort" id="sort-by-name">
      <input type="radio" name="sort" id="sort-by-published" checked="checked">
      <input type="radio" name="sort" id="sort-by-views">
      <!--  name为sort-order的input,用来控制排序方式,升序还是降序  -->
      <input type="radio" name="sort-order" id="sort-descending" checked="checked">
      <input type="radio" name="sort-order" id="sort-ascending">
    

    然后是label。

    <table class="table">
        <thead class="table-head">
          <tr class="table-row">
            <th class="table-cell">
              <label class="table-sorter" for="sort-by-name">文章</label>
              <label class="table-orderer" for="sort-ascending" data-filtered="filtered">↓</label>
              <label class="table-orderer" for="sort-descending" data-filtered="filtered">↑</label>
            </th>
            <th class="table-cell">
              <label class="table-sorter" for="sort-by-published">出版</label>
              <label class="table-orderer" for="sort-ascending">↓</label>
              <label class="table-orderer" for="sort-descending" data-filtered="filtered">↑</label>
            </th>
            <th class="table-cell">
              <label class="table-sorter" for="sort-by-views">浏览</label>
              <label class="table-orderer" for="sort-ascending" data-filtered="filtered">↓</label>
              <label class="table-orderer" for="sort-descending" data-filtered="filtered">↑</label>
            </th>
          </tr>
        </thead>
        <tbody class="table-body">
        </tbody>
      </table>
    

    接下去是表格主题内容。

       <tbody class="table-body">
          <tr class="table-row" style="--order-by-published: 161021; --order-by-views: 10368;">
            <th class="table-cell">Conditions for CSS Variables</th>
            <td class="table-cell">2016-10-21</td>
            <td class="table-cell">10&thinsp;368</td>
          </tr>
          <tr class="table-row" style="--order-by-published: 161221; --order-by-views: 2431;">
            <th class="table-cell">Controlling the Specificity</th>
            <td class="table-cell">2016-12-21</td>
            <td class="table-cell">2&thinsp;431</td>
          </tr>
          <tr class="table-row" style="--order-by-published: 180104; --order-by-views: 4463;">
            <th class="table-cell">Counters and Stones</th>
            <td class="table-cell">2018-01-04</td>
            <td class="table-cell">4&thinsp;463</td>
          </tr>
          <tr class="table-row" style="--order-by-published: 171128; --order-by-views: 6585;">
            <th class="table-cell">Flexible Overflow</th>
            <td class="table-cell">2017-11-28</td>
            <td class="table-cell">6&thinsp;585</td>
          </tr>
          <tr class="table-row" style="--order-by-published: 170627; --order-by-views: 4597;">
            <th class="table-cell">Keyboard-Only Focus</th>
            <td class="table-cell">2017-06-27</td>
            <td class="table-cell">4&thinsp;597</td>
          </tr>
          <tr class="table-row" style="--order-by-published: 170531; --order-by-views: 2829;">
            <th class="table-cell">Label-to-Input States</th>
            <td class="table-cell">2017-05-31</td>
            <td class="table-cell">2&thinsp;829</td>
          </tr>
        </tbody>
    

    3.2 CSS

    /* 关键代码 */
    
    .table-body {
      display: flex;
      flex-direction: column;
    }
    
    .table-row {
      order: calc(var(--order) * var(--sort-order, -1));
    }
    
    #sort-by-published:checked ~ .table > .table-body > .table-row {
      --order: var(--order-by-published);
    }
    
    #sort-by-views:checked ~ .table > .table-body > .table-row {
      --order: var(--order-by-views);
    }
    
    #sort-ascending:checked + .table {
      --sort-order: 1;
    }
    
    /* 反向排序 */
    #sort-by-name:checked ~ #sort-ascending:checked + .table > .table-body {
      flex-direction: column-reverse;
    }
    

    以及其他布局和样式方面的代码

    /* 其他代码 */
    
    .table-wrapper > input {
      position: fixed;
      left: 0;
      right: 0;
      clip: rect(1px,1px,1px,1px);
      visibility: hidden;
    }
    
    .table,
    .table-caption,
    .table-head {
      display: block;
      margin: 0;
    }
    
    table,td,th{
      border: 1px solid #000;
      border-collapse:collapse;
    }
    
    a{
      text-decoration: none;
      color:black;
    }
    
    .table-row {
      position: relative;
      display: grid;
      grid-template-columns: 50% 25% 25%;
    }
    
    .table-cell {
      text-align: right;
      padding: 0.25em 0.5em;
      white-space: nowrap;
    }
    
    .table-cell:first-child {
      text-align: left;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    
    .table-orderer {
      display: none;
    }
    
    .table-head .table-cell {
      position: relative;
      display: flex;
      user-select: none;
    }
    
    .table-head .table-cell:hover {
      background: rgba(0,0,0,0.05);
    }
    
    .table-head .table-cell:not(:first-child) {
      flex-direction: row-reverse;
    }
    
    .table-sorter:before,
    .table-orderer:before {
      content: "";
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      cursor: pointer;
    }
    
    #sort-by-name:checked ~ .table .table-sorter[for=sort-by-name] ~ .table-orderer,
    #sort-by-published:checked ~ .table .table-sorter[for=sort-by-published] ~ .table-orderer,
    #sort-by-views:checked ~ .table .table-sorter[for=sort-by-views] ~ .table-orderer {
      display: inline;
    }
    
    #sort-ascending:checked + .table .table-orderer[for=sort-ascending],
    #sort-ascending:not(:checked) + .table .table-orderer[for=sort-descending] {
      display: none !important;
    }
    

    3.3 整体源码

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <title>纯CSS实现表格排序-利用CSS 变量和Flexbox</title>
            <style type="text/css">
                /* 其他代码 */
                
                .table-wrapper>input {
                    position: fixed;
                    left: 0;
                    right: 0;
                    clip: rect(1px, 1px, 1px, 1px);
                    visibility: hidden;
                }
                
                .table,
                .table-caption,
                .table-head {
                    display: block;
                    margin: 0;
                }
                
                table,
                td,
                th {
                    border: 1px solid #000;
                    border-collapse: collapse;
                }
                
                a {
                    text-decoration: none;
                    color: black;
                }
                
                .table-row {
                    position: relative;
                    display: grid;
                    grid-template-columns: 50% 25% 25%;
                }
                
                .table-cell {
                    text-align: right;
                    padding: 0.25em 0.5em;
                    white-space: nowrap;
                }
                
                .table-cell:first-child {
                    text-align: left;
                    overflow: hidden;
                    text-overflow: ellipsis;
                }
                
                .table-orderer {
                    display: none;
                }
                
                .table-head .table-cell {
                    position: relative;
                    display: flex;
                    user-select: none;
                }
                
                .table-head .table-cell:hover {
                    background: rgba(0, 0, 0, 0.05);
                }
                
                .table-head .table-cell:not(:first-child) {
                    flex-direction: row-reverse;
                }
                
                .table-sorter:before,
                .table-orderer:before {
                    content: "";
                    position: absolute;
                    top: 0;
                    left: 0;
                    right: 0;
                    bottom: 0;
                    cursor: pointer;
                }
                
                #sort-by-name:checked~.table .table-sorter[for=sort-by-name]~.table-orderer,
                #sort-by-published:checked~.table .table-sorter[for=sort-by-published]~.table-orderer,
                #sort-by-views:checked~.table .table-sorter[for=sort-by-views]~.table-orderer {
                    display: inline;
                }
                
                #sort-ascending:checked+.table .table-orderer[for=sort-ascending],
                #sort-ascending:not(:checked)+.table .table-orderer[for=sort-descending] {
                    display: none !important;
                }
            </style>
        </head>
        <body>
            <div class="table-wrapper">
                <!--  :checked实现单击,这些input不在网页中显示  -->
                <input type="radio" name="sort" id="sort-by-name">
                <input type="radio" name="sort" id="sort-by-published" checked="checked">
                <input type="radio" name="sort" id="sort-by-views">
                <input type="radio" name="sort-order" id="sort-descending" checked="checked">
                <input type="radio" name="sort-order" id="sort-ascending">
                <table class="table">
                    <thead class="table-head">
                        <tr class="table-row">
                            <th class="table-cell">
                                <label class="table-sorter" for="sort-by-name">文章</label>
                                <label class="table-orderer" for="sort-ascending" data-filtered="filtered">↓</label>
                                <label class="table-orderer" for="sort-descending" data-filtered="filtered">↑</label>
                            </th>
                            <th class="table-cell">
                                <label class="table-sorter" for="sort-by-published">出版</label>
                                <label class="table-orderer" for="sort-ascending">↓</label>
                                <label class="table-orderer" for="sort-descending" data-filtered="filtered">↑</label>
                            </th>
                            <th class="table-cell">
                                <label class="table-sorter" for="sort-by-views">浏览</label>
                                <label class="table-orderer" for="sort-ascending" data-filtered="filtered">↓</label>
                                <label class="table-orderer" for="sort-descending" data-filtered="filtered">↑</label>
                            </th>
                        </tr>
                    </thead>
                    <tbody class="table-body">
                        <tr class="table-row" style="--order-by-published: 161021; --order-by-views: 10368;">
                            <th class="table-cell">Conditions for CSS Variables</th>
                            <td class="table-cell">2016-10-21</td>
                            <td class="table-cell">10&thinsp;368</td>
                        </tr>
                        <tr class="table-row" style="--order-by-published: 161221; --order-by-views: 2431;">
                            <th class="table-cell">Controlling the Specificity</th>
                            <td class="table-cell">2016-12-21</td>
                            <td class="table-cell">2&thinsp;431</td>
                        </tr>
                        <tr class="table-row" style="--order-by-published: 180104; --order-by-views: 4463;">
                            <th class="table-cell">Counters and Stones</th>
                            <td class="table-cell">2018-01-04</td>
                            <td class="table-cell">4&thinsp;463</td>
                        </tr>
                        <tr class="table-row" style="--order-by-published: 171128; --order-by-views: 6585;">
                            <th class="table-cell">Flexible Overflow</th>
                            <td class="table-cell">2017-11-28</td>
                            <td class="table-cell">6&thinsp;585</td>
                        </tr>
                        <tr class="table-row" style="--order-by-published: 170627; --order-by-views: 4597;">
                            <th class="table-cell">Keyboard-Only Focus</th>
                            <td class="table-cell">2017-06-27</td>
                            <td class="table-cell">4&thinsp;597</td>
                        </tr>
                        <tr class="table-row" style="--order-by-published: 170531; --order-by-views: 2829;">
                            <th class="table-cell">Label-to-Input States</th>
                            <td class="table-cell">2017-05-31</td>
                            <td class="table-cell">2&thinsp;829</td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </body>
    </html>
    

    4.声明

    爱前端,乐分享。FedFun希望与您共同进步。
    欢迎任何形式的转载,烦请注明装载,保留本段文字。
    独立博客http://whqet.github.io
    极客头条http://geek.csdn.net/user/publishlist/whqet
    CSDN博客http://blog.csdn.net/whqet/
    我的简书https://www.jianshu.com/u/c11d4318b3c7

    相关文章

      网友评论

        本文标题:纯CSS实现表格排序-利用CSS 变量和Flexbox

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