この記事でわかること

  • 部品の名前・役割・状態について定めた、WCAGの達成基準4.1.2の内容
  • divで作った開閉の部品が、読み上げで伝わらない理由
  • button要素とaria-expandedで、名前・役割・状態を伝える書き方
  • ブラウザが支援技術に渡す情報を、4つの作り方で比べた結果

「詳しい条件を見る」を押すと説明が開く部品を、divとJavaScriptだけで作ると、マウスで押せば開きます。ところが、画面の読み上げを使う人には、それがボタンであることも、いま開いているかどうかも伝わりません。この記事では、自分で作った部品の名前・役割・状態を支援技術に伝える方法を、WCAG 2.2の達成基準4.1.2を軸に整理します。

読み比べたのは、W3Cの達成基準4.1.2の解説(Understanding)と、技法G108・ARIA4・ARIA5、失敗例F59の原文で、2026年11月2日に確かめました。開閉の部品と受付の説明文は説明のために用意した作り物で、特定の道具や講座をすすめる内容ではありません。

先に結論: 開閉の部品はbuttonで作り、状態をaria-expandedで伝える

押して何かが起きる部品は、divではなくbutton要素で作ります。 開いたり閉じたりする部品なら、aria-expandedの値を、開いたときにtrue、閉じたときにfalseへ書きかえます。作り方ごとの伝わり方は、試した結果では次のとおりでした。

作り方 伝わる役割 開閉の状態 キーボード
buttonとaria-expanded ボタン 伝わる 押せる
buttonだけ ボタン 伝わらない 押せる
divにroleとtabindex ボタン 伝わらない 選べるが押せない
divにclickだけ 伝わらない 伝わらない 選べない

名前・役割・状態を伝える基準(4.1.2)

WCAG 2.2の達成基準4.1.2(レベルA)は、フォームの部品やリンク、スクリプトで作った部品を含むすべての部品について、名前と役割をプログラムで判別できること、利用者が変えられる状態や値をプログラムで設定できること、それらが変わったことを支援技術を含むブラウザなどに知らせることを求めています。

達成基準の注記では、この基準は主に、自分で部品を作ったりスクリプトで動かしたりする人のためのものだとしています。標準のHTMLの部品は、仕様どおりに使えば、すでにこの基準を満たします。

解説では、ねらいを、支援技術が部品の情報を集め、操作し、その状態の変化を追えるようにすることとしています。自分で部品を作ったり、部品をふだんと違う役割で動かしたりするときに、追加の手当てが要ります。

divで作った部品が伝わらない理由

失敗例F59は、divやspanのような汎用の要素に、スクリプトで部品の働きをさせて、役割を与えない作りを、失敗としています。リンクやボタン、入力欄のように役割の決まった要素と違い、divとspanには、あらかじめ決まった役割がありません。

F59の注記では、ふだん操作するものではない要素にイベントの処理を付けると、利用者がそこに操作できる部品があることに気づきにくく、どう動くかも分かりにくいとしています。また、こうした要素は操作できる要素と同じ合図を出さないため、利用者が操作しても支援技術に知らされないことがあるとしています。

技法G108は、標準の部品の機能を使って、名前と役割を伝え、状態の変化を知らせる方法です。技法ARIA4はWAI-ARIAのrole属性で役割を伝え、技法ARIA5はWAI-ARIAの状態や性質の属性で、部品の状態を伝える方法です。

書き方の例: buttonとaria-expandedで開閉の部品を作る

次のHTMLは、「詳しい条件を見る」を押すと説明が開き、もう一度押すと閉じる部品の例です。button要素で作り、開いているかどうかをaria-expandedの値で伝えます。

<button type="button" id="detail-toggle" aria-expanded="false" aria-controls="detail-panel">詳しい条件を見る</button>
<div id="detail-panel" hidden>
  <p>平日の10時から18時まで受け付けます。</p>
</div>

<script>
  const opener = document.getElementById("detail-toggle");
  const panel = document.getElementById("detail-panel");
  opener.addEventListener("click", () => {
    const open = opener.getAttribute("aria-expanded") === "true";
    opener.setAttribute("aria-expanded", String(!open));   // 開閉の状態を伝える
    panel.hidden = open;
  });
