IEサポート終了後に使いやすくなるCSSセレクタ(疑似クラス、疑似要素)を今のうちに覚えておこう
古くからあるレガシーシステムを保守されている方以外の100%が歓喜した「2022年6月をもってIEサポート終了」というニュースから約1か月。
IEのサポートが終了したら「display:gridが使える!」「position:sticky;があればこの実装が楽になる!」と今までIEをサポートしないといけないせいで使えなかったプロパティに思いを馳せている方は多いと思いますが、意外と「あるCSSセレクタが使える」かどうかで、CSSの書き方がシンプルになるかどうか差が出る部分は多いです。
この記事では、「IE後の世界」で当たり前になるかもしれないCSSセレクタを紹介します。
:is() 疑似クラス
:is()を使用すると、同じようなセレクタの繰り返しを防ぐことができます。
<!DOCTYPE html>
<html lang="en">
<head>
<style>
.link {
color: red;
}
/* IEの世界 */
.block-a .link,
.block-c .link {
color: green;
}
/* IE後の世界 */
:is(.block-a , .block-c) .link {
color: green;
}
</style>
</head>
<body>
<div class="block-a"><a href="" class="link">リンク</a></div>
<div class="block-b"><a href="" class="link">リンク</a></div>
<div class="block-c"><a href="" class="link">リンク</a></div>
</body>
</html>
理解しやすいように単純化した例ですが、.linkというクラスに対するスタイルを「あるブロックでは緑色」のように子孫要素で上書きする必要がある場合にシンプルな記載を実現することができます。
この例では嬉しさが伝わりにくいですが、
「.block-a」が.link-wrap div.a > div.c > p
「.block-c」が.link-wrap header > nav > li
等と統一感なく複雑なものだった場合、
.link-wrap :is( div.a > div.c > p, header > nav > li)のように「,」を繰り返す手間が省けます。
:where() 疑似クラス
用途は:is()と同じくセレクタをまとめることができる:where()疑似クラスですが、:is()との違いは「詳細度を上げない(0にする)」という嬉しいメリットがあります。
他のページで詳細度を上げてしまったスタイルを打ち消すために最終的には「!important」を連発するという「至急」と書いたメールがデフォルトになってしまうような愚かな事態を防げます。
※記載方法は:is()と同様なので割愛します
:is()と:where()の使い分け
残念なことに我々はまだ「IEの世界」に生きていますので、実際の案件で使い分けをしてみないことには判断が難しいところです。
個人的には詳細度は低い方がメンテの際に上書きできる余地が多いということで嬉しい気がしているのですが、「詳細度が0」は多少極端な仕様という気もしますので、
分かりやすさ:is()
メンテのしやすさ:where()
という感触を持っています。
:read-only 疑似クラス
:read-onlyは読み取り専用input要素に適用するための疑似クラスです。
「読み取り専用の時は文字色を薄くしたい」といった用途に使用します。
<!DOCTYPE html>
<html lang="en">
<head>
<style>
input[type="text"] {
color: red;
}
input[type="text"]:read-only {
color: gray;
}
</style>
</head>
<body>
<input type="text" value="よみかきできるよ">
<input type="text" value="よみとりだけだよ" readonly>
</body>
</html>
:read-write疑似クラス
:read-writeは、:read-onlyとは逆に「読み書きできる」状態の要素に適用できる疑似クラスです。
<!DOCTYPE html>
<html lang="en">
<head>
<style>
input[type="text"] {
color: red;
}
input[type="text"]:read-only {
color: gray;
}
input[type="text"]:read-write {
color: blue;
}
</style>
</head>
<body>
<input type="text" value="よみかきできるよ">
<input type="text" value="よみとりだけだよ" readonly>
</body>
</html>
上記のような指定をした場合、「readonly」がついていない1つ目のinput要素の文字色は「青色」になります。
input要素だけのための疑似クラスかと思いきや、
<p contenteditable>この段落は編集可能です。読み書き可です。</p>
のように「contenteditable」が設定された要素にも影響しますので注意が必要です。
※使う頻度は低いと思いますが
参考:https://developer.mozilla.org/ja/docs/Web/CSS/:read-write
:in-range、:out-of-range 疑似クラス
この疑似クラスは、「min」「max」が設定された<input type="number">に使用でき、:in-rangeが「範囲内」、out-of-rangeが「範囲外」を表します。
入力値がout-of-range(範囲外)の時に文字を赤色にするなどに使用できますが、その場合:in-range君が寂しがるので両方使える例を考えてみました。
<!DOCTYPE html>
<html lang="en">
<head>
<style>
input[type="number"] + p {
color: red;
}
input[type="number"]:out-of-range + p {
display: block;
}
input[type="number"]:in-range + p {
display: none;
}
</style>
</head>
<body>
<input type="number" placeholder="1から10の数値" min="1" max="10" value="12">
<p>エラー!範囲外!</p>
</body>
</html>
この例の場合、入力値が範囲外のときだけエラーメッセージを表示します。
あんまり使わない例のような気もしますが。
:host疑似クラス、::part、::slotted疑似要素
これらの疑似クラス、疑似要素はshadow DOMに関するセレクタです。IE後の世界ではshadow DOMが標準的に使用できるようになりますが、まだ「shadow DOMのうれしさ」への理解が薄いので、理解が深まった段階で記事を起こそうと思います。
終わりに
display:grid等のプロパティが使用できることに比べると実装上の影響は少ないかもしれませんが、特に:is()、:where()は使いこなせば「実装時のタイプ量」を減らせる可能性があるので、一定の効果はありそうです。