MDN wants to learn about developers like you: https://www.surveygizmo.com/s3/5171903/MDN-Learn-Section-Survey-Recruiter-Pathway

基本から外れて、ここでは色々なフォームのパーツを構造化し、意味をつけるのに使われる要素を詳しく見ていきます。

前提条件: 基本的なコンピュータリテラシーと、HTML の基本的な理解。
目的: HTML フォームを構造化して意味を与えて使いやすくアクセシブルにする方法を理解すること。

HTML フォームは柔軟性があるため、HTML で最も複雑な構造の1つとなっています。専用のフォーム要素と属性を使用して、あらゆる種類の基本フォームを作成できます。HTML フォームを構築するときに正しい構造を使用すると、フォームが使用可能でアクセスしやすいことを確実にするのに役立ちます。

<form> 要素

<form> 要素はフォームを正式に定義するとともに、自身の属性でフォームの動作を定義します。HTML フォームを作成しようとするたびに、この要素から始めて、すべてのコンテンツをその中に入れなければなりません。多くの支援技術やブラウザプラグインは <form> 要素を検出でき、またフォームを使いやすくするための特別なフックを実装できます。

前の記事ですでにこれを見ています。

注記: フォームの中にフォームを入れ子にすることは厳格に禁じられています。これを行うと、ユーザが使用するブラウザによっては予期せぬ動作が発生するおそれがあります。

<form> 要素の外部でもフォームウィジェットを使用できますが、そのフォームウィジェットはどのフォームに対しても何も行わないことに注意してください。フォームの外部にあるウィジェットを使うと便利な場合もありますが、ウィジェット自身は何も行わないことから特別な設計が必要になります。フォームの動作を JavaScript でカスタマイズしなければなりません。

注記: 技術的には、HTML5 でフォーム関連要素に form 属性を導入しました。これは、実際には <form> に包含されていない要素であっても明示的にフォームへ紐付けることを可能にします。しかし当分の間、本機能は各ブラウザで使用できるほど十分に実装されてはいません。

<fieldset> および <legend> 要素

<fieldset> 要素は、スタイルや意味付けのために、同じ目的を持つウィジェットのグループの作成に便利です。<fieldset> 要素は、 <fieldset> タグのすぐ下に <legend> 要素を入れてラベルを付与できます。<legend> 要素は、<fieldset> 要素の目的を正式に説明します。

多くの支援技術は <legend> 要素を、対応する <fieldset> 要素内にある各ウィジェットのラベルの一部であるかのように扱うでしょう。例えば JawsNVDA といったスクリーンリーダーは、各ウィジェットのラベルを読み上げる前に legend の内容を読み上げます。

以下に小さなサンプルを挙げます:

<form>
  <fieldset>
    <legend>Fruit juice size</legend>
    <p>
      <input type="radio" name="size" id="size_1" value="small" />
      <label for="size_1">Small</label>
    </p>
    <p>
      <input type="radio" name="size" id="size_2" value="medium" />
      <label for="size_2">Medium</label>
    </p>
    <p>
      <input type="radio" name="size" id="size_3" value="large" />
      <label for="size_3">Large</label>
    </p>
  </fieldset>
</form>

: この例は fieldset-legend.html で見ることができます(ライブ版も見てください)。

この例では、スクリーンリーダーは最初のウィジェットを "Fruit juice size small"、2 番目を "Fruit juice size medium"、3 番目を "Fruit juice size large" と読み上げるでしょう。

このサンプルでのユースケースは、もっとも重要なことのひとつです。ラジオボタンのセットを置くたびに、それらを <fieldset> 要素内へ入れ子にするようにしましょう。ユースケースは他にもあり、通常は <fieldset> 要素でフォームを明確に区分するために使用できます。理想的には長いフォームは複数ページに分けるべきですが、フォームが長くなっても1つのページに収めないといけない場合、別々の関連セクションを別々の fieldset に入れることは使いやすさを改善します。

支援技術への影響力により、<fieldset> 要素はアクセシブルなフォームを作成するために重要な要素のひとつです。しかし、それを誤用しないようにするのはあなたの責務です。できれば、フォームを作成するたびにスクリーンリーダーがどのように解釈するか聞いてみましょう。変に聞こえるのであれば、フォームの構造を改善するためのよいヒントになります。

<label> 要素

これまでの記事で見てきたように、<label> 要素は、HTML フォームウィジェットのラベルを定義する正式な方法です。これは、アクセシブルなフォームを作成したい場合にもっとも重要な要素です — 適切に実装された時は、スクリーンリーダーはフォーム要素のラベルと関連する指示を一緒に読み上げます。前の記事で見てきたこの例を見てみます:

<label for="name">Name:</label> <input type="text" id="name" name="user_name">

 <label><input> とがそれぞれ forid 属性により正し関連付けられると (label の for 属性は対応するウィジェットの id 属性を参照します)、スクリーンリーダーは "Name, edit text"のように読み上げます。

