ラジオボタンとCSSを使って、特定の規則に従ってデータを並び替えるソート機能を実装するサンプルです。
ソート機能を実装しようと思ったらとりあえずJSを利用するのを考える人も多いと思いますが、本当に簡易的なものであればCSSでもそれっぽい動きが実装できます。
デモのようにページ上部にある「Reset」「Red」「Blue」「Yellow」をそれぞれ選択することによって、その下に並んでいる赤や青の要素が並び替えられる動きを実装していきます。
以前にもラジオボタンとCSSを組み合わせてちょっとした動きを実装するものとして「ラジオボタンとCSSを使ってレイアウトを切り替える」を紹介したのですが、今回も同様でラジオボタンの:checked
と間接セレクタ(~
)を利用します。
まず、HTMLでソートの切り替えやリセットに利用するラジオボタン(<input type="radio">
)とソートの対象となる要素(今回のサンプルの場合はli
要素)をそれぞれ配置し、ラジオボタンにはソート時に利用するidを、ソート対象要素にはdata
属性を利用して値を指定しておきます。
今回は「特定のカラーを持つ要素をソートする」動きの実装になるので、それぞれの値には「red」や「blue」といったカラーを表す命名を用いて、HTMLは下記のようなものを使用します。
<div class="sort-contents">
<input id="sort-reset" type="radio" name="sort" checked><label for="sort-reset">Reset</label>
<input id="sort-red" type="radio" name="sort"><label for="sort-red">Red</label>
<input id="sort-blue" type="radio" name="sort"><label for="sort-blue">Blue</label>
<input id="sort-yellow" type="radio" name="sort"><label for="sort-yellow">Yellow</label>
<ul>
<li data-color="red"></li>
<li data-color="blue"></li>
<li data-color="yellow"></li>
<li data-color="red-blue"></li>
<li data-color="blue"></li>
<li data-color="red-yellow"></li>
<li data-color="red"></li>
<li data-color="blue-yellow"></li>
・
・
・
</ul>
</div>
装飾に関する記述も多いですが、上記HTMLに対して下記のようなCSSを指定することでデモのようなソートの動きを実装することができます。
:root {
--color-red: #e74c3c;
--color-blue: #3498db;
--color-yellow: #f1c40f;
}
.sort-contents {
padding: 1em;
text-align: center;
}
input[name="sort"] {
display: none;
}
label {
display: inline-block;
margin: 0 1em;
font-size: 1.2rem;
font-family: 'Open Sans', sans-serif;
font-weight: 300;
cursor: pointer;
}
label:hover,
input[name="sort"]:checked + label {
color: #000;
border-bottom: 2px solid currentColor;
}
input[name="sort"]:checked + label {
cursor: default;
}
label[for="sort-red"]:hover,
#sort-red:checked + label {
color: var(--color-red);
}
label[for="sort-blue"]:hover,
#sort-blue:checked + label {
color: var(--color-blue);
}
label[for="sort-yellow"]:hover,
#sort-yellow:checked + label {
color: var(--color-yellow);
}
ul {
display: flex;
flex-wrap: wrap;
margin: 0 -20px;
padding: 1em 0 0;
list-style: none;
text-align: left;
}
ul li {
width: calc(20% - 40px);
min-height: 150px;
margin: 40px 20px 0;
}
[data-color="red"] {
background: var(--color-red);
}
[data-color="blue"] {
background: var(--color-blue);
}
[data-color="yellow"] {
background: var(--color-yellow);
}
[data-color="red-blue"] {
background: linear-gradient(var(--color-red) 50%, var(--color-blue) 50%);
}
[data-color="red-yellow"] {
background: linear-gradient(var(--color-red) 50%, var(--color-yellow) 50%);
}
[data-color="blue-yellow"] {
background: linear-gradient(var(--color-blue) 50%, var(--color-yellow) 50%);
}
[data-color="blue-red"] {
background: linear-gradient(var(--color-blue) 50%, var(--color-red) 50%);
}
[data-color="yellow-red"] {
background: linear-gradient(var(--color-yellow) 50%, var(--color-red) 50%);
}
[data-color="yellow-blue"] {
background: linear-gradient(var(--color-yellow) 50%, var(--color-blue) 50%);
}
#sort-red:checked ~ ul [data-color*="red"],
#sort-blue:checked ~ ul [data-color*="blue"],
#sort-yellow:checked ~ ul [data-color*="yellow"] {
order: -1;
}
実装のポイントになるのがul
要素に指定しているdisplay: flex
とコード下部のorder: -1
で、具体的にはFlexboxを利用して配置された要素をorder
を変更することで並び替えるというものになります。
各ラジオボタンが選択された際、間接セレクタ(~
)と:checked
を使用して兄弟関係で且つソート対象要素の親要素であるul要素へスタイル指定し、そこで特定のdata
属性を持つ要素のorder
値を変更させることでデモのような動きを実装することができます。
また、order: -1
を指定しているセレクタにある[data-color*="red"]
のように特定のdata
属性指定に部分一致を用いることで、今回のサンプルにあるdata-color="red-blue"
やdata-color="yellow-red"
のような複数の値を持つものも対象にすることができます。
もっと複雑な条件とか動きをつけたいとなるとやはりJavaScriptを利用することになりますが、先述したように本当に簡易的なものであればCSSだけでもこのような動きが実装できるので、覚えておくと使えそうな場面があると思います。