リンクテキストが空、または「詳しくはこちら」だけのリンク
空のリンクを重ねてバナー全体をクリックできるようにし、下のカードはすべて同じ「詳しくはこちら」で終わっています。
問題
スクリーンリーダー利用者が、リンクを開く前にリンク先を知ることができません。
紅茶店のトップページは、紅葉の写真に「秋のブレンドが入荷しました」という見出しと説明文を載せたバナーで始まります。バナー全体がクリックできます。Tabキーでバナーに移動すると、スクリーンリーダーは「リンク」とだけ読むか、「collections/autumn」とアドレスを読み上げます。その下には、見出し、短い文、「詳しくはこちら」のリンクを持つ記事カードが3枚並んでいます。リンク一覧を開くと、名前のないリンクの後に「詳しくはこちら」が3回続きます。
バナー全体をクリックできるように、テーマが空の <a> を絶対配置でバナーに重ねています。見出しと説明文はリンクの外の要素にあるため、リンクにはテキストがなく、アクセシブルな名前もありません。カードのリンクにはテキストがありますが、3つの異なる記事に同じ言葉を使っています。
スクリーンリーダー利用者は、リンクを順にたどったり、ページ内のリンク一覧を開いたりして移動することがよくあります。名前のないリンクは手がかりにならず、同じ「詳しくはこちら」が並ぶと、一つずつ開かないとリンク先が分かりません。音声操作の利用者は、リンクのテキストを声に出して操作しますが、名前のないリンクは呼べません。「詳しくはこちらをクリック」と言うと、3つのリンクが同時に該当します。
axe の link-name のような自動チェックは、空のバナーリンクを確実に検出します。ただし名前が役に立つかは判断しないため、「詳しくはこちら」の連続、「IMG_2041.jpg」という名前のリンク、alt が「ロゴ」のアイコンは合格になります。AIによる手早い修正では aria-label="リンク" を加えることが多く、警告は消えても誰の役にも立ちません。表示テキストを含まない aria-label を付けると、音声操作でリンクを呼べなくなります。
修正方法
リンク先が分かる言葉をすべてのリンクに持たせます。今あるリンクに補うか、見出しをリンクにします。
- 1すべてのリンクに言葉を持たせる。テキスト、画像の alt、または表示テキストで始まる名前を使う。
- 2バナーに重ねたリンクに名前を付けるか、疑似要素で広げた見出しのリンクに置き換える。
- 3「詳しくはこちら」は視覚的に隠したテキストで補うか、リンク先に置き換える。
<div class="banner"> <img src="/images/autumn.jpg" alt=""> <a href="/collections/autumn" class="banner-link"></a> <div class="banner-text"> <h2>秋のブレンドが入荷しました</h2> <p>ほうじ茶、チャイ、栗の香りのお茶。</p> </div></div> <article class="card"> <h3>ほうじ茶のおいしい淹れ方</h3> <p>低めの温度で短く蒸らすと、香ばしさが引き立ちます。</p> <a href="/journal/brew-hojicha">詳しくはこちら</a></article>html
<div class="banner"> <img src="/images/autumn.jpg" alt=""> <a href="/collections/autumn" class="banner-link"> <span class="visually-hidden">秋のブレンドが入荷しました</span> </a> <div class="banner-text"> <h2>秋のブレンドが入荷しました</h2> <p>ほうじ茶、チャイ、栗の香りのお茶。</p> </div></div> <article class="card"> <h3>ほうじ茶のおいしい淹れ方</h3> <p>低めの温度で短く蒸らすと、香ばしさが引き立ちます。</p> <a href="/journal/brew-hojicha"> 詳しくはこちら<span class="visually-hidden">:ほうじ茶のおいしい淹れ方</span> </a></article>css
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;}バナーのリンクは中身が空なので、支援技術が読み上げる言葉がありません。カードの「詳しくはこちら」は、上の見出しと合わせて読んだときにだけ意味が通じます。リンク一覧では、その見出しは読まれません。
言葉を補う方法では、レイアウトは変わりません。バナーのリンクは「秋のブレンドが入荷しました、リンク」、カードのリンクは「詳しくはこちら:ほうじ茶のおいしい淹れ方、リンク」と読み上げられます。カードのリンクの名前は表示テキストで始まるため、音声操作でもその言葉で呼べます。バナーのリンクは、隠したテキストの代わりに、h2 に付けた id を aria-labelledby で参照して見出しから名前を取ることもできます。こうすると、見出しとリンクの名前がずれません。どちらの場合も、バナーを上から順に読むと、リンクと見出しで同じ言葉が2回読まれます。
どちらの方法でもすべてのリンクに名前が付き、2.4.4を満たします。言葉を補う方法は変更が小さく、レイアウトやCSSを変えずに済みます。構造を変えられないテーマや外部のスライドショー、「詳しくはこちら」を残すデザインに向いています。見出しをリンクにする方法は、リンクが一つで読み上げも一度、名前は画面に見えている見出しそのものになるため、より整った形です。テンプレートを変更できる場合はこちらを選びます。自社のカードは見出しリンクにし、変更できないスライドショーは重ねたリンクに名前を付ける、というように組み合わせても構いません。
広げたリンクが他の操作要素を覆う。 カード内に「保存」ボタンやタグのリンクなどがある場合は、position: relative と疑似要素より上の z-index を指定しないと押せません。カード内のテキストも選択できなくなります。操作要素が多いカードでは、見出しと画像だけをクリックできるようにすることも検討します。
カード全体を一つの <a> で囲む。 HTMLとしては正しく、カード全体を押せますが、カード内のすべての文字がリンクの名前になり、長い文章が読み上げられます。中に別のリンクやボタンも置けません。見出しをリンクにすれば、どちらの問題も避けられます。
隠したテキストと aria-label。 display: none はアクセシブルな名前からも文字を消すため、clip を使った .visually-hidden クラスを使います。aria-label はリンクの中身を置き換え、ブラウザーの翻訳機能で訳されないことがあり、表示テキストとずれやすいため、隠したテキストを優先します。使う場合は、表示テキストで始めてください。
画像とアイコンのリンク。 画像だけのリンクでは、alt に画像の説明ではなくリンク先(「Leaf & Kettle ホーム」「Instagram」)を書きます。同じリンク内にテキストもある画像は alt="" にし、名前が二重に読まれないようにします。SVGアイコンは aria-hidden="true" で隠し、リンクに視覚的に隠したテキストを入れます。
編集できるコンテンツ。 テーマやCMSでは、バナーの見出しが任意項目のことがよくあります。空欄のままだと、広げたリンクはまた名前を失います。リンクを設定したらラベルを必須にするか、ラベルが空のときはリンクを出力しないようにします。「今すぐ購入」が並ぶ複数のバナーも、「詳しくはこちら」と同じ問題です。
厳密には文脈で足りる場合もある。 WCAG 2.4.4 は、リンクテキストを、同じ文、リスト項目、表のセルなど、プログラムで判別できる文脈と合わせて読むことを認めています。整った構造のカード内の「詳しくはこちら」は適合する場合もありますが、リンク一覧では分かりにくいままです。レベルAAAの2.4.9は、リンク単体で意味が分かることを求めています。空のリンクは、どの場合でも不適合です。
修正の確認
5つの確認
確認方法: キーボード、スクリーンリーダー、マウス
OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。共通のカード、バナー、スライドショーのコンポーネントを変更した際は、再度確認します。
制限
このサンプルは、どのアプリケーションでも同じ結果になることを保証するものではありません。コード内のパスとクラス名は仮のものです。コンテンツの編集者が後から曖昧なリンクを書くこともあるため、公開前の確認にリンクテキストを含めてください。実際に使用する支援技術で、操作全体を確認してください。
よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。
コードを更新しても、使いやすさを保つために
ガイドの内容を、コーディングエージェントやCIで使える開発ルールにまとめます。更新後は、キーボードとスクリーンリーダーで再テストし、問題が再発していないか確認します。