顕微鏡のイラスト

テキストサイズの拡大設定の問題と解決策

WCAG 2.2 では、ユーザーが画像拡大ソフトや支援技術を使用せずに、200% までテキストを拡大してもコンテンツが正しく表示されることを要求しています。しかし、テキストサイズの拡大に関しては、ブラウザや OS の設定を尊重せず、ユーザーがテキストサイズを拡大してもコンテンツが拡大されないという問題が長年存在していました。この記事では、この問題の原因と解決策について解説します。

WCAG 2.2 では、ユーザーが画像拡大ソフトや支援技術を使用せずに、200% までテキストを拡大してもコンテンツが正しく表示されることを要求しています(1.4.4 Resize Text)。ロービジョンのユーザーの多くは OS やブラウザのテキストサイズの設定を使用してテキストを拡大しています。しかし、テキストサイズの拡大に関しては、ブラウザや OS の設定を尊重せず、ユーザーがテキストサイズを拡大してもコンテンツが拡大されないという問題が長年存在していました。大きく分けて以下の 2 つの問題があります。

  • フォントサイズの単位に px を使用している場合、一部のブラウザではユーザーのテキストサイズの設定が無視され、テキストが拡大されない問題
  • OS のテキストサイズの変更がブラウザに反映されない問題

フォントサイズの単位に px を使用している場合の問題

ブラウザのテキストサイズの設定について見てみましょう。Google Chrome では、設定 > デザイン > フォントサイズからテキストサイズを「極小」から「極大」の 5 段階で設定できます。

Firefox では、設定 > 一般 > 言語と外観 > フォントからピクセル単位でフォントサイズを設定できます。

Safari では、設定 > 詳細 > アクセシビリティから最小のフォントサイズを設定できます。

しかし、Google Chrome ではフォントサイズの単位に px を使用している場合、ブラウザの設定が無視され、ユーザーがテキストサイズを拡大してもコンテンツが拡大されないという問題が存在します。Google Chrome のフォントサイズの拡大設定は実際にはルート要素 <html> のデフォルトのフォントサイズ(16px)を拡大するものであるためです。この問題を回避するために、CSS では remem などの相対単位や % を使用することが推奨されてきました。

実際に以下のコードで確認してみましょう。それぞれの要素のフォントサイズの単位を px, rem, % にしてみます。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Text Scaling Test</title>
    <style>
      .px {
        font-size: 16px;
      }
      .rem {
        font-size: 1rem;
      }
      .percent {
        font-size: 100%;
      }
    </style>
  </head>
  <body>
    <p class="px">This text uses px units.</p>
    <p class="rem">This text uses rem units.</p>
    <p class="percent">This text uses percent units.</p>
  </body>
</html>

Google Chrome のテキストサイズの設定を「極大」にしてみると、.px クラスのテキストは拡大されませんが、.rem.percent クラスのテキストは拡大されることがわかります。

一方で Firefox や Safari などのブラウザは、フォントサイズの単位が px であってもユーザーのテキストサイズの設定を尊重して拡大するため、この問題は発生しませんでした。

この問題を回避するために今日ではフォントサイズや margin, padding, gap などのレイアウトに関するプロパティの単位には px といった絶対値を使用せず、remem などの相対単位や % を使用することが推奨されています。このプラクティスは後者の OS のテキストサイズの変更がブラウザに反映されない問題にも関わってきます。

OS のテキストサイズの変更がブラウザに反映されない問題

OS レベルでもテキストサイズを変更できます。macOS では、システム設定 > アクセシビリティ > ディスプレイ > テキスト > テキストサイズから変更できます。

iOS では、設定 > アクセシビリティ > 画面表示とテキストサイズ > さらに大きな文字から変更できます。

OS やブラウザの組み合わせによっても異なりますが、OS のテキストサイズの変更がブラウザに反映されない問題も存在します。MacOS + Google Chrome の組み合わせや iOS + Safari の組み合わせではテキストサイズは拡大されませんでした。手元にないので検証できないのですが、Android + Firefox の組み合わせ、Windows 11 + Chrome or Edge、Firefox の組み合わせでは OS のテキストサイズの変更がブラウザに反映されるようです。

フォントサイズレベルでの拡大ができないと、ユーザーはブラウザのズーム機能を使用して拡大する必要がありますが、すべての要素が拡大されるため、レイアウトが崩れたりするといった問題が発生します。特に画面幅が狭いモバイルデバイスでは、より深刻な問題になります。このように OS のテキストサイズの変更がブラウザに反映されない問題はユーザーのアクセシビリティに大きな影響を与えることが広く知られていたため、いくつかの解決策が提案されています。

iOS の非標準的なアプローチ

WebKit ベースのブラウザでは font-family の値として -apple-system-* を使用することで iOS で最適なフォントが選択されるようになります。これにより OS レベルのフォントの設定が動的に反映されるようになるため、ブラウザで表示されるテキストのサイズも OS のテキストサイズの変更に応じて拡大されるようになります。

:root {
  font: -apple-system-body;
}
 
body {
  font-family: sans-serif;
  font-style: initial;
  font-weight: initial;
}

https://ia11y.github.io/Coding-Patterns/iOS/text-resizing/ios-system-fonts.html でこの挙動を確認できます。iOS で確認するとたしかに OS のテキストサイズの変更に応じてテキストが拡大されることがわかります。

env(preferred-text-scale)

