個人的に使用頻度の低い擬似クラスたち
MDNのデザインが新しくなりましたね。
私としては以前よりも見やすくなっている印象で、大変ありがたく思います。
せっかくのリニューアル記念(?)ということで、サイト内を適当に巡回していたところ、たまたまCSSの擬似クラス一覧にたどり着きました。
どうせならと思い、個人的に使用頻度の低い(もしくは使用したことのない)擬似クラスについてまとめてみました。
擬似クラスとは
そもそも擬似クラスとはなんですかという話です。
ざっくりいうと要素の状態を指定できる便利なやつです。
たとえば:hover
なんかは頻繁に使われる擬似クラスですね。
以下はマウスポインターが(対象の)要素上にある状態の時に、背景色を変化させるコードです。
.box {
background-color: red;
&:hover {
background-color: blue;
}
}
使用頻度の低い擬似クラスたち
ブラウザに実装されていないものを紹介しても仕方がないので、基本的にはモダンブラウザの最新バージョンである程度実装されているものを対象としています。
具体的にはChrome / Edge / Firefox / Safari / Safari on iOSのうち少なくとも3つ以上のブラウザでサポートされているものです(記事執筆時点)。
:autofill
input
の要素が自動補完された状態を表します。
以下はinput
が自動補完された時にborder
の色が赤から緑に変わるサンプルです。
input {
border: 3px solid red;
&.autofill { // 「autofillあり」の方だけ色が緑に変わる
&:-webkit-autofill {
border: 3px solid green;
}
&:autofill {
border: 3px solid green;
}
}
}
Tips:背景色を変更する
:autofill
でたまにあるのが背景色をデフォルトから変更したい(というよりデフォルトの色を反映したくない)という要望です。
しかしブラウザによっては:autofill
におけるデフォルトのbackground-color
を上書きできないこともあります。
回避策の1つとして、box-shadow
を使う方法があります。
input{
&:-webkit-autofill {
box-shadow: 0 0 0 2rem green inset; //inset で内側にシャドウを伸ばす
}
&:autofill {
box-shadow: 0 0 0 2rem green inset; //inset で内側にシャドウを伸ばす
}
}
:indeterminate
一部のフォーム要素で未確定の状態を表します。
対象要素としてはinput[type=checkbox]
、input[type=radio]
、progress
などがあります。
以下はチェックボックスとラジオボタンの未定義状態を表したサンプルコードです。
チェックボックスの状態を未確定にするためにはJavaScriptを使う必要があります。
input {
// 状態が未確定の時は文字が赤色
&:indeterminate {
+ span {
color: red;
}
}
}
const checkbox = document.getElementById("checkbox");
// checkboxの場合は、JavaScriptでindeterminateをtrueにする必要がある
checkbox.indeterminate = true;
:placeholder-shown
input
もしくはtextarea
において、プレイスホルダーの文字列が表示されている状態を表します。
フローティングラベルを実装する時に便利だったりします。
以下は簡易的なフローティングラベルのサンプルコードです。
input {
// :focusと組み合わせることで、フローティングラベルの実装に便利
// :not(:placeholder-shown)でプレイスホルダーが表示されていない(文字列が入力されている)時にラベルを動かす
&:focus,
&:not(:placeholder-shown) {
+ label {
color: rgba(0, 0, 0, 0.7);
transform: translate(-0.1rem, -0.8rem) scale(0.8);
}
}
}
:defined
定義されているすべての要素を表します。
標準として組み込まれている要素の指定としては、あまり使用することがないかもしれません。
どちらかというとカスタム要素の定義と組み合わせて使うことが多いと思われます。
// JavaScriptでカスタム要素が定義されるまでの間、非表示にする
my-circle:not(:defined) {
opacity: 0;
// 縦横を指定することによって、レイアウトシフトを防げる
width: 100px;
height: 100px;
}
:host / :host()
Shadow DOMのホストを表します。
ホストは言い換えるとルート要素みたいなもので、Shadow DOMのルート要素を指定できます。
Shadow DOMの内部で指定した場合のみ有効です。
以下の例ではカスタム要素のmy-custom-element
がホストとなります。
<my-custom-element></my-custom-element>
// これは外部から指定しているので無視される
:host {
background-color: green !important;
}
class MyCustomElement extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
this.shadowRoot.innerHTML = `
<style type="text/css">
:host {
display: inline-block;
padding: 2rem;
}
//:hostかつmy-custom-element要素を指定
:host(my-custom-element) {
background: #ccc;
}
.shadow-dom {
font-size: 20px;
font-weight: bold;
}
</style>
<div class="shadow-dom">Shadow DOM</div>
`;
}
}
customElements.define("my-custom-element", MyCustomElement);
:scope
セレクターが選択する対象の参照点である要素を表します。
CSSファイルに書いたときは:root
と同じ扱いになるようです。
挙動が変わるのはJavaScriptで要素を取得した時で、取得した要素そのものを:scope
で表せます。
取得済みの要素に対してquerySelector/querySelectorAll
などで子セレクタ
を使いたいケースなどで便利そうです。
// :rootと同じ扱い。
:scope {
color: blue;
}
const container = document.getElementById("container");
// #contaierが:scopeとなる
// :scopeの直下要素を取得したい時に有用
const Nest1Els = container.querySelectorAll(":scope > div");
Nest1Els.forEach((el) => {
el.style.margin = "20px 0 0";
});
:target
URLのフラグメント(アンカー)に一致するid属性を持つ要素を表します。
#
付きのアンカーリンクで、その対象要素にスタイルを当てられます。
<a href="#section1">to section1</a>
<section id="section1">
This is Section 1
</section>
:target {
color: red;
background-color: pink;
}
:lang()
ある特定の言語を指定されている要素を表します。
複数言語対応を頻繁にしている方だと、言語ごとにフォントを変更したりする際にそこそこ使うかもしれません。
.text {
&:lang(ja) {
color: red;
}
&:lang(en) {
color: blue;
}
}
:fullscrenn
全画面表示になっている状態を表します。
下記サンプルコードではFullscreen API
経由で全画面モード(もしくはその解除)を実行しています。
// 全画面モードでは文字が赤色に。
:fullscreen p {
color: red;
}
const req = document.getElementById("requestFull");
const exit = document.getElementById("exitFull");
req.addEventListener("click", () => {
if (document.fullscreenEnabled) {
// 全画面モードにする
document.documentElement.requestFullscreen();
}
});
exit.addEventListener("click", () => {
// 全画面モードを解除
if (document.exitFullscreen) {
document.exitFullscreen();
}
});
:first / :left / :right
@page
とともに使われる擬似クラスで、印刷で特定のプロパティ(対象プロパティについてはMDN等を参照してください)を調整できます。
:first
は最初のページ、:left
は左のページ、:right
は右のページを表します。
書字方向が左から右の場合、1ページ目は右(:right)になります。
p {
page-break-after: always;
}
@page :left {
// 2つ目のpが対象(buttonも対象)
margin-left: 0;
}
@page :right {
// 1つ目と3つ目のpが対象
// ただし、1つ目のpは:firstで上書きされるので
// 実際は3つ目のpにだけスタイルが当たる
margin-left: 50%;
}
@page :first {
// 1つ目のpが対象
margin-top: 50%;
margin-left: 50%;
}
<p>最初のページです(:first & :right)</p>
<p>2ページ目(:left)</p>
<p>3ページ目(:right)</p>
まとめ
個人的に使用頻度の低い擬似クラスたちでした。
CSSだけでもできることは増えてきているので、CSSなのかJavaScriptなのか、適切な判断ができるようになりたいですね。
個人としてはまだWeb Components
を実装する機会がほとんどないのですが、:defined
や:host
などはこれから使用する機会か増えていくかもしれません。
参考
Discussion