カード型UIの「もっと見る」リンクのアクセシビリティを改善する

「もっと見る」や「詳しく見る」といったリンクを含んだカード型UIは、Webサイトで頻繁に見かけるパーツです。カードの先頭から順に読み進める分には問題ありませんが、スクリーンリーダーの「リンクジャンプ機能」を利用すると、リンクテキストが繰り返されるだけで遷移先がわからなくなることが度々生じます。

この記事では、この問題がなぜ起きるのかをアクセシビリティの達成基準と照らし合わせながら整理し、リンクテキストの変更と視覚的に隠すテキストによる2つの改善方法を紹介します。

読み上げの検証にはmacOSのVoiceOverとChrome(バージョン 150.0.7871.187)を使用しています。スクリーンリーダーやブラウザの種類・バージョンによって読み上げ結果が異なる場合があります。

対象のカードUI

まずは改善前のマークアップです。リスト項目ごとにarticleでカードを構成し、見出し・説明文・「もっと見る」リンクを並べた、一般的によく見る実装です。

<ul class="p-card__list">
<li class="p-card__item">
<article class="p-card__card">
<div class="p-card__thumbnail">
<img src="https://picsum.photos/id/101/400/240" alt="" width="400" height="240" loading="lazy" decoding="async">
</div>
<div class="p-card__body">
<h2 class="p-card__title">自然の中で過ごす週末</h2>
<p class="p-card__text">緑あふれる山間でゆったりとした時間を過ごしませんか。新鮮な空気と美しい景色が、心と体をリフレッシュさせてくれます。</p>
<a href="#" class="p-card__more">もっと見る</a>
</div>
</article>
</li>
<li class="p-card__item">
<article class="p-card__card">
<div class="p-card__thumbnail">
<img src="https://picsum.photos/id/102/400/240" alt="" width="400" height="240" loading="lazy" decoding="async">
</div>
<div class="p-card__body">
<h2 class="p-card__title">季節の食材を味わう</h2>
<p class="p-card__text">地元の農家から届く新鮮な野菜や果物を使った、心温まる料理をお楽しみください。素材の味を活かしたメニューが自慢です。</p>
<a href="#" class="p-card__more">もっと見る</a>
</div>
</article>
</li>
<li class="p-card__item">
<article class="p-card__card">
<div class="p-card__thumbnail">
<img src="https://picsum.photos/id/103/400/240" alt="" width="400" height="240" loading="lazy" decoding="async">
</div>
<div class="p-card__body">
<h2 class="p-card__title">心安らぐ空間づくり</h2>
<p class="p-card__text">木の温もりを感じるインテリアと、柔らかな光が差し込む空間で、日常の疲れを癒やすひとときをお過ごしください。</p>
<a href="#" class="p-card__more">もっと見る</a>
</div>
</article>
</li>
</ul>

以下が表示例です。

カード型UIの実装例

どのような問題が発生するか

カードの先頭から順に読み進める場合には、特に問題は発生しません。「自然の中で過ごす週末、見出しレベル2」→ 説明文 →「もっと見る、リンク」という順で読み上げられるため、直前の文脈から「もっと見る」の行き先を自然に理解できます。

問題が発生するのは、スクリーンリーダーの「リンクジャンプ機能」を利用したときです。

リンクジャンプ機能での移動

スクリーンリーダーには、ページ内のリンクだけを順にジャンプして移動する機能があります。VoiceOverでは「VO + Command + L キー」で、次のリンクへ直接ジャンプできます。本文を読み飛ばして目的のリンクへ素早くたどり着くための機能で、スクリーンリーダーのユーザーには日常的に使われています。

この機能でカードUIのリンクを順に移動すると、次のように読み上げられます。

  • 「もっと見る、閲覧済み、リンク」
  • 「もっと見る、閲覧済み、リンク」
  • 「もっと見る、閲覧済み、リンク」

まったく同じ内容が3回繰り返されるだけで、それぞれのリンクがどのカードのものなのか、クリックした先に何が表示されるのかがまったくわかりません。

リンク一覧表示機能

同様の問題は「リンク一覧表示機能」でも発生します。これはページ内のリンクをリストにして一覧表示し、そこから目的のリンクを選んで移動できる機能です。VoiceOverでは「VO + U キー」を押すとリンク一覧が表示されます。

一覧には「もっと見る」がリンクの数だけ並ぶことになり、こちらも区別がつきません。

VoiceOverのリンク一覧に「もっと見る」が3つ並んでいるスクリーンショット

アクセシビリティの達成基準ではどう位置づけられるか

「もっと見る」だけのリンクは規格違反なのでしょうか。WCAG2.1の達成基準にはリンクの目的に関する項目が2つあり、それぞれ次のようになっています。

達成基準レベル求められること改善前のカードUI
2.4.4 リンクの目的(コンテキスト内)Aリンクテキスト単独、またはプログラムによる解釈が可能なコンテキストとあわせて、リンクの目的を判断できる満たしている可能性が高い
2.4.9 リンクの目的(リンクのみ)AAAリンクテキスト単独で、リンクの目的を判断できる満たしていない

達成基準2.4.4では、リンクと同じリスト項目内にあるテキストは「プログラムによる解釈が可能なコンテキスト」として認められる可能性が高いです。今回のカードUIは同じliの中に見出しと説明文があるため、2.4.4(レベルA)は満たしている可能性が高いことになります。

一方で、達成基準2.4.9はリンクテキスト単独で目的がわかることを求めており、「もっと見る」だけでは行き先が判断できないため、2.4.9(レベルAAA)は満たしていない状態です。

