HTML のフォームコントロール要素と label 要素の紐づけ2021年12月24日 21時11分

この記事は HTML アドベントカレンダーの 24 日目の分、兼 JavaScript アドベントカレンダーの 24 日目の分です。


HTML のフォームコントロール要素 (inputtextareaselectbutton 要素など) には、label 要素を使ってラベルを指定できます。ここでいうラベルとは、そのフォームコントロールに何を入力するか・そのフォームコントロールで何ができるのかの簡単な説明であり、人間が読んで理解できるようなフォームコントロールの名前です。

ある label 要素の子孫にフォームコントロール要素が存在すれば、その label 要素の内容が、そのフォームコントロール要素のラベルとなります。そうでない場合、label 要素の for 属性にフォームコントロール要素の ID (id 属性の値) を指定する必要があり、その label 要素の内容が、その ID を持つフォームコントロール要素のラベルとなります。

このフォームコントロール要素と label 要素との紐づきは JavaScript を使って参照できます。フォームコントロール要素オブジェクトの labels プロパティはそのフォームコントロール要素と紐づく label 要素の一覧 (NodeList オブジェクト) を返し、label 要素オブジェクト (HTMLLabelElement オブジェクト) の control プロパティはその label 要素に紐づくフォームコントロール要素を返します。

labels プロパティの名前が複数形なのは、ひとつのフォームコントロール要素に対して複数の label 要素を紐づけられるからですね。

<label id="query-label-1" for="query-field">キーワード</label>
<label id="query-label-2" for="query-field">URL</label>
<input id="query-field" type="search" name="q">
const label1 = document.getElementById('query-label-1');
const label2 = document.getElementById('query-label-2');
const field = document.getElementById('query-field');

console.assert(label1.control === field, 'control プロパティでフォームコントロールを参照できる (1)');
console.assert(label2.control === field, 'control プロパティでフォームコントロールを参照できる (2)');
console.assert(field.labels[0] === label1, 'labels プロパティで label 要素を参照できる (1)');
console.assert(field.labels[1] === label2, 'labels プロパティで label 要素を参照できる (2)');

あるフォームコントロールにおいて、labels プロパティの返す NodeList オブジェクトは常に同一です。紐づく label 要素に変更があれば、その NodeList オブジェクトの内容が動的に変化します。

const oldLabels = field.labels;
label1.remove();
const newLabels = field.labels;

console.assert(oldLabels === newLabels, 'labels プロパティの値は何度参照しても同一のオブジェクトである');
console.assert(oldLabels.length === 1, 'labels プロパティの値は動的に変化する');

ただし、実際のところひとつのフォームコントロール要素に複数の label 要素を紐づけるような場面はほとんどないと思います。

button 要素にも label 要素を紐づけられます。しかしながら、button 要素の場合は自身の内容がラベルとして扱われるので (<button type="submit">検索する</button> なら「検索する」がそのボタンのラベルになります)、実際のところ button 要素に label 要素を紐づけるような場面はほとんどないと思います。

ラベルは aria-label 属性aria-labelledby 属性を使って指定することもできます。

<form action="/search">
  <p>
    <input type="search" name="q" aria-label="キーワード">
    <button type="submit" aria-label="検索する">🔍</button>
  </p>
</form>