シリーズ「アクセシビリティ通信」ではウェブアクセシビリティに関するトピックを取り上げていきます。今回はテキストリンクの指定について取り上げます。

2023 年 1 月末のリニューアル以降に、本サイトで実施したウェブアクセシビリティの改善に取り組みました。

実施するきっかけとなったのは、以下の記事を執筆するために、スクリーンリーダーでの検証をとおして、改善すべき問題がいくつか見つかったためです。

また、2 月 27 日 に発売された書籍『Webアプリケーションアクセシビリティ』を読んだことも、改修に取り組むための契機になりました。

『Webアプリケーションアクセシビリティ』の表紙
『Webアプリケーションアクセシビリティ』では、ウェブアクセシビリティの基礎から事例を通した改善方法まで網羅的に学習することができる

今回は、これらの検証や書籍をとおして気づいた、テキストリンクにおけるアクセシビリティ上の問題点を見ていきます。

テキストリンク「記事を読む」の問題点

見出し「テキストリンク「記事を読む」の問題点」

本サイトのブログ一覧やプロジェクト一覧には、見出しや概要の後に「記事を読む」や「プロジェクトをみる」のテキストリンクが配置されています。以降「記事を読む」のみに焦点を当てますが、実装内容は同じです。

この記事一覧のリスト項目のコンポーネントは以下の構成ですが、本記事ではこのコンポーネントを「記事コンポーネント」と呼びます。

記事コンポーネントの構成要素。タグ、見出し、日付、テキストリンクの要素が含まれる
記事コンポーネントの末尾には「記事を読む」のテキストリンクが配置されている

この記事コンポーネントにリンクを指定するときに、全体をリンク(<a> 要素)で囲う方法も考えられますが、スクリーンリーダーで読み上げられるテキスト量が多くなることを避けるために、リンクは「記事を読む」のみに指定し、CSS の ::after 擬似要素で要素全体に広げています。

改修前のテキストリンクの実装
<a href="...">記事を読む</a>
リンク範囲を要素全体に広げる CSS
a::after {
  content: '';
  display: block;
  position: absolute;
  inset: 0;
}

この実装に関連する WCAG 2.1 の達成基準「2.4.4 リンクの目的(コンテキスト内)」では以下のように説明されています。この基準はレベル A です。

それぞれのリンクの目的が、リンクのテキスト単独で、又はリンクのテキストとプログラムによる解釈が可能なリンクのコンテキストから判断できる。ただし、リンクの目的がほとんどの利用者にとって曖昧な場合は除く。

Web Content Accessibility Guidelines (WCAG) 2.1 日本語訳

記事コンポーネントには見出しが含まれるため、コンテキストから判断できるので、この基準は満たせそうです1

しかし、スクリーンリーダーによっては、ページ内のリンク要素の一覧を表示する機能(リンクジャンプ)があり、このモードでは「記事を読む」ではリンク先を判別できないことに気づきます。以下は、macOS の VoiceOver ローターを使用して、リンク一覧を表示した状態です。

VoiceOver ローターのスクリーンショット。「リンク」を表示している
「記事を読む」や「プロジェクトをみる」のように、同じ文字列でリンク先が異なる要素が複数存在し、見分けがつかない

この問題に取り組むには、以下の改善案が考えられます。

  1. aria-label 属性で補足
  2. .sr-only(スクリーンリーダー向けのテキスト)で補足
  3. aria-describedby 属性で補足
  4. aria-labelledby 属性で補足
  5. title 属性で補足

改善案 1. aria-label 属性

見出し「改善案 1. aria-label 属性」

まず、リンク要素に aria-label 属性を追加して、スクリーンリーダーでの読み上げ時に、リンク先ページを説明する方法が考えられます。

aria-label を指定する例
<a href="..." aria-label="CSS Color 再入門">記事を読む</a>

このように指定することで、macOS VoiceOver であれば「記事を読む」は無視され、「リンク CSS Color 再入門」と、記事タイトルを読ませることができます。

しかし、このように、テキストラベルを aria-label 属性などのアクセシブルな名前で置き換える方法はアンチパターンなので避けるべきです。

WCAG 2.1 の達成基準「2.5.3 名前(name)のラベル」では以下のように説明されています。この基準はレベル A です。

