ノベルティメディア

media

Next.jsでのフォーム実装とアクセシビリティ対応の考え方

Next.jsでのフォーム実装とアクセシビリティ対応の考え方

こんにちは。ノベルティの高宮です。

今回はNext.jsを使ってアクセシビリティに配慮したフォームの実装方法やアクセシビリティ対応の考え方について紹介します。

モダンな言語でのフォーム実装をしながらアクセシビリティの考え方について詳しく解説していますのでぜひ参考にしてみてください。

今回のコラムでわかること

  • Reactでフォームを実装する方法
  • アクセシビブルなフォームを実装する方法

アクセシビリティに配慮したフォーム実装のポイント

今回は、フォームを様々な使い方でも使えるようにするために以下のポイントを意識して実装しました。

  • キーボードだけで操作することができる
  • スクリーンリーダーや支援デバイスを用いて入力内容、形式、説明、エラーを読み取ることができる
  • 入力形式(全角・半角など)、文字数、使用できる文字の制限などでエラーが起きる場合は、ユーザーが入力する前に説明する
  • エラーが起きたときに起きた箇所を明示して、修正方法を説明する

コードの全体像と完成形のフォームはこちらです

今回、Next.jsで実装した理由としては、HTMLとJavaScriptではコード量が長くなり可読性が落ちることと、DOM操作がかなり大変になるかと思ったからです。

また、WordPressのプラグインやフォームサービス等はデフォルトでマークアップされており、アクセシビリティ対応できない箇所があるのでは?と思いNext.jsで実装しています。レンダリングの制御などはしていないので、Reactのみでも大丈夫です。

バリデーションチェックはReact Hook FormとZodを使うほうが簡単で柔軟にチェックできますが、今回は趣旨と外れるので力技で行っています。

具体的な実装方法を解説していきます

それでは具体的なフォームのアクセシビリティ対応をコードも含めて説明していきます。

ラベルとフォームコントロールを関連付ける

ラベルとはフォームコントロール(テキスト入力ボックス、チェックボックス、ラジオボタンなど)にどのような情報を入力すればいいのかを認識させる文言を指します。

なぜ関連付けることが大切かというと、障害をもつユーザが情報を適切に入力したり、必要な操作をしたりすることが困難になる可能性があるからです。

一つ例を見てみましょう。

以下のようなテキストボックスがあったとします。

視覚に障害のない人がこれを見れば何を入力すべきか、すぐに分かるかと思います。

しかし、実際に視覚に障害のある方と同じようにスクリーンリーダーを使ってこのテキストボックスを操作してみます。

すると「テキストボックスをフォーカスしていて、そのテキストボックスには何も入力されていない」という情報しかわかりません。

これでは何を入力していいのかも必須項目であることもわかりません。これがお問い合わせフォームであれば、このユーザーはお問い合わせをすることもできないのです。

ユーザー適切に情報を入力し、正しく操作できるようにラベルとフォームコントロールを関連付ける必要があります。

実際に関連付けると以下のように名前を入力することと必須項目であることを伝えることができます。

実装の仕方は関連付けたいlabel要素のhtmlFor属性とinput要素のidに同一のフィールドをいれます。

<div className={styles.formItem}>
    <label htmlFor="name" className={styles.title}>お名前<span aria-hidden>必須</span></label>
    <input id="name" type="text" name="name" required aria-required autoComplete="off"/>
</div>

※autoComplete=”off”はスクリーンショットを撮る際に余計な情報が写ってしまうため設定していました。本来は外します。

この例では、テキストボックスに「お名前」というラベルを関連付けるために”name”という同一のフィールドを入れることで関連付けています。

required属性 はこのテキストボックスが必須項目であることを示す属性です。aria-required属性 はテキストボックスが必須項目であることをスクリーンリーダーやその他の支援デバイスに示すことができる属性です。

required属性とaria-required属性は本来どちらか一つで良いみたいですが、デバイスやスクリーンリーダーによってはreqeired属性を読み取ってくれないものがあるようなので、できるだけ多くのデバイス、スクリーンリーダーに対応するために2つつけています。

ラベルとグループを関連付ける

今回はグループは利用していませんが、ラジオボタンやチェックボックスなど、グループの場合のラベル付けについても説明します。

