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までは前者の方法しか認識しない。
よって、とくに理由がなければ前者の書き方が良いと思います。
そもそもなぜ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>
あるスクリーンリーダーでは、Tabキーを使って1番目のチェックボックス(label
要素なし)を選択しても「チェックボックス チェックナシ」としか読み上げられません。これでは、利用者は自分が今選択しているチェックボックスが何なのかを理解することができませんね。
一方、label
要素を使った2番目のチェックボックスでは、サヨナラゼツボウセンセイ チェックボックス チェックナシ
と読み上げられ、チェックボックスの内容を知ることができます。
また、晴眼者がマウスを利用する場合にも、label
要素を使っていればラベルをクリックすることでもコントロールを選択することができ、とくにチェックボックスやラジオボタンのようにコントロールが小さい場合には有用でしょう。
WCAG 2.0の実装方法集に沿って晴眼者向けの改善を行う
WCAG 2.0の「実装方法集」と言える「Techniques for WCAG 2.0」に、label
要素とCSSによるスタイルを組み合わせてフォームをアクセシブルにする方法が載っています。
- C15: Using CSS to change the presentation of a user interface component when it receives focus
- C15: CSSを用いて、ユーザーインタフェースコンポーネントがフォーカスを受けとったときの表示を変更する(
www.ciaj.or.jp
)(日本語訳)
この文書のExample 2: Highlighting elements that receive focusを実装してみると、こうなります。
- ちなみに、原文、日本語訳ともにHTML、CSSに1か所ずつ文法ミスがありますね。とくにCSSのミス(セミコロンであるべきところがコロンになっている)は致命的で、そのままコピペしただけでは正しく再現できません。
ラジオボタンにフォーカスすると、対応するラベル部分の背景色が黄色になります。多くのチェックボックスやラジオボタンが横並びになっているフォームで、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
要素を親要素で囲んで、それにスタイルを付けるのが良いと思います。
以上のことを踏まえたうえで、こんなスクリプトを作ってみました。
- なお、チェックボックスやラジオボタンの
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
要素へのスタイル付けはスクリプト無効環境向けです。
これでスクリプトが有効な環境では、該当のチェックボックスかラジオボタン、あるいはラベル上にカーソルが乗ったときやフォーカスを受けたときに背景色が変わり、分かりやすくなりました。