📙

アクセシビリティを考慮したHTMLコーディングガイド

2022/09/28に公開

これ何なの?

もともと私が社内メンバー向けに書いていたドキュメントで、 UIパーツ毎のアクセシビリティを考慮したHTMLコーディングTips集です。
社内のドキュメント置き場に眠っていたものですが、知見として社外にも共有出来る内容だなと思ったのと、アクセシビリティをこれからやっていこう!という方の参考になればと思い共有させて頂きます。

※そもそもアクセシビリティって何なの?という方は、ウェブアクセシビリティ基盤委員会のサイトを見てみてください🔍


目次

  • おすすめVSCode拡張機能
  • 🕹ボタン
  • 📷 画像
  • 🔍 ナビゲーション
  • 💻 フォーム

おすすめVSCode拡張機能

axe Accessibility Linter をインストールしておくとimgタグのalt忘れなど警告が表示されるので、アクセシブルでない書き方を未然に防げるので便利です!


🕹ボタン

buttun タグを使いましょう。( input type="button" はHTML4の時代のものなので非推奨 )
div タグでボタンを実装している例があるかもしれませんが、 divタグではキーボード操作でフォーカスが当たらないためNGです ❌

フォーカスが当たらない例

<div class="save__button" @click="saveBlog">保存</div>

フォーカスが当たる例

<button class="save__button" @click="saveBlog">保存</button>

アイコンのみのボタンの場合

ECのカートボタン(🛒)のようにアイコンのみのボタンに対して、スクリーンリーダーを利用する際は、適宜以下のように aria-label 属性でボタンの効果がわかるように説明文を加えるとさらに良いかもしれません。



↓ 以下のコード例だとフォーカスが当たり、「カート内のアイテムを表示、ボタン」と読み上げられます

<!-- アイコンのみのボタン -->
<button class="cart__button" @click="openCart" aria-label="カート内のアイテムを表示"></button>

📷 画像

imgタグには必ず alt属性を設定しましょう!
alt属性の有無や設定値によるスクリーンリーダーの読み上げの違いは以下の通りです。

alt属性がない場合

  • 「fuga.jpg image」と読み上げられます
<img src="images/fuga.jpg">

alt属性が設定されている場合

  • 「フガの写真」と読み上げられます
<img src="images/fuga.jpg" alt="フガの写真">

alt属性が設定されているが、空文字の場合

  • 読み飛ばされます
    • それ自体に意味を持たないデザインや装飾目的の画像の場合は、空文字にして読み飛ばさせるのが良さそうです。
<img src="images/fuga.jpg" alt="">

alt属性の設定値を書く際のヒント


【参考書籍・リンク】


1. 画像と等価のテキストを書く

例えば、クレジットカード会社の企業ロゴなどは以下のようにロゴに書かれているテキストを alt にも設定するのが良いようです。

<img src="images/credit/jcb.png" alt="JCB">

2. 繰り返しを避ける

地図のような画像の前後にキャプション・説明文がある場合は、それらと重複しない内容を指定するのが良いようです。

<div>
  <img src="images/map.png" alt="エフ・ニッセイ・恵比寿ビルまでの地図です。地図に続いて詳細">
</div>
<p>〇〇駅から〇〇方面に乗り、「〇〇駅」で下車します。改札を出たら右に曲がり……</p>

🔍 ナビゲーション

マークアップする際は、 nav タグを使いましょう。
nav タグを使うことでスクリーンリーダーに対してセクションがナビゲーション ( navigation ) ロールを持つことを伝えることが出来ます。

参考: ARIA: navigation ロール

 <nav>
    <ul>
      <li>
        <nuxt-link 
          to="/">
          ホーム
        </nuxt-link>
      </li>
      <li>
        <nuxt-link
          to="/shop">
          店舗情報
        </nuxt-link>
      </li>
      <li>
        <nuxt-link
          to="/menu">
          メニュー
        </nuxt-link>
      </li>
      <li>
        <nuxt-link
          to="/information">
          お知らせ
        </nuxt-link>
      </li>
    </ul>
  </nav>

ナビゲーション内で現在のページをスクリーンリーダーに伝えたい場合

現在のページに該当するメニュー項目には、 動的に aria-current="page" を設定するようにすることで、スクリーンリーダーに現在のページであることを伝えることが出来ます。

  <nav>
    <ul>
      <li>
        <nuxt-link 
          to="/" :aria-current="isCurrentPage('') ? 'page' : undefined"
        >
          ホーム
        </nuxt-link>
      </li>
      <li>
        <nuxt-link 
          to="/shop"
          :aria-current="isCurrentPage('shop') ? 'page' : undefined"
        >
          店舗情報
        </nuxt-link>
      </li>
      <li>
        <nuxt-link
          to="/menu"
          :aria-current="isCurrentPage('menu') ? 'page' : undefined"
        >
          メニュー
        </nuxt-link>
      </li>
      <li>
        <nuxt-link
          to="/information"
          :aria-current="isCurrentPage('information') ? 'page' : undefined"
        >
          お知らせ
        </nuxt-link>
      </li>
    </ul>
  </nav>

💻 フォーム

labelfor属性 を使って適切にフォームコントロール( input 要素)との関連付けを行いましょう。

参考: H44: テキストラベルとフォームコントロールを関連付けるために、label 要素を使用する

テキストフィールドの例

<label for="firstname">First name:</label> 
<input type="text" name="firstname" id="firstname" />

ラジオボタンなどのグループ化された入力要素については以下を参照ください。

参考: H71: fieldset 要素及び legend 要素を使用して、フォームコントロールのグループに関する説明を提供する

スクリーンリーダーのユーザーに直前の操作によってバリデーションエラーが発生したことを伝えたい場合

aria-live="polite" をエラーメッセージの要素に付与することで実現出来ます。
以下のUIの例では、バリデーションエラー発生時に上から順に「お名前を入力してください」「メールアドレスを入力してください」「お問い合わせ内容を入力してください」と読み上げられます。

参考: ARIA ライブリージョン

<form>
  <div class="mb-12">
    <Label for="name">
      お名前 <span class="text-xs text-red-500">(必須)</span>
    </Label>
    <input
      id="name"
      v-model="name"
      class="w-full px-3 py-2 placeholder-gray-300 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300"
      type="text"
      placeholder="お名前太郎"
    />
    <!-- エラーメッセージ部分 -->
    <p 
      v-if="name.$anyInvalid"
      aria-live="polite"
      class="text-xs text-red-500 mt-3"
    >
      {{ name.$message }}
    </p>
    <!-- エラーメッセージ部分 -->
  </div>
  <!-- 中略 -->
</form>

参考まとめ

Discussion