0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

:has() 擬似クラスを使って CSS だけで必須フィールドのラベルに * マーカーを付ける

Last updated at Posted at 2022-04-23

フォームの表現でよく見られる、必須フィールドとなるラベルに * のようなマーカーを付ける方法について、 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> で囲うような構造にしています。

サンプルコード

上の各方法で実装したサンプルコードが以下です。
セレクタの指定をいくつか変えています。

Sample Form
<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 となるラベルの右に * マーカーがついているのが確認できます。

sample_form.png

Vuetify の場合

おまけで仕事でよく使う Vuetify でも試してみました。

See the Pen Mark required fields with * in Vuetify by Kitagawa (@aster-mnch) on CodePen.

おわりに

最近各ブラウザでの :has() 擬似クラス対応が進んでいるため、今後はいろいろなサイトで使われていくかもしれません。
今回紹介した内容以外にもさまざまな使い方が以下のサイトで紹介されているので、気になった方は是非試してみてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?