【テクニカル・上級編】 :in-range と :out-of-range 疑似クラス – CSS実践ガイド

「範囲」をCSSで語るということ:`:in-range` と `:out-of-range` のアーキテクチャ的深層

CSSの歴史を振り返れば、我々は長い間、フォームのバリデーションという「JavaScriptの領分」に首を突っ込んで苦労してきた。`min`や`max`属性をHTMLに書いたとしても、その状態をCSSでシームレスに可視化できるようになったのは、モダンブラウザの恩恵だ。

しかし、この `:in-range` と `:out-of-range` をただ「エラー表示のためのおまけ」だと思っているなら、それは大きな勘違いだ。これらはブラウザのレンダリングエンジンと密接に同期する、極めて軽量かつ強力なステートマシンの一部なのである。

1. なぜ JavaScript ではなく CSS でやるべきなのか

多くのエンジニアが陥る罠は、`input`イベントを監視して、バリデーション結果をクラス名としてDOMに付与する処理を書いてしまうことだ。しかし、考えてみてほしい。

  • メインスレッドの解放: JSで監視すれば、入力のたびにイベントリスナーが発火し、仮想DOMやクラス操作のオーバーヘッドが発生する。一方、`:in-range`はブラウザの内部的なConstraint Validation APIと直結している。CSSエンジンが直接状態を判定するため、メインスレッドへの負荷は皆無に等しい。
  • レイアウトスループットの最大化: CSSでのスタイル変更は、ブラウザの再描画パイプラインの中で最適化される。JSを介さないため、UIの「もたつき」を排除できる。

2. 実践:堅牢なバリデーションUIの設計

単に枠を赤くするだけなら初心者でもできる。我々が目指すべきは、ユーザーに「直感的なフィードバック」を与えつつ、アクセシビリティを損なわない設計だ。

/ ベースとなる入力フィールドの設計 /
.c-input {
border: 2px solid #ccc;
transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease;
}

/ 範囲内:成功体験の提示 /
.c-input:in-range {
border-color: #2ecc71;
}

/ 範囲外:静的かつ論理的な警告 /
.c-input:out-of-range {
border-color: #e74c3c;
/ 視覚的な警告だけでなく、フォーカス時のアクセシビリティを確保 /
outline: 2px solid rgba(231, 76, 60, 0.2);
}

/ 擬似要素を活用して、警告メッセージをCSSだけで制御する /
.c-input-wrapper:has(input:out-of-range)::after {
content: “指定された範囲(1〜100)外です”;
color: #e74c3c;
font-size: 0.8rem;
margin-top: 4px;
display: block;
}

3. 注意すべき「闇」:ブラウザの不一致と非同期の罠

ここからが現場レベルの話だ。`:in-range`には決定的な弱点がある。それは「値が未入力(空文字)の時」にはどちらも適用されないという点だ。`min`や`max`があっても、ユーザーが空欄にした場合、ブラウザは「範囲外」とはみなさない。

この仕様は、「必須入力ではない数値フィールド」を扱う際にバグの温床となる。

  • 回避策: 必須項目であれば `:required` 疑似クラスを併用し、`:placeholder-shown` を組み合わせることで、CSSだけで「未入力」と「範囲外」を厳密に切り分ける必要がある。

/ 必須かつ範囲外の場合のみ警告を出すための高度なセレクタ指定 /
.c-input:out-of-range:not(:placeholder-shown) {
/ ここで初めて「ユーザーが入力したが、それが不正である」ことを確定させる /
background-color: #fff0f0;
}

4. パフォーマンスとメモリ効率への考察

大規模なフォームアプリケーションでは、数千個の入力フィールドを同時にレンダリングすることもあるだろう。その際、過剰な `:has()` セレクタや複雑な子孫セレクタは、スタイル計算(Recalculate Style)のコストを増大させる。

  • セレクタの単一化: `:in-range` は可能な限り独立したクラスやBEM単位で運用し、スタイル適用範囲を局所化すること。
  • レンダリング負荷の低減: `:out-of-range` で `box-shadow` を動的にアニメーションさせるのは避けるべきだ。これはレイヤーの再生成をトリガーし、特にモバイル端末でのスクロールパフォーマンスを著しく低下させる。`border-color` や `background-color` などの、合成(Compositing)コストが低いプロパティに留めるのが、プロの選択だ。

結論:CSSは「宣言」であり「状態」である

`:in-range` と `:out-of-range` は、単なる視覚効果ではない。ブラウザのバリデーションエンジンと対話するための、最も洗練されたインターフェースである。

「JavaScriptでバリデーションしてCSSを制御する」という過去の常識を捨て、「HTMLのセマンティクス(min/max)をCSSが直接解釈する」というアーキテクチャにシフトすることで、あなたのWebアプリケーションはより堅牢で、より軽量なものへと進化するだろう。

コードを書くとき、常に問いかけてほしい。「これは本当にJSがやるべき仕事か?」と。その答えがCSSにあるとき、あなたのコードは最高にエレガントで、極めて高いパフォーマンスを発揮するはずだ。

コメント

タイトルとURLをコピーしました