label が正しくセットアップされていない場合、スクリーンリーダーは "Edit text blank" のように読み上げて、これはとても役立つものではありません。

ウィジェットは <label> 要素の中でネストできて、次のようになります:

<label for="name">
  Name: <input type="text" id="name" name="user_name">
</label>

この場合でも for 属性を設定することがベストプラクティスと考えられています。これは、label とウィジェットの暗黙的な関係を理解できない支援技術があるためです。

ラベルもクリック可能です!

ラベルをセットアップするもう一つの利点は、ユーザがラベルをクリックするとウィジェットをアクティブにすることが、あらゆるブラウザで可能になります。これは例えば、テキスト入力で、入力と同様にラベルをクリックしてフォーカスさせることができますし、ラジオボタンやチェックボックスで特に有用です — このコントロールのヒットエリアはとても小さく、できるだけ大きくしておくのは便利です。

例えば:

<form>
  <p>
    <input type="checkbox" id="taste_1" name="taste_cherry" value="1">
    <label for="taste_1">I like cherry</label>
  </p>
  <p>
    <label for="taste_2">
      <input type="checkbox" id="taste_2" name="taste_banana" value="1">
      I like banana
    </label>
  </p>
</form>

: この例は checkbox-label.html で見ることができます(ライブ版も見てください)。

複数のラベル

複数のラベルを持つウィジェットの扱いに問題がある支援技術があるかもしれません。このため、アクセシブルなフォームを作成するには対応する要素の内部にウィジェットを入れ子にするとよいでしょう。

以下のサンプルについて考えてみましょう:

<p>Required fields are followed by <abbr title="required">*</abbr>.</p>

<!-- ラベルをつける要素を label の子孫にすると、label で 'for' 属性を使用する必要はありません。-->
<!-- 2 つの例をご覧ください: -->
<div>
  <label for="username">Name:</label>
  <input type="text" name="username">
  <label for="username"><abbr title="required">*</abbr></label>
</div>

<!-- 前出の例よりは良いです: -->  
<div>
  <label for="username">
    <span>Name: </span>
    <input id="username" type="text" name="username">
    <abbr title="required">*</abbr>
  </label>
</div>

<!-- これが最も良いでしょう: -->
<div>
  <label for="username">Name: <abbr title="required">*</abbr></label>
  <input id="username" type="text" name="username">
</div>

このサンプルでは、最初の段落で入力必須の要素の規則を定義しています。ユーザが入力必須の要素を見つける前にスクリーンリーダーのような支援技術が注意事項を表示したり読み上げたりするためには、はじめに置かなければなりません。これにより、ユーザは何をしなければならないかを理解します。

  • 最初の例では、label 要素すべての入力が読み上げられません  — "edit text blank" だけです。その上に実際のラベルは別々に読まれます。複数の <label> 要素はスクリーンリーダーを混乱させます。
  • 2 つ目の例では、少し明確になります "name star name edit text" というようにラベルが入力と一緒に読み上げられます。しかしラベルはまだ別々に読み上げられます。少し混乱しやすいですが、これは入力と関連したラベルがあるのまだ良いでしょう。
  • 3 つ目の例が最も良いです — 実際のラベルがすべて一緒に読み上げられ、 "name star edit text" のようにラベルと入力が一緒に読み上げられます。

: スクリーンリーダーによっては、少し異なる結果になる場合もあります。これは VoiceOver (と同様に動作する NVDA)でテストしています。あなたの体験を聞きたいです。

: この例は GitHub の required-labels.html で見ることができます(s ライブ版も見てください)。2 や 3 のコメントを外したバージョンの例を実行しないでください — 複数の label と複数の同じ input ID があると、スクリーンリーダーは確実に混乱します!

フォームで使用される一般的な HTML 構造

HTML フォーム特有の構造の前提として、フォームは単に HTML であると覚えておくとよいでしょう。つまり、HTML フォームを組み立てるために HTML のすべての力を利用できるのです。

サンプルでわかるように、ラベルとそのウィジェットを <div> 要素で包み込むのが一般的な慣習です。HTML リストにあるように、<p> 要素も良く使われます(後者は複数のチェックボックスやラジオボタンを構造化するのに最もよく使われます)。

<fieldset> 要素に加えて、複雑なフォームの構築に HTML の見出し (例<h1>, <h2>) やセクション (例 <section>) を使うことも一般的です。

とりわけ、コードがどうあるのが心地よいかのや、どれがアクセシブルで使いやすいフォームとなるのかを見つけるのはあなた次第です。

これは<section> 要素に含まれる機能セクションと、ラジオボタンを含む <fieldset> にそれぞれ分かれています。

アクティブラーニング: フォーム構造を構築する