つまり改善前の状態は「規格違反(レベルA)ではないが、リンクジャンプ機能やリンク一覧表示ではコンテキストが失われるため、実用上は不便」という位置づけです。スクリーンリーダーのユーザーの使い勝手を考えると、2.4.9の水準を目指して改善する価値は十分にあります。

解決方法

推奨される方法と補助的な方法を紹介します。

方法1(推奨): リンクテキスト自体を変更する

もっともシンプルな解決方法は、リンクのテキストそのものを変更することです。

  • 「自然の中で過ごす週末についてもっと知る」
  • 「季節の食材を味わうについてもっと知る」

というように、リンクテキストにカードの内容を含めることで、リンクテキストが一意なものとなり、リンクジャンプ機能でもリンク一覧表示でも識別できるようになります。

ただし、サイト上に表示される文言を実装側で勝手に変えるわけにはいきません。ディレクターやデザイナーなど上流とコミュニケーションを取り、合意の上で変更する必要があります。

方法2(補助的): 視覚的に隠すテキストで補完する

もう一つの方法は、実装側でアクセシブルな名前(スクリーンリーダーが読み上げるテキスト)を補完する方法です。あくまでも補助的な方法であり、優先すべきは方法1のリンクテキストの変更です。

<li class="p-card__item">
<article class="p-card__card">
<div class="p-card__thumbnail">
<img src="https://picsum.photos/id/101/400/240" alt="" width="400" height="240" loading="lazy" decoding="async">
</div>
<div class="p-card__body">
<h2 class="p-card__title">自然の中で過ごす週末</h2>
<p class="p-card__text">緑あふれる山間でゆったりとした時間を過ごしませんか。新鮮な空気と美しい景色が、心と体をリフレッシュさせてくれます。</p>
<a href="#" class="p-card__more">もっと見る</a>
<a href="#" class="p-card__more"><span class="u-sr-only">自然の中で過ごす週末を</span>もっと見る</a>
</div>
</article>
</li>
.u-sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
border-width: 0;
}

.u-sr-onlyは、要素を視覚的には見えなくしつつ、スクリーンリーダーには読み上げ対象として残すためのユーティリティクラスです。「もっと見る」の直前に見出しのテキストをスクリーンリーダーだけに伝わる形で追加することで、リンクは「自然の中で過ごす週末をもっと見る」として読み上げられるようになります。

以下はリンク一覧表示機能での改善後の例です。リンクジャンプ機能でも同様に改善されています。

VoiceOverのリンク一覧に「自然の中で過ごす週末をもっと見る」など一意なリンク名が並んでいるスクリーンショット

なお、見出しとリンク直前のテキストを完全に同期させたいのであれば、見出しにid属性をつけ、リンクにaria-labelledby属性で見出しのidを参照させる方法もあります。今回はそこまではしていません。

aria-labelではうまくいかなかった

次のようにシンプルにリンク要素にaria-labelを追加する方法も選択肢として考えられます。

<li class="p-card__item">
<article class="p-card__card">
<div class="p-card__thumbnail">
<img src="https://picsum.photos/id/101/400/240" alt="" width="400" height="240" loading="lazy" decoding="async">
</div>
<div class="p-card__body">
<h2 class="p-card__title">自然の中で過ごす週末</h2>
<p class="p-card__text">緑あふれる山間でゆったりとした時間を過ごしませんか。新鮮な空気と美しい景色が、心と体をリフレッシュさせてくれます。</p>
<a href="#" class="p-card__more">もっと見る</a>
<a href="#" class="p-card__more" aria-label="自然の中で過ごす週末をもっと見る">もっと見る</a>
</div>
</article>
</li>

しかしこの方法では、リンクジャンプ機能では適切に読み上げられるのですが、リンク一覧表示機能ではaria-labelが反映されず、「もっと見る、閲覧済み」としか読み上げられないケースがあるようです(VoiceOverなど)。

これは、仕様上はaria-labelがリンク内のテキストより優先されてアクセシブルな名前になるはずのところ、リンク一覧のような集約された表示への反映はスクリーンリーダーやブラウザの実装に差があり、安定しないためだと考えられます。DOM上に実テキストとして存在する.u-sr-only方式であれば、リンク内のテキストがそのまま名前になるため、こうした実装差の影響を受けにくくなるようです。

まとめ

カード型UIの「もっと見る」リンクは、同じリスト項目内に見出しや説明文がある場合、JIS X 8341-3:2016の達成基準2.4.4(レベルA)は満たしている可能性が高いです。

ただし、リンクテキスト単独で目的がわかることを求める達成基準2.4.9(レベルAAA)は満たしていません。リンクジャンプ機能やリンク一覧表示ではコンテキストが参照できず、行き先がわからないという実用上の問題もありました。

理想はリンクテキスト自体を一意なものに変更することですが、文言の変更には上流との調整が必要です。実装側で完結させる場合は、.u-sr-onlyのような視覚的に隠すテキストで補完するのが確実でした。

視覚的な確認だけでは気づきにくい問題ですが、リンクテキストは単独で行き先や目的がわかるようにしておくことで、スクリーンリーダーのユーザーの使い勝手を大きく改善できます。

参考サイト

この記事を書いた人

写真:ブール 代表 西川雅人

Masato Nishikawa

ウェブ制作会社・デザイナー様向けに、コーディングやWordPress実装を承っているフリーランスです。繁忙期のサポートや、継続的な外注先をお探しでしたら、お気軽にお声がけください。

コーディングや
WordPress実装の
ご相談を承っています。

新規制作から運用フェーズの修正まで柔軟に対応します。
お見積りや実装可否の確認など、お気軽にご連絡ください。