「またか」と思うかもしれないが、フォーム実装で一番見落とされがちなのが `:required` と `:optional` の使いこなしだ。
現場でコードレビューをしていると、未だに「必須項目にクラス名 `is-required` を付与して、JavaScriptで頑張って制御する」といった古い実装に出くわす。悪いとは言わない。だが、ブラウザが標準で用意している強力なフックを無視するのは、あまりに勿体ない。
今回は、CSSのスペシャリストの視点から、この二つの疑似クラスをどう「現場の武器」に変えるか、その極意を伝授しよう。
—
なぜクラス名ではなく疑似クラスを使うべきか
結論から言えば、「HTMLの構造と状態(State)を分離できるから」に尽きる。
`required` 属性を持つ要素は、ブラウザ側ですでにバリデーションの対象として認識されている。CSSの `:required` 疑似クラスを使うということは、マークアップに忠実な「事実」に基づいてスタイルを当てるということだ。クラス名で管理すると、JSの処理漏れで「必須なのに必須っぽくない」というUXのバグが必ず生まれる。
ブラウザは `required` 属性を検知した瞬間、内部的に `:required` 状態を付与する。これをCSS側でフックする方が、CSSアーキテクチャとしては遥かに堅牢だ。
実践:アスタリスクをスマートに制御する
よくある「ラベルの横にアスタリスクを出す」という処理。これをJSでやる必要はない。CSSの擬似要素と組み合わせれば、すべて完結する。
サンプルコード
/ 必須項目のラベルにだけ「」を表示するスマートな手法 /
/ 必須項目のinputの直後のラベルに対してスタイルを当てる /
.form-field:has(:required) label::after {
content: ” “;
color: #ff4d4f; / 警告色の赤 /
font-weight: bold;
}
/ 任意項目には「(任意)」と添えることで視認性を上げる /
.form-field:has(:optional) label::after {
content: ” (任意)”;
color: #8c8c8c; / 控えめなグレー /
font-size: 0.85em;
}
ここで重要なのは `:has()` セレクタの活用だ。`label` 自体には属性がない場合でも、親要素(コンテナ)から子要素の状態を覗き込むことで、DOM構造を汚さずにスタイルを適用できる。これぞ現代のCSS設計だ。
—
現場で刺さる「UXの微調整」
単にアスタリスクを出すだけでは、中級者とは呼べない。実務では「入力中」の状態まで考慮してあげるのが優しさというものだ。
例えば、ユーザーが入力に失敗した際や、フォーカスしている際の挙動を `:required` と組み合わせるだけで、プロダクトの質は一段階上がる。
/ 必須項目で、かつ未入力のまま送信しようとした場合(:invalid)の強調 /
input:required:invalid {
border: 2px solid #ff4d4f;
outline-color: #ff4d4f;
}
/ 逆に、入力が完了した必須項目は優しく緑色でフィードバックする /
input:required:valid {
border: 2px solid #52c41a;
}
注意点:ブラウザの挙動を知っておく
ここで一つ、シニアとして忠告しておく。`:invalid` は、ユーザーがページを開いた瞬間の「空の必須項目」に対しても適用されてしまう。
これだと、入力する前からフォーム全体が赤く染まってしまい、ユーザーを不安にさせる。これを防ぐには、`:placeholder-shown` を組み合わせるのが定石だ。
/
- placeholderが表示されている=ユーザーがまだ何も入力していない
- という状態を利用して、初期状態の「真っ赤なエラー」を防ぐ
/
input:required:invalid:not(:placeholder-shown) {
border-color: #ff4d4f;
}
—
まとめ:運用を楽にするのがアーキテクトの仕事
フロントエンドエンジニアの仕事は、単に画面を作ることじゃない。「変更に強く、かつメンテナンスコストが低い実装を維持すること」だ。
1. クラス名での管理をやめ、`:required` / `:optional` を信頼する。
2. `:has()` を駆使して、HTML構造をシンプルに保つ。
3. `:placeholder-shown` を組み合わせ、初期状態のノイズを排除する。
これらのテクニックは、どれも仕様に基づいた極めてクリーンなものだ。コードを書くときは、常に「ブラウザがどう解釈するか」を想像してほしい。そうすれば、無駄なJSは消え去り、驚くほど軽量で美しいフォームが手に入るはずだ。
明日からの実装で、ぜひ試してみてくれ。現場で詰まったら、またいつでも相談に乗るよ。

コメント