標準的なアプローチとしては、CSS の環境変数 env(preferred-text-scale) を使用する方法が提案されています。env(preferred-text-scale) はユーザーのテキストサイズの設定に基づいて拡大率を返す環境変数です。これを使用することで、ユーザーのテキストサイズの設定に応じてフォントサイズを拡大できます。

ページ全体のテキストをユーザーのテキストサイズの設定に応じて拡大するには、以下のようにルート要素のフォントサイズを env(preferred-text-scale) を使用して設定します。remem などの相対単位を使用している場合、ルート要素のフォントサイズが拡大されることで、ページ全体のテキストがユーザーのテキストサイズの設定に応じて拡大されるようになります。また env 関数の第 2 引数にデフォルト値も指定できます。

env(preferred-text-scale) を使用してフォントサイズを動的に拡大させる場合、2 重に拡大されるのを防止するために、text-size-adjust: none を指定することが推奨されます。text-size-adjust プロパティは、ユーザーのテキストサイズの設定に応じてフォントサイズを自動的に拡大するかどうかを制御するプロパティで、一部のモバイルブラウザでのみ機能します。

:root {
  font-size: calc(100% * env(preferred-text-scale, 1));
  text-size-adjust: none;
}
 
p {
  font-size: 1rem;
}

ただし、この方法ではメディアクエリのブレークポイントはフォントスケールを考慮しないため、ユーザーが大きなフォントサイズを設定している場合にレイアウトが崩れる可能性があります。この制限を解決するのが、次に紹介する text-scale meta タグです。

text-scale meta タグ

meta タグ text-scale ではページ全体にユーザーのテキストサイズの設定に応じて拡大するかどうかを指定します。text-scale meta タグは値として legacyscale を取ります。legacy は従来の挙動を維持し、scale はユーザーのテキストサイズの設定を尊重して拡大する挙動を指定します。

<meta name="text-scale" content="scale" />

この text-scale の値に content="scale" を指定している場合、以下の CSS を指定しているのと同義になります。

:root {
  font-size: calc(100% * env(preferred-text-scale));
  text-size-adjust: none;
}

ウェブサイトの開発者は remem などの相対単位を使用している場合、text-scale meta タグを使用するだけで、ユーザーのテキストサイズの設定に応じてテキストが拡大されるようになるのです。env(preferred-text-scale) を使用して CSS でフォントサイズを動的に拡大する方法と比べて、CSS を変更することなく OS やブラウザのテキストサイズの設定を尊重してテキストを拡大できるようになるという点がこの meta タグの大きな利点です。

text-scale meta タグは現在 Android 版の Chrome でのみサポートされています。現時点では広くサポートされていないものの、将来の対応に備えてフォントサイズやレイアウトを設計する際には相対単位である remem を使用することが推奨されます。またデフォルトのフォントサイズを上書きしないことも重要です。<meta name="text-scale" content="scale" /> を使用する場合、ユーザーの設定によりルートレベルのデフォルトのフォントサイズを変更できるようになりますが、これを上書きしてしまうとユーザーのテキストサイズの設定が反映されなくなってしまいます。

<meta name="text-scale" content="scale" />
<style>
  :root {
    /* NG: ユーザーが設定したテキストサイズの拡大率が反映されなくなる */
    font-size: 10px;
  }
</style>

まとめ

  • フォントサイズの単位に px を使用している場合、一部のブラウザではユーザーのテキストサイズの設定が無視され、テキストが拡大されない問題が存在するため、フォントサイズやレイアウトの単位には remem などの相対単位や % を使用することが推奨される
  • OS のテキストサイズの変更がブラウザに反映されない問題も存在する
  • 非標準なアプローチとしては、iOS の非標準的なアプローチである -apple-system-* を使用する方法がある
  • 標準的なアプローチとしては、CSS の環境変数 env(preferred-text-scale) を使用する方法がある。env(preferred-text-scale) はユーザーのテキストサイズの設定に基づいて拡大率を返す環境変数で、これを使用することでユーザーのテキストサイズの設定に応じてフォントサイズを拡大できる
  • より簡単なアプローチとしては、text-scale meta タグを使用する方法がある。text-scale meta タグは値として legacyscale を取り、content="scale" を指定することでユーザーのテキストサイズの設定を尊重して拡大する挙動を指定できる

参考

記事の理解度チェック

以下の問題に答えて、記事の理解を深めましょう。

Google Chrome でブラウザのテキストサイズの設定を「極大」にしている場合、設定が無視されてテキストが拡大されないフォントサイズの単位はどれですか?

  • `px`

    正解!

    絶対単位である `px` を使用している場合、Google Chrome ではユーザーのテキストサイズの設定が反映されなくなってしまいます。相対単位である `rem` や `%` を使用することが推奨されます。

  • `rem`

    もう一度考えてみましょう

  • `em`

    もう一度考えてみましょう

  • `%`

    もう一度考えてみましょう

`text-scale` meta タグの `content` 属性に指定できる値として正しい組み合わせはどれか?

  • `none` と `auto`

    もう一度考えてみましょう

  • `legacy` と `scale`

    正解!

    `legacy` は従来の挙動を維持し、`scale` はユーザーのテキストサイズの設定を尊重して拡大する挙動を指定します。

  • `default` と `responsive`

    もう一度考えてみましょう

  • `fixed` と `dynamic`

    もう一度考えてみましょう