纯CSS实现表格排序-利用CSS 变量和Flexbox
2018-02-24 本文已影响151人
快乐前端FedFun
1.引子
今天闲逛知名前端资讯站Front-End Front,发现一个比较有意思的效果,给大家分享下,希望可以对大家有所启发。
纯CSS实现表格排序心急的同学,先看效果,我放在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 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 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 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 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 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 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 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 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 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 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 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 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