</script>

button要素なら、役割は「ボタン」として伝わり、ボタンの中の文字が名前になります。Tabキーで選べて、EnterキーやSpaceキーで押せることも、ブラウザが受け持ちます。

手順: 自分のページで、自作の部品を確かめる

  1. 押せる所を探す: クリックで何かが起きる所のうち、buttonやa要素ではないもの(divやspan)を探します
  2. Tabキーで回る: Tabキーで、その部品を選べるか、EnterキーやSpaceキーで押せるかを試します
  3. ブラウザの情報を見る: 開発用の画面のアクセシビリティの欄で、役割と名前が出ているかを見ます
  4. 状態の変化を見る: 開いたり選んだりした後に、aria-expandedなどの値が変わっているかを見ます
  5. buttonに直す: divで作った部品は、できるだけbutton要素に置きかえます

試した結果

上のHTMLと、同じ開閉を3通りの別の作り方で書いた版を用意しました。divにclickの処理だけを付けた版、divにrole="button"とtabindex="0"を付けた版、buttonだけでaria-expandedを付けない版です。4つのページを作業用のPCの中だけで配り、画面なしで動かしたChromeに読み込ませて、ブラウザが支援技術に渡す情報(アクセシビリティツリー)とキーボードでの動き方を見比べました。

  • 上のHTMLは、役割が「button」、名前が「詳しい条件を見る」、開閉の状態がfalseと渡されていました。Tabキーで選んでEnterキーを押すと説明が開き、状態はtrueに変わりました
  • divにclickだけの版は、ボタンとしては渡されず、文字としてだけ渡されていました。Tabキーでは選べず、マウスのクリックでだけ開きました
  • divにroleとtabindexを付けた版は、ボタンとして渡され、Tabキーで選べましたが、Enterキーを押しても開きませんでした
  • buttonだけの版は、ボタンとして渡され、キーボードで開きましたが、開閉の状態は渡されていませんでした

使ったブラウザは、作業用のMacに入っているChrome 156で、画面なしの形で動かしました。確かめたのはブラウザが渡す情報とキーボードの操作で、スクリーンリーダーでの読み上げは試していません。

自分で直すか、相談するかの判断

目安は、「その部品のHTMLを、自分で書きかえられるか」です。自分で書いたものなら、divをbutton要素に置きかえ、開閉する部品にはaria-expandedを足せば直せます。

ページを作る道具やテーマ、外から読み込んだ部品が出しているHTMLは、自分では直せないことがあります。その場合は、設定でボタンの作りに変えられるかを調べ、できなければ提供元か、制作を任せた人に相談します。部品の作りを基準に照らして判断できるようになりたいなら、Webデザインを学べる講座で、作った部品を講師に確かめてもらう方法もあります。

つまずきやすいところ

  • roleを付けても、キーボードで押せない: divにrole="button"を付けると、ボタンとしては伝わります。ただ、試したときもEnterキーでは開きませんでした。キーで動かす処理まで自分で書くことになるので、button要素を使います
  • 状態の値を書きかえ忘れる: aria-expanded="false"を最初に書いても、開いたときにtrueへ書きかえなければ、閉じたままと伝わります。開閉の処理と同じ所で書きかえます
  • ボタンの名前が見た目の文字と違う: 見えている文字と、支援技術に渡す名前をそろえる方法は、Webデザインでボタンの見た目のラベルと名前を一致させる方法で紹介しています
  • 押した結果が画面のどこかに出るだけになっている: 送信の結果のように、フォーカスを動かさずに出る知らせを読み上げで伝える方法は、Webデザインで画面の変化を読み上げで伝える方法にまとめています
  • キーボードで回ったときに、どこにいるか見えない: フォーカスの表示を消さずに残す方法は、Webデザインでキーボードだけで操作できるかを確かめる方法が参考になります

まとめ

  • 自分で作った部品は、名前・役割・状態を支援技術に伝える必要があります
  • 押して何かが起きる部品は、divではなくbutton要素で作ります
  • 開閉する部品は、aria-expandedの値を開閉と同じ所で書きかえます
  • Tabキーで選べて押せるか、ブラウザが渡す役割と状態が合っているかを確かめます