<fieldset className={styles.formItem}>
  <legend className={styles.title}>お問い合わせ項目</legend>
  <label><input type="checkbox" name="contact" value="お問い合わせ項目1" />お問い合わせ項目1</label>
  <label><input type="checkbox" name="contact" value="お問い合わせ項目2" />お問い合わせ項目2</label>
  <label><input type="checkbox" name="contact" value="お問い合わせ項目3" />お問い合わせ項目3</label>
</fieldset>

グループにラベルを関連付けるにはグループ全体をfieldset要素で囲み、グループのラベルをlegend要素でマークアップします。

このようにマークアップすることで、一番最初のチェックボックスをフォーカスした際にスクリーンリーダーがグループのラベルを読み上げてくれます。

基本的には上記の方法でラベル付けをすることが望ましいのですが、仕様上label要素やfieldset要素が使えない場合もあるかと思います。

その場合はaria-labelledby属性を用いることでdiv要素span要素でも実装することができます。

ここでは長くなるので省略しますが、興味のある方は調べてみてください。

ラベルを関連付ける際のよくない実装例

次にラベルを関連付ける際に良くないとされている実装例について解説します。

例1:プレースホルダーをラベルの代わりにする

placeholder属性をlabel要素の代わりに使うことには、いくつかの問題点があります。

一点目はユーザーが入力を開始すると、プレースホルダーが消えてしまうため、何を入力すべきかわからなくなる可能性がある点です。

多くのスクリーンリーダーはプレースホルダーの内容を読み上げないため、視覚に障害のあるユーザーはテキストコントロールに何を入力したらいいか理解することができません。

また、プレースホルダーの内容を常に覚えておかないといけないため、視力に障害がなくても高齢者や学習障害、記憶障害のある人には負担の大きいフォームになってしまいます。

二点目はプレースホルダーの色が薄いことです。

プレースホルダーの色は入力済みのテキストとの差別化を図るために薄くデザインされていることがほとんどです。

input要素の背景とのコントラスト比が低く、見づらい傾向にあるので、こちらも高齢者や弱視や色覚異常の人が何を入力すべきか見えない場合があります。

これらの問題から、プレースホルダーをラベルの代わりにするのではなく、label要素やaria-labelledby属性を用いてラベルと関連付けましょう。

例2:入力内容の説明をlabel外に配置している

全角、半角、文字数などの説明はフォームコントロールの後ろではなく、ラベル内に設置しましょう。

説明が関連付けられていないとユーザーは説明の存在に気づけずに入力してしまい、エラーを回避できない可能性があるので入力内容だけでなく、説明もlabel内にマークアップして関連付けをしましょう。

例3:必須項目を表す「※」を説明せずに使っている

「※」は視覚的にははっきりと示せますが、誰もが必須項目であると理解できる記号ではありません。

特にアイコンは国によって捉え方や意味が異なるので外国人にもわかりにくいデザインであると言えます。

当然、スクリーンリーダーを使っているユーザーには必須であることは理解できません。

仕様の関係上、「必須」というテキストが使えないのであれば、フォーム上部に「※」が入力必須であることを示しておくのもいいかと思います。

エラーメッセージも対応すべき項目は多岐にわたりますが「エラーとなっている箇所が特定され、そのエラーがユーザーにテキストで説明される」ことを目的に実装します。

スクリーンリーダーでスクリーンリーダーで読めるように入力内容や説明と同様にエラーメッセージもlabel内に設置します。

 <div className={styles.formItem}>
          <label htmlFor="name" className={styles.title}>
            お名前
            <span className={styles.required} aria-hidden>必須</span>

            //ここ!
            {error.name && <span className={styles.errorMessage}>{error.name}</span>}


          </label>
          <input id="name" type="text" name="name" required aria-required value={name} onChange={handleNameChange} aria-invalid={error.name ? "true" : "false"} />
        </div>

label内に設置することで、どのフォームコントロールに対するエラーメッセージなのかを関連付けられ、スクリーンリーダーでも読み取ることができます。

エラー発生時にフォームコントロールにaria-invalid=”true”を付与する

aria-invalid=”true”は、スクリーンリーダーやその他の支援技術に対して、フォームコントロールの入力がエラーであることを伝えるために使用されます。