これらのアイデアを実践し、もう少し複雑なフォーム構造、つまり支払いフォームを作成しましょう。このフォームはあなたがまだ理解していないかもしれないウィジェットタイプをいくつも含みますが、今はそのことを心配しないでください。次の記事 (ネイティブフォームウィジェット) でそれらがどのように機能するのかがわかります。今のところ、以下の説明に沿って説明を注意深く読み、フォームを構成するためにどのラッパー要素を使用しているか、そしてその理由を理解することから始めてください。

  1. あらかじめ、空のテンプレートファイルお支払いフォームの CSS のローカルコピーをコンピュータの新しいディレクトリに作成します。
  2. まず最初に、HTML <head> 内に次の行を追加して CSS を HTML に適用します。
    <link href="payment-form.css" rel="stylesheet">
  3. 次に、外側の <form> 要素を追加してフォームを作成します。
    <form>
    
    </form>
  4. <form> タグ内に、必須フィールドにマークを付ける方法をユーザに通知するための見出しと段落を追加することから始めます。
    <h1>Payment form</h1>
    <p>Required fields are followed by <strong><abbr title="required">*</abbr></strong>.</p>
  5. 次に、前のエントリの下に、より大きなコードセクションをフォームに追加します。ここでは、連絡先情報フィールドを個別の <section> 要素内にラップしていることがわかります。さらに、2つのラジオボタンのセットがあり、それぞれ独自のリスト (<li>) 要素の中に入れています。最後に、2つの標準テキスト <input> とそれに関連する <label> 要素があり、それぞれ <p>の内側に含まれています。パスワードを入力するためのパスワード入力。 今すぐフォームにこのコードを追加してください:
    <section>
        <h2>Contact information</h2>
        <fieldset>
          <legend>Title</legend>
          <ul>
              <li>
                <label for="title_1">
                  <input type="radio" id="title_1" name="title" value="M." >
                  Mister
                </label>
              </li>
              <li>
                <label for="title_2">
                  <input type="radio" id="title_2" name="title" value="Ms.">
                  Miss
                </label>
              </li>
          </ul>
        </fieldset>
        <p>
          <label for="name">
            <span>Name: </span>
            <strong><abbr title="required">*</abbr></strong>
          </label>
          <input type="text" id="name" name="username">
        </p>
        <p>
          <label for="mail">
            <span>E-mail: </span>
            <strong><abbr title="required">*</abbr></strong>
          </label>
          <input type="email" id="mail" name="usermail">
        </p>
        <p>
          <label for="pwd">
            <span>Password: </span>
            <strong><abbr title="required">*</abbr></strong>
          </label>
          <input type="password" id="pwd" name="password">
        </p>
    </section>
  6. それでは、フォームの2番目の <section> — 支払い情報に目を向けます。ここには3つの異なるウィジェットとそのラベルがあり、それぞれ <p> の中に含まれています。1つ目は、クレジットカードの種類を選択するためのドロップダウンメニュー (<select>) です。2番目は、クレジットカード番号を入力するための number 型の <input> 要素です。最後のものは、カードの有効期限を入力するための date 型の <input> 要素です (これは、サポートしているブラウザでは日付選択ウィジェットが表示され、サポートしていないブラウザでは通常のテキスト入力に戻ります)。もう一度、前のセクションの下に次のように入力します。
    <section>
        <h2>Payment information</h2>
        <p>
          <label for="card">
            <span>Card type:</span>
          </label>
          <select id="card" name="usercard">
            <option value="visa">Visa</option>
            <option value="mc">Mastercard</option>
            <option value="amex">American Express</option>
          </select>
        </p>
        <p>
          <label for="number">
            <span>Card number:</span>
            <strong><abbr title="required">*</abbr></strong>
          </label>
          <input type="text" id="number" name="cardnumber">
        </p>
        <p>
          <label for="date">
            <span>Expiration date:</span>
            <strong><abbr title="required">*</abbr></strong>
            <em>formatted as yyyy/mm/dd</em>
          </label>
          <input type="text" id="date" name="expiration">
        </p>
    </section>
  7. 最後に追加するセクションはもっと単純で、フォームデータを送信するための submit タイプの <button> のみを含みます。これをフォームの一番下に追加してください。
    <p> <button type="submit">Validate the payment</button> </p>

You can see the finished form in action below (also find it on GitHub — see our payment-form.html source and running live):

完成したフォームは以下のように動作しています (GitHub でも確認できます。payment-form.html ソースを参照してライブ実行してください)。

おわりに

HTML フォームを適切に構築するためのあらゆる知識を得ることができました。次の記事では、ユーザから情報を集めるのに使いたくなすべての種類のフォームウィジェットの詳細な実装ついて詳しく見ていきます。

関連情報

このモジュール

ドキュメントのタグと貢献者

最終更新者: silverskyvicto,