フォームのユーザビリティを改善する10のTips
miyakeです。Webアプリケーションにおけるユーザーインタフェースの代表格と言えばフォーム。今日はそんなフォームのUIを作るに当たって、普段自分が心掛けていることをつらつらとご紹介します。
■チェックボックスやラジオボタンはfieldset,label要素でくくる
チェックボックスやラジオボタンには一般的にその内容を表すテキスト(ラベル)が付けられますが、input要素だけでマークアップした場合、チェックボックス(ラジオボタン)の部分しかクリックすることができません。
label要素を用いることで、ラベルの部分をクリックしてフォームを操作することが可能になります。これは是非設定しておきましょう。
ラベルをクリックできると思って期待を裏切られると、かなりのストレスになりかねません。
また、そのチェックボックスやラジオボタンのグループをfieldset要素で囲んでおくことをお勧めします。マークアップ的な理由というよりも、後からCSSでデザインをに手を入れる時に、CSSだけで対応できる範囲が広くなることのメリットが大きいです。
実際のHTMLは以下のようになります(紙面の都合上適宜改行していますが、実際は一行で書く方が安全です)。
<fieldset>
<input type="radio" id="fav1" name="favorite" value="1" />
<label for="fav1">犬好き</label>
<input type="radio" id="fav2" name="favorite" value="2" />
<label for="fav2">猫好き</label>
</fieldset>
以下、長いので続きを読むでどうぞ。
注)この部分、当初はlabel内にinputを入れていましたが、不適切ではないかとのご指摘をコメントにて頂き、修正しました。ご指摘ありがとうございました。また、fieldset要素を使用する場合、xhtmlの仕様ではfieldsetの後にlegend要素によるラベルを付けるべきであるとされていますが、本エントリでは省かせて頂きました。
また、はてなブックマークのコメントにて、「Safari2ではlabel部分をクリック出来ない」という情報を寄せて頂きました。確認したところ、確かにラベル部分をクリックしても選択できませんでした。未確認ですがSafari3では大丈夫だそうです。情報ありがとうございました。
■エラー時は class="error" を付ける
入力エラーがあった場合には、フォーム項目の脇にエラーメッセージを表示します(場合によってはページ上部にも)。この時、フォームの要素に対してエラーであることを表すクラスを指定し、CSSで装飾を施すことで「どの項目を入力し直す必要があるか」をユーザーに伝えます。
<p><input type="text" name="name" class="error" value="" /></p>
<p class="error">※お名前を入力してください。</p>
このようなHTMLを出力するようにプログラムを組んでおけば、
input.error {
background:#fc0;
}
こういったCSSでエラーがあった項目の背景に色を付けたりできます。
チェックボックスやラジオボタンの場合は、label要素やfieldset要素にもそれぞれ class="error" を指定しておきます。
input要素だけに付けた場合、チェックボックス(ラジオボタン)の部分だけしかスタイルが適用されません。また、Firefoxでは背景色の指定自体が効きません。

