フォームの表現でよく見られる、必須フィールドとなるラベルに * のようなマーカーを付ける方法について、 CSS のみで実装する方法を紹介します。
注意
:has() は現在 (2022/04/23) 時点での対応ブラウザは Safari 15.4 以降のみなので、お使いのブラウザでは動作しない可能性があります。
そもそも :has()
とは
これまでの CSS セレクタでは不可能だった、自分の子要素や後に続く要素から判別することができる CSS の擬似クラスです。
例えば、 <img>
要素を直接含む <div>
を指定する場合、以下のように書くことが出来ます。
div:has(> img) {
}
実現方法
ラベル付きの入力フィールドについて、よく使われる構造に対してそれぞれ二つずつ実装方法を紹介します。
例では <input>
のみとしていますが、同じようなやり方で別のフィールドタグについても対応できます。
<label>
と <input>
が隣接する場合
<div>
<label></label>
<input>
</div>
上のような構造の場合、「div
の子要素で隣接要素に input:required
を持つ label
」と「子要素に input:required
を持つ div
の子要素 label
」という指定方法で、それぞれ以下のように指定することができます。
div > label:has(+ input:required)::after {
content: "*";
}
div:has(> input:required) > label::after {
content: "*";
}
<input>
を <label>
の内側に入れる場合
<label>
<span></span>
<input>
</label>
上のような構造の場合も同様に、「div
の子要素で隣接要素に input:required
を持つ span
」と「子要素に input:required
を持つ label
の子要素 span
」という指定方法で、それぞれ以下のように指定することができます。
label > span:has(+ input:required)::after {
content: "*";
}
label:has(> input:required) > span::after {
content: "*";
}
※ ::after 擬似要素を使っている都合上、フィールドのラベルを <span>
で囲うような構造にしています。
サンプルコード
上の各方法で実装したサンプルコードが以下です。
セレクタの指定をいくつか変えています。
<form>
<div class="labeled-input labeled-input--adjacent">
<label>Name</label>
<input type="text" required>
</div>
<div class="labeled-input labeled-input--descendant">
<label>Email</label>
<input type="email" required>
</div>
<label class="label-with-input label-with-input--adjacent">
<span>Tel</span>
<input type="tel" required>
</label>
<label class="label-with-input label-with-input--descendant">
<span>Birthday</span>
<input type="date" required>
</label>
<div>
<input type="submit" value="Submit">
</div>
</form>
<style>
:root {
background-color: #fcfcfc;
}
form {
width: 160px;
margin: 12px;
padding: 12px;
border: solid thin grey;
}
form > *:not(:first-child) {
margin-top: 4px;
}
.labeled-input > label,
.label-with-input,
.label-with-input > span {
display: block;
}
.labeled-input.labeled-input--adjacent
> label:has(+ input:required)::after {
content: "*";
color: red;
}
.labeled-input.labeled-input--descendant:has(> input:required)
> label::after {
content: "*";
color: blue;
}
.label-with-input.label-with-input--adjacent
> span:has(+ input:required)::after {
content: "*";
color: green;
}
.label-with-input.label-with-input--descendant:has(> input:required)
> span::after {
content: "*";
color: orange;
}
</style>
実際の Safari での表示が以下のようになります。
それぞれ required
となるラベルの右に *
マーカーがついているのが確認できます。
Vuetify の場合
おまけで仕事でよく使う Vuetify でも試してみました。
See the Pen Mark required fields with * in Vuetify by Kitagawa (@aster-mnch) on CodePen.
おわりに
最近各ブラウザでの :has()
擬似クラス対応が進んでいるため、今後はいろいろなサイトで使われていくかもしれません。
今回紹介した内容以外にもさまざまな使い方が以下のサイトで紹介されているので、気になった方は是非試してみてください。