視覚的にエラーを確認できないユーザーでも、問題のある入力を修正することが可能になります。

今回の実装ではフォームコントロールが編集されるたびにバリデーションチェックを行い、その結果に応じてaria-invalid属性のtrueとfalseを出し分けています。

 <div className={styles.formItem}>
          <label htmlFor="name" className={styles.title}>
            お名前
            <span className={styles.required} aria-hidden>必須</span>
            {error.name && <span className={styles.errorMessage}>{error.name}</span>}
          </label>
          <input 
            id="name"
            type="text"
            name="name"
            required
            aria-required
            value={name}
            onChange={handleNameChange}

            //ここaria-invalid={error.name ? "true" : "false"}
          />
        </div>

エラーの修正方法をわかりやすく説明する

エラーメッセージは、できる限りわかりやすい内容にします。

「必須項目です」「エラーがあります」といった内容では、どのように修理すべきかがわからない可能性があります。

少なくともエラーになった項目名と修正方法は説明できるといいでしょう。

送信ボタンはaria-disabled属性を使って活性・非活性を制御する

送信ボタンのよくある実装として初期値にdisabledを設定しておき、必須項目をすべて入力したタイミングでdisabledを外すといった実装があるかと思います。

しかし、disabled属性はスクリーンリーダーでは検知することができずフォーカスすることもできないので、スクリーンリーダーなどの支援デバイスを使っているユーザーにとっては存在しないものになってしまいます。

代わりにに使用するのがaria-disabled属性です。

aria-disabled属性はフォーカスすることができるうえ、スクリーンリーダでは無効なボタンを表す「淡色表示(ツールによる)」というテキストを読み上げてくれます。

<div className={styles.submitBtnContainer}>
  <input
    type="submit"
    value="送信する"
    className={styles.submitBtn}
    
    //ここaria-disabled={isDisabled ? "false" : "true"}
  />
</div>

disabled属性とは違い、クリックすることができますが、クライアントサイド、サーバサイド側でバリデーションチェックを行えば問題ありません。

また、Webアクセシビリティについてガイドラインを制定している企業のサイト(三井住友銀行やfreee、花王など)を見てみるとdisabled属性は使わず、送信ボタンを常に有効にしておき、フォーム送信後にエラーメッセージをまとめて表示しているところが多いように感じています。

今回すべての入力項目が正しく入力されたらaria-disabled属性を削除し、それ以外ではaria-disabled属性を付与する実装にしています。

ここまで実装すればアクセシビリティに配慮されたフォームの完成です。

まとめ

これでNext.jsを使ったアクセシビリティに配慮したフォームの実装方法についての解説は終了です!

ノベルティではアクセシビリティ、ユーザビリティに配慮した実装やJamstackでのサイト制作にも力をいれていますので、ぜひお任せください!

興味のある方はお問い合わせを!

参考資料

ウェブアクセシビリティ導入ガイドブック:デジタル庁

ウェブアクセシビリティ基盤委員会(WAIC)

Webアプリケーションアクセシビリティ 今日から始める現場からの改善:伊原 力也、小林 大輔、桝田 草一、山本 伶(著)

↓ この記事をご覧の方へおすすめの記事はこちら ↓

アクセシビリティツリーとは?ウェブの使いやすさを支える技術

Webアクセシビリティとは?|なぜ対応が必要なのかわかりやすく解説

【Node.js使ってみたい!】Jamstackにも欠かせない、Web制作の現場でも愛されるNode.jsとは

この記事をシェアする

Webプロモーション・業務改善は
ノベルティひとつで完結

はじめての依頼にも
全力でサポートさせていただきます

メールでのお問い合わせ
各種サービス案内などをダウンロード

おすすめ記事/ PICKUP

    記事カテゴリー/ CATEGORY

      Webプロモーションや業務改善・DX化

      企業の課題はノベルティひとつで完結

      ホームページ制作などのWeb制作をはじめ、
      システム開発やマーケティング支援などワンストップで対応
      まずはお気軽にお問い合わせください

      お問い合わせ

      お電話またはメールでお気軽にお問い合わせください。

      資料ダウンロード

      各種サービスの資料をご用意しています