HTMLフォームのプルダウンにselected属性を付けるべき理由

公開日:

HTMLでフォームを作った際、プルダウンやリストボックスにdisabled属性を設定したときの挙動がブラウザによって異なるのが興味深かったのでまとめてみます。

option要素、optgroup要素のdisabled属性

input要素やtextarea要素などのフォームコントロールには、それを無効にするdisabled属性(www.w3.org)があります。

変更を不可にするreadonly属性と異なり、入力・選択ができなくなるだけでなく、フォーカスが合うことはなく、値の送信も行われません。たとえば次のフォームを送信した場合、 form.php には foo=hoge&baz=fuga しか送られません。

<form action="form.php">
  <p><input name="foo" value="hoge" /></p>
  <p><input name="bar" value="piyo" disabled="disabled" /></p>
  <p><input name="baz" value="fuga" readonly="readonly" /></p>
  <p><button type="submit">送信</button></p>
</form>

ところが、プルダウンやリストボックスの場合はdisabled属性に対応していなかったり、挙動のおかしなブラウザが存在します。

option要素に設定した場合、optgroup要素に設定した場合など4パターンにてテストしてみます。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<title>プルダウンやリストボックスにdisabled属性を設定してみる</title>
</head>
<body>
<form action="">
  <p>
    <select name="s1" id="s1">
      <option value="0" disabled="disabled">選択不能</option>
      <option value="1">選択可</option>
    </select>
    <label for="s1">option要素にdisabled属性を設定</label>
  </p>
  <p>
    <select name="s2" id="s2" multiple="multiple">
      <option value="0" disabled="disabled">選択不能</option>
      <option value="1">選択可</option>
    </select>
    <label for="s2">option要素にdisabled属性を設定(multiple)</label>
  </p>
  <p>
    <select name="s3" id="s3">
      <optgroup label="グループ1" disabled="disabled">
      <option value="0">選択不能</option>
      </optgroup>
      <optgroup label="グループ2">
      <option value="1">選択可</option>
      </optgroup>
    </select>
    <label for="s3">optgroup要素にdisabled属性を設定</label>
  </p>
  <p>
    <select name="s4" id="s4" disabled="disabled">
      <option value="0">選択不能</option>
    </select>
    <label for="s4">select要素にdisabled属性を設定</label>
  </p>
  <p><button type="submit">送信</button></p>
</form>
</body>
</html>
図1:Firefox13 の表示
図2:iPhone4(Safari) の表示

このHTMLを、PCとスマートフォンの代表的なブラウザで表示させた場合の違いを表にしました。ただし、4つ目の「select要素にdisabled属性を設定」したものは、いずれのブラウザもコントロールごと無効になったので省略します。

Firefox13, IE8以降Chrome19Safari5.1Opera12iPhone, iPadAndroid
option要素にdisabled属性disabledな選択肢は無効となり、有効なうち最初のものが初期選択Fx, IEと同じ最初の選択肢がdisabledでも初期選択されるが、そのまま送信しても値は送られないFx, IEと同じdisabledな選択肢も選択可能だが、その場合は値は送られない最初の選択肢がdisabledでも初期選択され、そのまま送信すると値が送られる (いちど選択を外すと二度と選択できない)
multipleなoption要素にdisabled属性disabledな選択肢は無効となるFx, IEと同じFx, IEと同じFx, IEと同じoption要素に設定した場合と同じFx, IEと同じ
optgroup要素にdisabled属性option要素に設定した場合と同じdisabledな選択肢は無効とならず、値も送られるoption要素に設定した場合と同じ最初の選択肢がdisabledでも初期選択され、そのまま送信すると値が送られる (いちど選択を外すと二度と選択できない)option要素に設定した場合と同じoption要素に設定した場合と同じ (Operaと同じ)
上記HTMLで何も変更せずボタンを押した時の送信データs1=1&s3=1s1=1&s3=0(なし)s1=1&s3=0(なし)s1=0&s3=0

主な注目点をまとめてみます。

  • FirefoxとIEの動作には、不自然な点は見当たらない
  • Google Chromeは、optgroup要素に対するdisabled属性に対応していない
  • iPhoneやiPadのSafariは、disabledな選択肢も選択できるが、その場合は値は送信されない
  • (表には含めていないが)IE7以前は、option要素とoptgroup要素に対するdisabled属性に対応していない。select要素に設定した場合を除き、未設定時と同じ状態になる。

と、このようにブラウザによって表示や挙動がまちまちです。しかしながら、そもそも一部要素に対するdisabled属性の指定が無視されるGoogle ChromeやIE7以前は別として、これらはブラウザの実装が貧弱なわけではなく、先に挙げたHTMLにも問題があります[1]

option要素のselected属性

option要素にselected属性を設定すると、初期状態で選択済み状態になりますが、HTML4.01では次のような記述があります。

If no OPTION element has the selected attribute set, user agent behavior for choosing which option is initially selected is undefined.

(中略)

authors should ensure that each menu includes a default pre-selected OPTION.

すなわち、select要素には必ず1つはselected属性の付いたoption要素がないといけないのです。なお、ラジオボタンも同じような規定(www.w3.org)があり、1つchecked属性を設定しなければなりません。

実際のブラウザの動作を見ると、checked属性のないラジオボタンはいずれも選択されない状態となる一方、selected属性のないプルダウンは一番目の選択肢が選択されるケースが多いので、たまたま一番目がデフォルト値な場合はselected属性が書かれないケースが多い気がします。いずれにしても、プルダウンのoption要素には必ずひとつselected属性を付けるようにしましょう。SafariやOpera、Android標準ブラウザでは先に挙げたような問題がなくなります。

ただし、Google Chromeがoptgroup要素のdisabled属性に対応していなかったり、iPhoneやiPadのSafariでdisabledな選択肢も選択できてしまう問題は解決しません。可能であればJavaScriptでDOMから除去してしまうのが良いと思います。

  • [1]とはいえiPhone, iPadの挙動はどう考えてもおかしいと思います。