ユーザインタフェース コンポーネントがテキスト又は文字画像を含むラベルを持つ場合、視覚的に提示されたテキストが名前 (name) に含まれている。

Web Content Accessibility Guidelines (WCAG) 2.1 日本語訳

つまり、リンクやフォーム要素などの要素に可視のテキストラベルが存在する場合には、スクリーンリーダーや音声コントロールなどの支援技術を使用しているユーザの利用体験を損なわないためにも、見た目上のテキストラベルと、支援技術が認識する名前(アクセシブルな名前)が一致するべきであるということです。

上記の例では、スクリーンリーダーでの使い勝手を向上させるために aria-label 属性を追加しましたが、一方で音声コントロールを使用するユーザの利用体験に問題が生じます。

具体的には、音声コントロールを使用するユーザが視覚情報をもとに音声によって操作するとき、見た目上は「記事を読む」にもかかわらず、支援技術が認識するアクセシブルな名前が「CSS Color 再入門」のため、「記事を読むをクリック」と発声しても一致しないためです。

このような理由から、可視テキストを aria-label 属性で上書きすることは極力避けるべきです。

なお、上記のように別のテキストで上書きするのではなく、アクセシブルな名前にテキストラベルを(なるべく先頭に)含める場合には、この基準を達成できます。

aria-label の先頭にテキストラベルを含めた例
<a href="..." aria-label="記事を読む: CSS Color 再入門">記事を読む</a>

関連する WCAG の達成方法集のページは以下です。

しかし、今回の例の「記事を読む」のように、ページ内に同じテキストラベルが複数存在するケースでは完全な解決策とはいえません。

WAI-ARIA は補足的に使用する

見出し「WAI-ARIA は補足的に使用する」

aria-label 属性に限りませんが、可能な限り HTML 要素のみでマークアップすべきであり、WAI-ARIA 属性は、あくまでも手段がないときに補足的に使用すべきです(自戒の念を込めて)。

補足的に使用する例としては、<nav> 要素などのランドマークロールを持つ要素に対して、aria-label 属性を指定するパターンが挙げられます。

スクリーンリーダーによっては、ランドマークを一覧で表示して移動できる機能が備わっていますが、ページ内に <nav> 要素が複数存在する場合に、この aria-label 属性の指定によって、機能を見分けるヒントになります。

ランドマークに aria-label を指定する例
<nav aria-label="メインメニュー">
  <!-- ... -->
</nav>

<nav aria-label="目次">
  <!-- ... -->
</nav>

<nav aria-label="現在地">
  <!-- ... -->
</nav>

<nav aria-label="カテゴリ一覧">
  <!-- ... -->
</nav>

以下は、VoiceOver ローターを使用して、ランドマーク一覧を表示した状態です。

VoiceOver ローターのスクリーンショット。「ランドマーク」を表示している

改善案 2. スクリーンリーダー向けテキスト

見出し「改善案 2. スクリーンリーダー向けテキスト」

続いて、スクリーンリーダー向けの不可視テキストで補足する方法です。

スクリーンリーダー向けのテキストを指定する例
<a href="...">
  記事を読む<span class="sr-only">: CSS Color 再入門</span>
</a>

記事タイトルを含む文字列「: CSS Color 再入門」は、.sr-only に指定している CSS によって視覚的には非表示になりますが、スクリーンリーダーでは「記事を読む: CSS Color 再入門」と読み上げられます。

