Gemcook Tech Blog
🏷️

CSSだけでできるアクセシビリティ改善3選【やりがちなミスも解説】

に公開

前回の記事ではクリッカブルエリアの調整とprefers-reduced-motionを利用したアニメーションの制御について紹介しました。
今回はその続編として、CSSを用いたアクセシビリティ対応のポイントをさらに3つ紹介します。

https://zenn.dev/gemcook/articles/css-accessibility-tips

:focus-visibleを使ったフォーカスインジケーターのカスタマイズ

キーボードでwebサイトを操作した時に、今どの要素にフォーカスが当たっているかわからなくなった経験はありませんか?
フォーカスインジケーター(フォーカスリング)は、キーボード操作をするユーザーにとって「今どこにいるか」を示す重要な視覚的手がかりです。

詳しくは以下の「Web Content Accessibility Guidelines (WCAG)」を参照してください。

https://www.w3.org/WAI/WCAG22/Understanding/focus-visible.html

outline: noneの落とし穴

CSSリセットなどで以下のようなコードを見たことはありませんか?

*:focus {
  outline: none;
}

この記述はフォーカスインジケーターを完全に消してしまうため、キーボードユーザーがどの要素にフォーカスしているかわからなくなってしまいます。
WCAG 2.4.7「Focus Visible(レベルAA)」では、キーボード操作可能なUIにはフォーカスインジケーターが見える状態であることが求められています。
そのため、outline: noneを使う場合は必ず代替のフォーカススタイルをセットで定義するようにしましょう。

:focus:focus-visibleの違い

:focusはマウスクリック時にもフォーカススタイルが表示されますが、:focus-visibleはブラウザが「フォーカスインジケーターの表示が必要」と判断した場合にのみ適用されます。
具体的にはキーボード操作でフォーカスした時にスタイルが当たり、マウスクリック時には当たらないという挙動になります。

これにより「マウスクリックした時にoutlineが表示されて見た目が気になる」という問題を解決しつつ、キーボードユーザーにはしっかりフォーカスを表示することができます。

https://developer.mozilla.org/ja/docs/Web/CSS/:focus-visible

対応方法について

:focus-visibleを利用してフォーカスインジケーターをカスタマイズするコードは以下になります。

<a class="link" href="#">リンク1</a>
<button class="button" type="button">ボタン1</button>
/* マウスクリック時のoutlineを非表示にする */
.link:focus:not(:focus-visible),
.button:focus:not(:focus-visible) {
  outline: none;
}

/* キーボード操作時のフォーカススタイル */
.link:focus-visible,
.button:focus-visible {
  outline: 2px solid #1a73e8;
  outline-offset: 2px;
  border-radius: 2px;
}

ポイントとしては以下になります。

  • :focus:not(:focus-visible)でマウスクリック時のoutlineを非表示にする。
  • :focus-visibleでキーボード操作時のみフォーカススタイルを適用する。
  • outline-offsetでoutlineと要素の間に余白を持たせることで視認性を向上させる。
  • フォーカスインジケーターのコントラスト比は3:1以上にすることが推奨されています(WCAG 2.2 SC 2.4.13 Focus Appearance)。

DevToolsでフォーカス状態を確認する方法

実際にキーボードで操作しなくても、ブラウザのDevToolsでフォーカス状態を確認することができます。

  1. DevToolsを開く(F12 or Cmd + Option + I
  2. 確認したい要素を選択
  3. 「Styles」パネルの :hov ボタンをクリック
  4. :focus-visible にチェックを入れる

フォーカスを確認する方法

これでフォーカス状態のスタイルを手軽に確認することができます。

カラーコントラストを意識する

テキストと背景の色の組み合わせによっては、色覚特性のあるユーザーや視力の弱いユーザーがテキストを読みにくくなってしまう ことがあります。
デザイン上おしゃれな薄いグレーのテキストも、アクセシビリティ的には問題になるケースがあります。

CSSで色を定義する際に、十分なコントラスト比を確保 することが大切です。

詳しくは以下の「Web Content Accessibility Guidelines (WCAG)」を参照してください。

https://waic.jp/translations/WCAG21/Understanding/contrast-minimum.html

WCAGで求められるコントラスト比について

WCAGでは以下のコントラスト比が求められています。

テキストの種類 最低限(AA) より高い基準(AAA)
通常テキスト 4.5:1 7:1
大きいテキスト(24px以上 / Bold 18.66px以上) 3:1 4.5:1

対応方法について

コントラスト比が低い例と十分な例のコードは以下になります。

/* ❌ コントラスト比が低い例(約2.6:1) */
.text-low-contrast {
  color: #999999;
  background-color: #ffffff;
}

/* ✅ コントラスト比が十分な例(約8.6:1) */
.text-high-contrast {
  color: #333333;
  background-color: #ffffff;
}

またprefers-color-scheme を利用してダークモードに対応する場合も、ライトモード・ダークモードそれぞれでコントラスト比を確認するようにしましょう!

/* ダークモード対応の例 */
:root {
  --color-text: #333333;
  --color-background: #ffffff;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-text: #e5e5e5;
    --color-background: #1a1a1a;
  }
}

コントラスト比を確認したい時に

以下のツールで簡単にコントラスト比を確認できます。

webサイトで確認する

https://webaim.org/resources/contrastchecker/

Chrome DevTools を利用して確認する

