label要素を使っていることを分かりやすく知らせる工夫

ウェブフォームを作成するとき、フォームコントロールが何を指すのかを示すためにlabel要素を使います。

使い方は2つの方法があり、一つはコントロールのIDと同じ値をlabel要素のfor属性に設定するもので、次のようにします。

<label for="name">名前</label>
<input name="name" id="name" />

もう一つは、ラベル文言とコントロールをlabel要素の中に入れるもので、次のようにします。

<label>名前<input name="name" /></label>

一見、後者の方がシンプルで良いような気がしますが、次のような問題があります。

  • label要素の中身はインライン要素しか入れられないので、HTMLの構造に制約ができてしまう。とくに、legend要素内にlabel要素を、fieldset要素直下にフォームコントロールを、といったようにフォームを構造化することが難しい。
  • IE6までは前者の方法しか認識しない。

よって、とくに理由がなければ前者の書き方が良いと思います。

  1. そもそもなぜlabel要素が必要なのか
  2. WCAG 2.0の実装方法集に沿って晴眼者向けの改善を行う
  3. label要素を使っていること自体を分かりやすく知らせる

そもそもなぜlabel要素が必要なのか

§

label要素を使うことにより、構造上の紐付けができることとなります。たとえば次のようなHTMLの場合。

<form action="">
<fieldset>
<legend>次のうち好きな作品は?</legend>
<ul>
<li><input type="checkbox" name="kaizo" value="1" />かってに改蔵</li>
<li><input type="checkbox" name="szbs" id="szbs" value="1" /><label for="szbs">さよなら絶望先生</label></li>
</ul>
</fieldset>
</form>
label要素ありなしの2つのチェックボックスを表示したところ

あるスクリーンリーダーでは、Tabキーを使って1番目のチェックボックス(label要素なし)を選択しても「チェックボックス チェックナシ」としか読み上げられません。これでは、利用者は自分が今選択しているチェックボックスが何なのかを理解することができませんね。

一方、label要素を使った2番目のチェックボックスでは、サヨナラゼツボウセンセイ チェックボックス チェックナシと読み上げられ、チェックボックスの内容を知ることができます。

また、晴眼者がマウスを利用する場合にも、label要素を使っていればラベルをクリックすることでもコントロールを選択することができ、とくにチェックボックスやラジオボタンのようにコントロールが小さい場合には有用でしょう。

WCAG 2.0の実装方法集に沿って晴眼者向けの改善を行う

§

WCAG 2.0の「実装方法集」と言える「Techniques for WCAG 2.0」に、label要素とCSSによるスタイルを組み合わせてフォームをアクセシブルにする方法が載っています。

この文書のExample 2: Highlighting elements that receive focus(W3C) を実装してみると、こうなります。

  • ちなみに、原文、日本語訳ともにHTML、CSSに1か所ずつ文法ミスがありますね。とくにCSSのミス(セミコロンであるべきところがコロンになっている)は致命的で、そのままコピペしただけでは正しく再現できません。
C15 の Example 2 を表示してみたところ

ラジオボタンにフォーカスすると、対応するラベル部分の背景色が黄色になります。多くのチェックボックスやラジオボタンが横並びになっているフォームで、Tabキーで選択を進めていった場合、今選択しているコントロールのラベルは右か左か分からなくなることがあるので、こういった配慮があると嬉しいですね。

選択したチェックボックスのラベルは左右どちらか迷ってしまう例

label要素を使っていること自体を分かりやすく知らせる

§

実はここからがこの記事の本題なのですが【遅】、現実にはlabel要素を使っていないページが数多く存在します。そのため、マウスを使うユーザーがフォームを目にしたとき、「このラベルをクリックしても反応しないかもしれない」と考え、結局コントロールをクリックするということはないでしょうか。私はあります。

ブラウザがデフォルトの機能として、label要素を使っている場合にクリックの有効範囲を示してくれればよいのでしょうが、現状そのようなブラウザはないようなので、実装してみます。要目はこんな感じ。

  • フォームコントロールやラベル上をカーソルが通過したときに、ラベルの背景色を変えるなど何らかの変化を起こす。
  • Tabキーなどでのフォーカス時にも同様の変化を起こす。
  • ラベルだけでなく、チェックボックスやラジオボタンも含めて背景を変えた方が、コントロールとラベルが紐付いていることが直感的に伝わるのではないか。