視覚的に非表示にするスタイルの例
.sr-only {
  margin: -1px;
  padding: 0;
  border-width: 0;
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

.sr-only は「screen reader only」の略で、同様の機能で .visually-hidden と命名されることもあります。どちらも慣例的なクラス名です。

この方法では、支援技術が認識するアクセシブルな名前に、テキストラベルが含まれているので、WCAG 2.1 の達成基準「2.5.3 名前(name)のラベル」はクリアしていますが、「改善案 1」のときと同じく、ページ内で「記事を読む」のテキストラベルが複数存在するため、最適な解決策とはいえません。

また、注意する点としては、WAI-ARIA 同様に .sr-only もまた、他に手段がないときに補足的に、控えめに、そして慎重に使用すべきです。

関連する WCAG の達成方法集のページは以下です。

改善案 3. aria-describedby 属性

見出し「改善案 3. aria-describedby 属性」

ここで、記事コンポーネントの構成要素をもう一度見てみます。

記事コンポーネントの構成要素。タグ、見出し、日付、テキストリンクの要素が含まれる

テキストリンクに関連づけたいのは見出しのテキストなので、この見出し要素に aria-describedby 属性で紐づける方法が考えられます。

aria-describedby を指定する例
<h3 id="heading">CSS Color 再入門</h3>
<a href="..." aria-describedby="heading">記事を読む</a>

Windows NVDA では「記事を読む リンク CSS Color 再入門」と読まれます。

どちらの要素も可視テキストであり、メンテナンス性にも優れているため、一見すると理想的に思えますが、この方法には以下の問題があります。

  • ページ内で id 属性の値が一意でなければならない
  • 一部のスクリーンリーダーではサポートされていない

スクリーンリーダーでの読み上げの例を NVDA としたのは、macOS VoiceOver や Windows ナレーターではサポートされていないためです。

改善案 4. aria-labelledby 属性

見出し「改善案 4. aria-labelledby 属性」

「改善案 3」を展開して、aria-describedby 属性 ではなく aria-labelledby 属性でテキストリンクと見出しを紐づけます。

aria-labelledby を指定する例
<h3 id="heading">CSS Color 再入門</h3>
<a href="..." id="link" aria-labelledby="link heading">記事を読む</a>

Windows NVDA では「リンク 記事を読む CSS Color 再入門」と読まれます。

こちらの方法では「改善案 3」と比較すると、スクリーンリーダーのサポート状況は良いようで、macOS VoiceOver や Windows ナレーターでも同じように読み上げられます。

しかし、管理する id 属性の数が増えるため、コードが複雑になります。

最後に title 属性で補足する方法です。

title を指定する例
<a href="..." title="CSS Color 再入門">記事を読む</a>

このようにテキストリンクに title 属性を付与することで、スクリーンリーダーでは、テキストラベルの後に読み上げられます。しかし、Windows ナレーターでは title 属性が読み上げられませんでした。

また、title 属性を指定すると、マウスカーソルを合わせたときにツールチップが表示されるのが若干気になる点です。

関連する WCAG の達成方法集のページは以下です。

これらの案を比較したうえで、最終的には「改善案 2. スクリーンリーダー向けテキスト」を採用しました。

「改善案 1. aria-label 属性」は、指定する値が重複する点と、一部の機械翻訳において aria-label 属性内のテキストが翻訳されないといったケースも考慮し、プレーンテキストのほうが望ましいと考えました。

「改善案 3. aria-describedby 属性」「改善案 4. aria-labelledby 属性」については、スクリーンリーダーでのサポートが完全ではないのと、id 属性の管理を踏まえて見送りました。

「改善案 5. title 属性」はシンプルに実装できるのですが、一部のスクリーンリーダーでサポートが不十分な点や、長い記事タイトルのときにツールチップの表示が気になるため、採用には至りませんでした。

しかし、どの案を採用した場合でも、ページ内で「記事を読む」のテキストラベルが重複しているため、音声コントロールでの利用体験を損ねる問題は回避できません。これは設計・デザイン上の問題のためです。

テキストリンク「記事を読む」のアクセシビリティ上の問題を改善するために、5 つの案を検討しましたが、本来この問題は、設計・デザイン段階で取り組む必要がありました。

例えば「記事を読む」にリンクを付けるのではなく、見出し要素に付ければ、見た目上のテキストラベルとアクセシブルな名前は一致し、テキストラベルも基本的にはユニークになるため、そもそも問題は発生しませんでした。

コーディングを終えた段階でこのような問題に取り組むと、今回見てきたような、煮え切らない対応を取らざるをえないことを改めて実感しました。

本サイトで実施したウェブアクセシビリティ改善は他にもあるので、また紹介していければと考えています。

脚注

  1. レベル AAA の達成基準「2.4.9 リンクの目的(リンクのみ)」では、リンクのテキスト単独でリンクの目的を判断できることが求められます[Web Content Accessibility Guidelines (WCAG) 2.1 日本語訳]。