トピックを検索
タイトルがない、または中身の分からないiframe
スタジオの来店案内ページに、タイトルのない地図と、埋め込みコードに付いてきた「Video player」だけがタイトルの動画が埋め込まれており、スクリーンリーダーはどちらの中身も伝えずにフレームを2つ読み上げます。
<iframe src="https://maps.example.com/embed?pb=…"> 問題
スクリーンリーダー利用者が、埋め込まれた地図や動画やウィジェットの中身を、中に入らないと知ることができません。
陶芸スタジオの「ご来店案内」ページに、埋め込みが2つあります。「アクセス」の見出しの下には、地図サービスの共有メニューから貼り付けた地図があります。「スタジオ紹介」の下には、動画サービスから貼り付けた2分の動画があります。道順を知りたいスクリーンリーダー利用者が、フレーム移動のキーやスクリーンリーダーのフレーム一覧でページ内のフレームをたどると、「フレーム」、続けて「Video player フレーム」と聞こえます。スクリーンリーダーによっては、1つ目で地図の長いURLを読むこともあります。どちらが地図かは分からないため、一つずつ中に入って確かめるか、あきらめて住所を別の場所で探すことになります。
iframe はページの中に別の文書を入れる要素で、支援技術は名前の付いたフレームとして伝えます。4.1.2は、すべてのユーザーインターフェースコンポーネントに、コードから判別できる名前があることを求めており、フレームもその一つです。地図の iframe には title がないため、名前がまったくありません。動画のフレームには、動画サービスがどの動画の埋め込みコードにも付ける title="Video player" があります。名前ではあっても、動画ではなくプレーヤーを表しています。title でフレームに名前を付けるWCAGの達成方法H64は、タイトルが「iframe の内容を説明している」ことを確認します。ページに2本目の動画があれば同じ名前になり、2つを区別できません。
見える人には地図と動画が見えており、問題に気づきません。問題は、コードが2つのフレームに付けている名前だけにあります。
10グループ中2グループに影響
axe の frame-title とANDIは、名前のない地図のフレームを検出します。どちらも空でないタイトルなら合格にするため、「Video player」は通ります。axe の frame-title-unique が検出するのは、2つのフレームが同じタイトルを持つ場合だけです。また自動チェックは最初に読み込まれた状態のページを調べるため、Cookieの選択やクリックの後にフレームを挿入するチャットや予約のウィジェットは、多くの場合一度も調べられません。警告の修正をAIに頼むと、title="iframe"、title="埋め込みコンテンツ"、サービス名など、中身について何も言わない名前を付けがちです。フレームに aria-hidden="true" を付ける修正もあります。自動チェックは静かになりますが、地図はスクリーンリーダーから隠れ、中のリンクは何も読まれないままTabの順序に残ります。名前がフレームの中身を表しているかは、人が判断する必要があります。
試してみる
各フレームについてスクリーンリーダーが読む内容だけを頼りに、地図を探してください。
ページの下には、フレームからフレームへ移動したときにスクリーンリーダーが読む内容が出ます。行を選ぶと、そのフレームへ移動します。選ぶ前に、どれが地図か分かりますか?
問題あり 修正できますか?
ご来店案内
アクセス
4 Mill Lane。火曜から日曜、10:00〜18:00。
スタジオ紹介
ろくろと窯をめぐる2分間。
フレームを順に移動すると、スクリーンリーダーの読み上げ:
再現デモです。「問題あり」は意図的にアクセシブルでない状態にしています。
修正方法
各フレームに、中身を表す短いタイトルを付けます。
- 1スクリプトが挿入するものも含め、表示されるすべてのフレームにタイトルを付ける。
- 2フレーム、プレーヤー、埋め込みであることではなく、中身を書く。
- 3フレームごとに固有の名前を、ページの言語で付ける。
<h2>アクセス</h2><p>4 Mill Lane。火曜から日曜、10:00〜18:00。</p><iframe src="https://maps.example.com/embed?pb=!1m18!1m12…" width="600" height="320" style="border:0" loading="lazy"></iframe> <h2>スタジオ紹介</h2><iframe src="https://video.example.com/embed/x7Kq2" width="560" height="315" title="Video player" allowfullscreen></iframe><h2>アクセス</h2><p>4 Mill Lane。火曜から日曜、10:00〜18:00。</p><iframe src="https://maps.example.com/embed?pb=!1m18!1m12…" title="Kiln Room(4 Mill Lane)の地図" width="600" height="320" style="border:0" loading="lazy"></iframe> <h2>スタジオ紹介</h2><iframe src="https://video.example.com/embed/x7Kq2" title="スタジオ紹介の動画" width="560" height="315" allowfullscreen></iframe>この方法を選ぶ理由:まずHTMLの要素を使う
const booking = document.getElementById('booking');const nameFrames = () => { for (const frame of booking.querySelectorAll('iframe')) { if (frame.title !== '予約カレンダー') frame.title = '予約カレンダー'; }};nameFrames();new MutationObserver(nameFrames).observe(booking, { childList: true, subtree: true });地図のフレームには名前がなく、動画の名前は動画サービスの初期値のため、どちらもフレームの中身をスクリーンリーダー利用者に伝えません。
各フレームに中身を表す短い名前が付き、スクリーンリーダーは「Kiln Room(4 Mill Lane)の地図 フレーム」「スタジオ紹介の動画 フレーム」と読みます。道順を知りたい人は、どちらに入ればよいか分かります。動画の初期値のタイトルは、新しい名前と並べて残さず、書き換えています。title はフレームに名前を付けるためのHTMLの属性で、ブラウザーとスクリーンリーダーは、どのARIA属性よりも長くフレームの title を読んできました。
チャット、予約、決済、レビューのウィジェットは、多くの場合スクリプトで iframe を挿入するため、タイトルを書き足せる自分たちのマークアップがありません。それでも、中に読み込まれる内容が提供元のドメインから来ていても、iframe 要素そのものはページの一部なので、名前を付けられます。次のうち、最初に使えるものを選んでください。
まず、ウィジェット自身の設定を使います。多くのSDKは、初期化のときにタイトル、ラベル、アクセシビリティの設定を受け取るか、渡したコンテナからタイトルを写します。設定の名前は提供元によって違うため、ドキュメントを確認してください。提供元の更新を経ても残る修正は、設定だけです。CMSやネットショップのプラグインがテンプレートで iframe を出力する場合も同じです。まず設定を探し、なければプラットフォームが用意しているテンプレートの上書きやフィルターフックを使います。どちらもプラグインを更新しても残りますが、プラグインのファイルを直接書き換えた修正は消えます。
設定がなければ、自分たちのスクリプトでタイトルを付けます。SDKに準備完了や読み込み完了のコールバックがあればその中で、なければウィジェットのコンテナを監視して付けます。開く、閉じる、次の手順へ進むといった操作のたびにフレームを差し替えるウィジェットが多いため、一度付けて終わりにせず、付け続けます。
監視するのは文書全体ではなく、ウィジェットのコンテナだけにします。このオブザーバーは属性ではなくフレームの追加に反応するため、タイトルを付けても再び呼ばれることはありません。ウィジェットが複数のフレームを追加する場合は、すべてに同じ名前を付けず、利用者が操作するフレームを選んで付けます。この方法は提供元のマークアップが変わらない間しか持たず、スクリプトの読み込みに失敗すれば何もしません。応急処置として扱い、名前がないことを提供元に報告し、提供元が更新するたびにページを確認し直してください。
SDKは、メッセージのやり取りや不正利用のチェックのために、何も表示しない小さな補助フレームも追加することがあります。display: none で隠されたものには何も要りません。1、2ピクセルの大きさでページに残っているものはスクリーンリーダーに伝わるため、「決済のセキュリティチェック」のように役割で名前を付け、隠すよう提供元に依頼します。閉じたShadow Rootの中にあるフレームには、ページのどのスクリプトからも届かず、直せるのは提供元だけです。
ウィジェットを直せない場合も、問題はページに残ります。WCAGは、管理できない第三者のコンテンツについて部分適合の表明を認めていますが、それは不足を説明するもので、解消するものではありません。アクセシビリティ方針でそのウィジェットを挙げ、予約用のメールアドレスなど、同じことをする別の方法を示し、提供元を選ぶときや契約を更新するときの判断材料にしてください。
iframe に aria-label や aria-labelledby を付けても名前は付き、どちらも title より優先されます。ここではどちらも何も加えません。title と aria-label の両方があるフレームは、名前を2つ持ち、いずれ食い違うおそれがあるため、title だけを付けます。
フレームのマークアップがどこから来るかで、タイトルを付ける場所が決まります。
- 自分たちのテンプレートにあるフレーム:マークアップに
titleを書きます。埋め込み用のコンポーネントでは、「埋め込みコンテンツ」のような初期値にせず、必須のpropsにします。 - コンテンツ編集者が貼り付けるフレーム:埋め込みブロックにタイトルの必須欄を設けます。貼り付けたコードから属性を消したり、動画サービスの初期値を残したりするエディターもあるため、公開されたページで確認します。
- 外部のウィジェット、プラグイン、SDKが挿入するフレーム:編集できるマークアップがないため、前の節のとおり、ウィジェットの設定を使うか、スクリプトでタイトルを付けます。
名前はページの言語で書きます。動画サービスの初期値は英語のことが多く、日本語に設定したスクリーンリーダーは、それを不自然な発音で読みます。名前は短く具体的にします。「春に撮影した、陶芸スタジオを2分で紹介する動画」ではなく「スタジオ紹介の動画」です。名前と一緒にロールが読まれるため、「フレーム」や「iframe」を名前に入れる必要はありません。
トラッキング用のフレームのように、display: none、visibility: hidden、hidden 属性で隠されたフレームは支援技術に伝わらないため、名前は要りません。警告を消すために、見えているフレームを aria-hidden で隠すのはやめてください。中のフォーカスできる要素は、何も読まれないままフォーカスを受け取ります。
フレームの中の文書が自分たちのものなら、その文書にもフレームの名前と同じ内容の <title> を付けます。フレームに入るときにその文書のタイトルを読むスクリーンリーダーがあり、フレームを単独で開いたときにはページのタイトルになります。
AI コーディングアシスタントで修正しますか? このガイドを Markdown で取得
修正の確認
マウスを使わない3つの確認
確認方法: スクリーンリーダー
OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。埋め込みを追加したときや外部のスクリプトが変わった際は、再度確認します。
制限
このサンプルは、どのアプリケーションでも同じ結果になることを保証するものではありません。コードの中のURL、ID、名前は仮のものです。フレームの伝え方はスクリーンリーダーによって違い、フレームに着いたときに名前を読むもの、代わりに中の文書のタイトルを読むもの、中に入るまでどちらも読まないものがあります。言い回しではなく名前を聞いてください。このガイドはフレームの名前を扱い、地図のキーボード操作や動画の字幕など、フレームの中身がアクセシブルかどうかは扱いません。実際に使用する支援技術で、操作全体を確認してください。
よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。
コードを更新しても、使いやすさを保つために
ガイドの内容を、コーディングエージェントやCIで使える開発ルールにまとめます。更新後は、キーボードとスクリーンリーダーで再テストし、問題が再発していないか確認します。