ただし注意点として、チェックボックスやラジオボタンのinput要素に背景色を指定する、すなわちこんなCSSを書いた場合、

label, input[type="checkbox"], input[type="radio"] {
  background-color: #F90;
}
  • Firefox 3.6, Safari 5, Google Chrome 5 では、チェックボックスやラジオボタンには全く効果が現れない。
  • Opera 10.6 ではチェックボックスの四角やラジオボタンの丸の内側のみ背景色が付く。
  • IE 7, 8 ではチェックボックスやラジオボタンの周囲に背景色が付くが、フォントサイズによってはラベル部分との背景位置や高さに差異が生じてしまう。

と、このようにブラウザによって表現が異なるうえに、どれも美しくないので、input要素とlabel要素を親要素で囲んで、それにスタイルを付けるのが良いと思います。

Firefox 3.6, Opera 10.6, IE 8 の表示例

以上のことを踏まえたうえで、こんなスクリプトを作ってみました。

  • なお、チェックボックスやラジオボタンのinput要素の直後にlabel要素があるHTMLを想定しています。HTMLの構造が異なる場合は改造が必要です。

JavaScript

§

  • コードを読んでいただければ分かると思いますが、jQuery(jquery.com) が必要です。この記事を書いている時点で最新のバージョン1.4.2で動作確認しています。

2010年10月7日追記オブジェクト指向を取り入れて改造してみました。JavaScriptのオブジェクト指向は慣れていないので、癖があったりするかもしれませんが…。

jQuery(function($) {
  var hoverClass = "hover"; // ラベルの親要素にカーソルが乗ったときに付けるクラス名
  var focusClass = "focus"; // ラベルの親要素がフォーカスを受けたときに付けるクラス名

  var form = new Form();
  $(":checkbox, :radio, :checkbox + label, :radio + label").mouseover(function() {
    // チェックボタン、ラジオボタン、またはそれらのラベルにカーソルが乗ったとき
    form.over($(this), hoverClass);
  });
  $(":checkbox, :radio, :checkbox + label, :radio + label").mouseout(function() {
    // チェックボタン、ラジオボタン、またはそれらのラベルからカーソルが離れたとき
    form.out($(this), hoverClass);
   });
  $(":checkbox, :radio").focus(function() {
    // チェックボタン、ラジオボタンがフォーカスを受けたとき
    form.over($(this), focusClass);
  });
  $(":checkbox, :radio").blur(function() {
    // チェックボタン、ラジオボタンがフォーカスを失ったとき
    form.out($(this), focusClass);
  });
});

var Form = function() {
  this.onload();
};
Form.prototype = {
  /* ページロード時にチェックボックスとラジオボタンに対して、親要素で囲む */
  onload: function() {
    $(":checkbox, :radio").each(function() {
      var input = $(this);
      var label = input.next();
      var parent = input.parent();
      var group = $("<span/>");
      group.append(input);
      group.append(label);
      parent.append(group);
    });
  },
  /* カーソルが乗るかフォーカスを得たときにクラス名を付ける */
  over: function(ctr, className) {
    var parent = ctr.parent("span");
    parent.addClass(className);
  },
  /* カーソルが離れるかフォーカスを失ったときはクラス名を削除する */
  out: function(ctr, className) {
    ctr.parent("span").removeClass(className);
  }
};

CSS

§

input[type="checkbox"]:hover + label,
input[type="checkbox"] + label:hover,
input[type="radio"]:hover + label,
input[type="radio"] + label:hover,
form span.hover {
  background-color: #FF6;
}

input[type="checkbox"]:focus + label,
input[type="radio"]:focus + label,
form span.focus {
  background-color: #FC6;
}
  • label要素へのスタイル付けはスクリプト無効環境向けです。

これでスクリプトが有効な環境では、該当のチェックボックスかラジオボタン、あるいはラベル上にカーソルが乗ったときやフォーカスを受けたときに背景色が変わり、分かりやすくなりました。

チェックボックスのラベル上にカーソルが乗ったときの例
チェックボックスがフォーカスを受けたときの例