IEとFirefoxでフォームのCSS実装が異なる posted by (C)フォト蔵
labelやfieldsetに背景色を指定すると、ラベル部分も含めてスタイルを制御できます。プログラマ的には、「とりあえずエラーのクラス名を付けておいて細かいところはデザイナー任せ」というスタンスが妥当なところでしょぅか。
■ログインフォームはページ読み込み時にフォーカスさせる
メールアドレス(ID)とパスワードを入力してログインするような一般的なログインページではJavaScriptを使って、ページが表示された時に最初の項目をフォーカスするようにしておきます。
他にも色々なフォームがあって、その中の一つがログインフォームという場合はこの限りではありませんが、ログインすることが目的のページでは是非設定しましょう。
ちょっとしたことですが、一度この形式に慣れてしまうと、そうなっていないフォームにはストレスを感じてしまいます。
■大切なボタンは大きくする
画面設計にもよりますが、入力内容を確定するsubmitボタンなどを大きくすることでユーザビリティの向上が見込めます。
昔自分が担当していたシステムでバージョンアップのついでに確定ボタンを大きくしたら、追加機能よりもそちらを喜ばれたことがあります。
毎日ずっとネットに触れていると「キーボードでsubmitするから」とか思ってしまいがちですが、「入力はキーボードでするけど、最後のボタンはマウスでクリックする」という操作をする人も(自分のいた環境では)少なくありませんでした。
また、サイトのターゲット層によってはボタンだけでなく、他の項目の文字サイズや要素毎の余白も検討する価値があります。
■ボタンのテキストは「押したらどうなるか」が分かるように
ボタンには「登録」や「投稿」といった単語だけでなく、「この内容で登録する」「日記を投稿する」のように「そのボタンをクリックすることで何が起こるか」が伝わりやすいようなラベルを設定します。自分は「○○を○○する」といった文脈で書くことが多いですね。
「フォームに何かを入力して、submitボタンを押す」という行為は、特にPCに不慣れな人にとっては心理的な抵抗・プレッシャー、場合によっては恐怖感さえ感じるもののようです。
その根本には、「何が起こるか分からない不安」というのがあるようです。フォームのテキストに十分な情報を持たせることで、少しでもその不安を和らげることができればいいですね。
■画面遷移と現在位置をチャートなどで見せる
入力・確認・完了の3画面程度であれば必要性は薄いと思われますが、それ以上に画面遷移するようなフォームでは
- フォームの一連の処理でどれだけの画面があるか
- 今表示しているのはその中のどのページか
を示すナビゲーションを設置するのも一つの手です。通常のパンくずナビゲーションを設けている場合はそちらに組み込むのも手ですが、ECサイトなどでは購買のフローを明確にするために使われることがあります。
■フォーム要素の幅はCSSで指定する
input要素には幅を指定するsize属性がありますが、この指定では実際のところ狙い通りの幅で表示させるのは難しいです。input要素の幅はsize属性ではなく、CSSで指定することをお勧めします(幅の単位は要件に応じて)。
また、textarea要素には列数と行数を指定するcols,rows属性があります。こちらはDTD上必須の属性として定義されていますので、設定した上で幅だけを改めてCSSで指定してやるといいでしょう。cols属性だけで指定するとブラウザ間で幅を一定にできないようてす。
■全角英数字は必要に応じて半角に変換する
メールアドレスが全角で入力された場合、「半角英数字で入力してください」というエラーを出すよりも、サーバサイドで半角に変換してあげた方が親切です。
特にPCに不慣れな方が一所懸命メールアドレスを入力したのに、このエラーメッセージを突きつけられると心が折れる可能性は高いように思います。
設計ポリシーによっては難しいかも知れませんが、登録時は自動変換せずに半角だけを認め、その後のログインなどでは全角でも通るように変換する、といったアプローチも考えられます。
また、フリガナの入力などで半角カタカナを全角カタカナに変換する処理も入れておくといいかも知れません。全角ひらがな→全角カタカナの変換も可能ですが、そこまで対応するかは検討の余地があるでしょう。
■前後のスペースも必要に応じて削除する
メールアドレスやユーザーIDをコピー&ペーストで入力した時に、末尾にスペースが入ってしまってエラーになる場合があります。
入力された内容の先頭と末尾にあるスペースをシステム側で落としてやることで、こうした状況を防ぐことができます。
■郵便番号検索を付ける
フォームのユーザビリティと言うよりは、一つの機能になってしまうので詳細は省きますが、あると無いとで大きく利便性が変わってきます。郵便番号→住所の自動入力はもちろんですが、住所→郵便番号も引けるとより便利ですね。
フォームはユーザーとサイトをつなぐとても大切なインタフェースです。
が、プログラム的な要素とデザイン的な要素の両方が求められ、分業が発生しがちなこともあってか、望ましくない実装になっているフォームが多々見られます。
ここに挙げた項目は必ずしも全ての状況て正しいものではありません。また、内容的にも決して目新しい物ではありません
重要なのは、
- 自分のサイトのターゲットは誰なのか?
- その人達はフォームがどうなっていると嬉しいか?
ということを考えた上で、その都度最適な形を考えることだと思います。
実際の業務では様々な制約から理想的なフォームを追求するのが難しい部分もあるかと思いますが、本稿が皆さんのフォーム構築の一助になれれば何よりです。