以下の手順で確認を行うことができます。

  1. DevTools を開く(F12 または Cmd + Option + I
  2. Elements タブ左上の矢印アイコン(インスペクターボタン)をクリック
  3. ページ上の確認したいテキスト要素にカーソルを合わせる
  4. ツールチップにコントラスト比が表示される(問題がある場合は ⚠️ マークつき)

Chrome DevToolsでの確認

visually-hiddenパターンでスクリーンリーダーに情報を提供する

アイコンのみのボタンやデザイン上テキストを省略している箇所で「このボタン何だろう?」と思ったことはありませんか?
見た目にはわかっていても、スクリーンリーダーを利用しているユーザーにはその意味が伝わらないことがあります。

そのような場合に、見た目には隠しつつスクリーンリーダーには読み上げられるテキストを追加するvisually-hiddenパターンが有効です。

display: nonevisibility: hiddenではダメな理由

/* これらはスクリーンリーダーからも隠れてしまう */
.hidden-1 {
  display: none;
}
.hidden-2 {
  visibility: hidden;
}

display: nonevisibility: hiddenを利用してしまうと、スクリーンリーダーからもコンテンツが見えなくなってしまうため、必要な情報を読み上げてもらうことができません。

visually-hiddenクラスの実装

見た目には隠しつつ、スクリーンリーダーからはアクセス可能にするCSSパターンは以下になります。

.visually-hidden {
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}

各プロパティの役割について解説します。

clip: rect(0 0 0 0) / clip-path: inset(50%)

要素の可視領域をゼロにクリッピングします。
clipは現在**非推奨(Deprecated)**となっており、clip-pathが後継の標準プロパティです。
レガシーブラウザをサポートする必要がない場合はclip-pathのみでも問題ありません。

https://developer.mozilla.org/ja/docs/Web/CSS/clip

https://developer.mozilla.org/ja/docs/Web/CSS/clip-path

height: 1px / width: 1px

要素のサイズを1pxに設定します。
0pxに設定すると一部のブラウザでアクセシビリティツリーから除外される可能性があるため、1pxにしています。

overflow: hidden

1pxの領域からはみ出すコンテンツを非表示にします。

position: absolute

要素を通常のレイアウトフローから外して、他の要素のレイアウトに影響を与えないようにします。

white-space: nowrap

テキストの折り返しを防止します。
スクリーンリーダーのビジュアルトラッキング(読み上げ位置を視覚的に示す機能)が正しく動作するために必要です。

利用例1: アイコンのみのボタン

<button class="icon-button" type="button">
  <svg aria-hidden="true" width="24" height="24" viewBox="0 0 24 24">
    <!-- ハンバーガーメニューのアイコン -->
    <path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z" />
  </svg>
  <span class="visually-hidden">メニューを開く</span>
</button>

ポイントとしては以下になります。

  • SVGにはaria-hidden="true"を追加してスクリーンリーダーからアイコン自体を隠す。
  • visually-hiddenクラスを利用したspanでボタンの意味をスクリーンリーダーに伝える。
  • スクリーンリーダーは「メニューを開く、ボタン」と読み上げる。

利用例2: 「もっと見る」リンクの補足

一覧ページなどで「もっと見る」というリンクが複数あると、スクリーンリーダーではすべてが同じ「もっと見る」として読み上げられてしまい、どの「もっと見る」なのかが区別できません。

<a href="/news">
  もっと見る<span class="visually-hidden">(ニュース一覧)</span>
</a>
<a href="/blog">
  もっと見る<span class="visually-hidden">(ブログ一覧)</span>
</a>

これにより、スクリーンリーダーでは「もっと見る(ニュース一覧)、リンク」のように読み上げてくれるため、どのリンクなのかを区別することができます。

利用例3: スキップリンク

ページの先頭にあるナビゲーションをスキップして、メインコンテンツに直接移動するための「スキップリンク」にも活用できます。
通常は非表示ですが、Tabキーでフォーカスが当たった時に表示されるようにします。

<a class="skip-link" href="#main-content">メインコンテンツへスキップ</a>
.skip-link {
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}

.skip-link:focus {
  clip: auto;
  clip-path: none;
  height: auto;
  overflow: visible;
  position: fixed;
  top: 8px;
  left: 8px;
  width: auto;
  z-index: 9999;
  padding: 8px 16px;
  background: #000;
  color: #fff;
  font-size: 14px;
  border-radius: 4px;
}

フォーカスを受け取った時にclipclip-pathをリセットすることで、視覚的にもリンクが表示されるようになります。

CSSフレームワークでの対応

代表的なCSSフレームワークでは、このパターンがユーティリティクラスとして提供されています。

フレームワーク クラス名
Bootstrap 5 .visually-hidden
Tailwind CSS .sr-only

自前でCSSを書かなくても利用できるため、フレームワークを利用している場合はこれらのクラスを活用すると便利です。

https://getbootstrap.com/docs/5.3/helpers/visually-hidden/

https://tailwindcss.com/docs/screen-readers

CSSの小さな工夫でアクセシブルなwebを

今回紹介した3つのテクニックをまとめると以下になります。

  • :focus-visible: キーボードユーザーにはフォーカスを見せつつ、マウスユーザーには余計なoutlineを見せない。
  • カラーコントラスト: テキストと背景に十分なコントラスト比を確保して、色覚特性や視力に関わらず読みやすくする。
  • visually-hidden: 見た目は隠しつつ、スクリーンリーダーユーザーに必要な情報を伝える。

前回の記事で紹介したクリッカブルエリアの調整やprefers-reduced-motionと合わせて、CSSでのアクセシビリティ対応を意識していきましょう。
小さな改修でもユーザーの体験が大きく変わることがあるので、少しずつ取り入れていくのがおすすめです。

最後までお読みいただき、ありがとうございました!!

Gemcook Tech Blog
Gemcook Tech Blog

Discussion