本稿は『CSS Advent Calendar 2016 - Qiita』21日目の記事です.
なんかみんな「ぼくがかんがえたさきょうのしーえすえすせっけい」について語る雰囲気っぽですが,ここは空気を読まずに小ネタでいきます.
ぜんぜんどうでもいい話ですが,僕はCSS設計ネタでは『morishitterのCSSの書き方(2016年夏) - morishitter blog
』と『Clean and Unbreakable CSS // Speaker Deck』が好きです.
TL;DR
-
:checked
擬似クラスと兄弟セレクタ~
を利用すると…- JSを書かずに「ステート(on/offの2値)によるスタイルを切り替え」が実現できる
-
label
要素とinput[type="checkbox"]
またはinput[type="radio"]
を利用すると…- JSを書かずに「ある要素がクリックされたらステート(on/offの2値)が変わる」が実現できる
サンプル: Pure-CSSなTODOリスト
タスクの完了状態の切り替え,およびタスクを1つ選択することができる(さすがにCSSだけで永続化は不可能,たぶん).
マークアップはこんな感じ(pugでごめんなさい).
// completeId, selectId, taskは変数
li.TaskList__item
input.TaskList__item-complete(type="checkbox" id=completeId)
input.TaskList__item-select(type="radio" name="TaskList__item-select" id=selectId)
label.TaskList__item-icon(for=completeId)
label.TaskList__item-body(for=selectId) #{task}
実装
以降のスニペットについては,関係ないところは省略してある.
// display: noneになってる
input.TaskList__item-complete(type="checkbox" id=completeId)
// 見えてるチェックボックスはlabelの::before疑似要素
// forでcheckboxのidを指定しているので,これをクリックするとcheckboxの状態も変わる
label.TaskList__item-icon(for=completeId)
.TaskList__item-body #{task}
/*
* チェックボックスの枠
*/
.TaskList__item-icon::before {
font-family: "FontAwesome";
content: "";
display: block;
border: 1px solid #444;
border-radius: 4px;
margin: calc(2 * var(--spacing)) var(--spacing);
width: var(--TaskList__item-icon-size);
height: var(--TaskList__item-icon-size);
line-height: var(--TaskList__item-icon-size);
cursor: pointer;
}
/*
* チェックボックスの中身
* FontAwesomeの`fa-check`
* 「チェックが入ったチェックボックスと同じ階層にある.TaskList__item-iconの::before疑似要素」にチェックマークを入れる
*/
.TaskList__item-complete:checked ~ .TaskList__item-icon::before {
content: "\f00c";
}
/*
* 「チェックが入ったチェックボックスと同じ階層にある.TaskList__item-body」に取り消し線を入れる
*/
.TaskList__item-complete:checked ~ .TaskList__item-body {
text-decoration: line-through;
}
タスクの選択も同様.
実用するには…
以下についてJSでサポートしてあげる:
- checkbox/radioの
checked
属性に永続化されてるタスクの状態を反映する - checkbox/radioのchangeイベントを拾ってWeb API叩くなりする
Pure CSSだとなにが嬉しいの?
単純に楽しいだけ.
JSとしてはchecked
属性とchange
イベントだけ見てればいいので,見た目とかはすべてCSSに丸投げできる.
よくあるクリックイベント拾って$.addClass()
して…みたいなのを書かなくていい~~,という建前~~.
取りうる状態が2種類しかない場合(on/off, open/close, complete/incomplete, running/stopped, etc.)に雑にスタイルを切り替えたい場合は利用価値があるかも.
微妙にテストが書きづらくなるとか,ムダに詳細度上げてる説があったり等のデメリットもあるので濫用しすぎない方がいいのかもしれない.
他には?
おわりに
CSSには他にもattr()やCSSカウンタのような使い所の難しいおもしろ機能がいっぱいあるので,じゃんじゃん悪用してたのしくCSSを書いていきましょう.
暇な時に仕様書を眺めてみると,新たな発見があるかもしれません.
個人的にはattr()がcontent
プロパティ以外にも利用できるようになるのが非常に楽しみです.