コメント
サンプルで出されているXHTMLソースなんですが
labelにinputを含めると
IEではinput部分しか選択できませんよ。
投稿者: アベ | 2007年8月17日 11:48
コメントありがとうございます。
自分の手元だとIE6/7共に動いてるようなんですが、
こういう書き方だと問題あるんでしょうか?
DTD的にはlabel要素はlabel要素自身を除く%Inlineな要素
(#PCDATAとフォームコントロールを含む各種インライン要素)を
子に持てるはずなので問題ないと思っていたのですが、ひょっとして
自分の知らない不具合があるんでしょうか? 何かご存じでしたら
またコメントにてご指摘頂けるとありがたいです。
確かに、<label for="~">によるid指定をせずに、inputを子要素とする
ことで関連付けようとすると、IE5/6ではラベル部分がクリック出来ません。
サンプルではidの指定も入れているので大丈夫だと思うんですが…
なお、試してみたところ、IE7はid指定無しでも問題ないようです。
どうせid指定するなら外に出した方がクリック時のoutlineが
綺麗に見える、というのはあるかも知れません。IE6の問題で、
<label for="~">によるid指定が事実上必須な現状では、
labelの中にinputを入れるメリットも特にありませんし。
ちなみに、このクリック時のoutlineもIE7だと出ないみたいですね。
投稿者: miyake | 2007年8月17日 12:57
<label for="fav1">
<input type="radio" id="fav1" name="favorite" value="1" />犬好き
</label>
これおかしくないですか?
label for="fav1"としながら、fav1は自身に内包されている。
プログラムで言うと、再帰的に自身を呼んで永久ループって感じですかね。
投稿者: hori | 2007年8月18日 00:39
fieldset要素の中身は、 初めにlegend要素があるべきです。
投稿者: シマダ | 2007年8月18日 20:03
> horiさん
なるほど、今までそういう視点で見ていませんでしたが、
確かにinputに対するlabelにそのinput自身が含まれるのは
不適切だったかも知れません。
パーサの処理を考えると、labelがfav1に関連付いて、その中に
参照先のinputその物が含まれている状態でしょうか。inputがlabelを
参照する訳ではないので、無限ループにはないようにも思いますが、
fav1のラベルにfav1が含まれているのは確かに構造として不適切ですね。
labelの中にlabelを入れてはいけないのは、もしかしてこのような
循環参照が発生しないように、というのもあるのでしょうか。
「for属性を指定せず、label要素の中に含むことで関連を表す」
という挙動をむしろ例外的なものとして捉えた方がいいのかも知れません。
勉強になりました。ご指摘ありがとうざいます。
サンプルのソースも変更しておきます。
> シマダさん
ご指摘ありがとうございます。
本エントリがマークアップの正しさを追求するためではなく、
あくまでユーザー視点のユーザビリティ改善ということもあって
legend要素については書かなかったのですが、全く触れていない
のもよろしくありませんね(実は書く時に入れようか迷いました)。
実際の現場ではlegendの表示が不要なケースが多いと予想されること、
xhtmlのDTDでは直接規定されておらず、コメントで「should」とされている
のみであることを考慮して、補足という形で追記したいと思います
(前者はあくまで私見ですが)。
投稿者: miyake | 2007年8月19日 15:02
textarea要素のcols属性とrows属性がDTD上必須だとおっしゃっていたので、
それならばfieldset要素の中のlegend要素もDTD上必須だと思い先のコメントを残したのですが、
XHTMLのDTDではコメントにおいてlegend要素を含むべきとされているものの、 必須ではなかったのですね。
これは私の確認不足でした。 失礼しました。
投稿者: シマダ | 2007年8月20日 18:15
>これおかしくないですか?
「犬好き」というラベルをid=fav1のラジオボタンに結びつけるという意味づけですから、特におかしい点は無いですね。
ただしこのような場合は、ラベルに関連づけられるフォームコントロールが自明なので、for属性を伴わなくとも暗示的な関連づけとして成立する、ということです。(for属性で関連づけられるフォームコントロールの位置に制限はないからです)
が、ブラウザの挙動の問題を鑑みて、自明なうえでもさらに明示的な関連づけをしている、という状態かと思われます。
投稿者: SC | 2008年8月27日 15:11