純CSS實(shí)現(xiàn)表格排序-利用CSS 變量和Flexbox

1.引子

今天閑逛知名前端資訊站Front-End Front碳锈,發(fā)現(xiàn)一個(gè)比較有意思的效果售碳,給大家分享下贸人,希望可以對(duì)大家有所啟發(fā)艺智。

純CSS實(shí)現(xiàn)表格排序

心急的同學(xué)力惯,先看效果父晶,我放在codepen上甲喝。


codepen上預(yù)覽埠胖、編輯效果


本案例用到了以下知識(shí)點(diǎn):

  • CSS變量
  • Flexbox布局
  • grid布局(非必須直撤,可以替代)

因此谋竖,本案例只在現(xiàn)代瀏覽器中運(yùn)行良好蓖乘。

2.核心原理

我們利用Flexbox的方式打破表格布局韧骗,讓表格做Flex容器(container)袍暴,每一行做Flex子項(xiàng)(item)政模,然后利用CSS變量的方式設(shè)置order览徒。

.table-body {
  display: flex;
  flex-direction: column;
}

.table-row {
  order: calc(var(--order) * var(--sort-order, -1));
}

另外习蓬,為了實(shí)現(xiàn)純CSS躲叼,我們用到了input的:checked偽類模擬實(shí)現(xiàn)單擊枫慷。

#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.實(shí)現(xiàn)步驟

3.1 HTML

為了實(shí)現(xiàn)單擊,我們使用input+label的方式調(diào)用:checked偽類探孝。首先顿颅,我們需要兩組input粱腻。

  <!--  :checked實(shí)現(xiàn)單擊,這些input不在網(wǎng)頁中顯示  -->
  <!--  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>

接下去是表格主題內(nèi)容。

   <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

/* 關(guān)鍵代碼 */

.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實(shí)現(xiàn)表格排序-利用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實(shí)現(xiàn)單擊,這些input不在網(wǎng)頁中顯示  -->
            <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希望與您共同進(jìn)步番舆。
歡迎任何形式的轉(zhuǎn)載恨狈,煩請(qǐng)注明裝載拴事,保留本段文字圣蝎。
獨(dú)立博客http://whqet.github.io
極客頭條http://geek.csdn.net/user/publishlist/whqet
CSDN博客http://blog.csdn.net/whqet/
我的簡書http://www.reibang.com/u/c11d4318b3c7

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市哮针,隨后出現(xiàn)的幾起案子十厢,更是在濱河造成了極大的恐慌蛮放,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瞻想,死亡現(xiàn)場(chǎng)離奇詭異蘑险,居然都是意外死亡岳悟,警方通過查閱死者的電腦和手機(jī)贵少,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來柴信,“玉大人宽气,你說我怎么就攤上這事⌒鞣眨” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長序目。 經(jīng)常有香客問我猿涨,道長,這世上最難降的妖魔是什么澡绩? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮事镣,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘唠叛。我一直安慰自己艺沼,他們只是感情好蕴掏,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布挽荡。 她就那樣靜靜地躺著定拟,像睡著了一般青自。 火紅的嫁衣襯著肌膚如雪株依。 梳的紋絲不亂的頭發(fā)上恋腕,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天荠藤,我揣著相機(jī)與錄音哈肖,去河邊找鬼谋减。 笑死出爹,一個(gè)胖子當(dāng)著我的面吹牛严就,可吹牛的內(nèi)容都是我干的器罐。 我是一名探鬼主播轰坊,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼粟害,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼颤芬!你這毒婦竟也來了站蝠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎澜倦,沒想到半個(gè)月后聚蝶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拔疚,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年既荚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了稚失。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡恰聘,死狀恐怖句各,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情晴叨,我是刑警寧澤凿宾,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站兼蕊,受9級(jí)特大地震影響产禾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望黄伊。 院中可真熱鬧愈腾,春花似錦悦即、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瞒大。三九已至踢械,卻和暖如春顾瞻,著一層夾襖步出監(jiān)牢的瞬間移稳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國打工嫂冻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留睛低,地道東北人骂铁。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓名段,卻偏偏與公主長得像信夫,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案大州? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 13,754評(píng)論 1 92
  • H5移動(dòng)端知識(shí)點(diǎn)總結(jié) 閱讀目錄 移動(dòng)開發(fā)基本知識(shí)點(diǎn) calc基本用法 box-sizing的理解及使用 理解dis...
    Mx勇閱讀 4,507評(píng)論 0 26
  • 2018年2月23日 星期五 天氣 多云 時(shí)間真是過的很快排嫌,覺得還沒在家呆多久躯畴,就又要準(zhǔn)備離開夯到。不過還好,還有些日...
    602f5c8ad9da閱讀 485評(píng)論 0 5
  • 死宅的我见秤,在涼涼的夜色里挣跋,一個(gè)人漫步于人海中查库、車水馬龍間:一是出來疏散疏散心情裤园,二是于人世的煙火里感受別人的喜...
    木子米爾閱讀 317評(píng)論 0 0
  • 白如晶玉的雪花在空中洋洋灑灑地飄著铡羡,坐在歸家的車上面论矾,我看著就像蒙著灰紗的天空心中不由得悸動(dòng)著闰靴⌒铀溃‘這就是近鄉(xiāng)情更怯...
    暮軒閱讀 632評(píng)論 2 7