文字サイズ変更(Font Size)— 標準・大・特大の3段階切り替え

表示・インジケーター 初級

このコンポーネントについて

文字サイズ変更は、Webアプリ全体のテキストを「標準・大・特大」の3段階で切り替えるアクセシビリティ向けUIです。文字の見えにくいユーザーや、画面との距離が遠い環境での視認性を高めることを目的としています。

このページでは、CSS カスタムプロパティ(変数)を使って見出し・本文・ラベルなど元々サイズが異なるすべてのテキスト要素を比例スケールする実装例を紹介します。ラベルに「小・中・大」ではなく「標準・大・特大」を採用しているのは、「小さい」を基準にすると大きな文字を必要とするユーザーが「自分は特別な設定が必要だ」と感じてしまうことへの配慮です。

  • 3段階のサイズ切り替え — 「標準・大・特大」のボタンで文字サイズを切り替える。スライダーではなくボタン形式のため、指の細かい動作が難しいユーザーでも操作しやすい
  • 全文字要素への一括適用 — CSS カスタムプロパティ --fs-scale をコンテナ要素に設定し、すべての子要素が em 単位で比例スケールする。見出し・本文・ラベル・キャプションなど元々サイズが異なる要素がすべて連動する
  • 設定の永続化(localStorage) — ブラウザに選択状態を保存し、ページリロード後も前回の設定が引き継がれる
  • アクティブ状態の明示 — 現在選択中のサイズのボタンを強調し、aria-pressed 属性でスクリーンリーダーにも状態を伝える

実装のポイント・注意点

CSS カスタムプロパティ(変数)は、親要素に定義した値をすべての子要素が参照できる仕組みです。.fs-root--fs-scale: 1 を設定し、font-size: calc(14px * var(--fs-scale)) をベースに指定します。子要素はすべて em 単位で相対指定(例:.fs-heading-lg { font-size: 1.5em })することで、--fs-scale が変わったとき全要素が一斉にスケールします。

emrem の使い分けに注意が必要です。remhtml 要素(ルート)のフォントサイズを基準にするため、.fs-root の変数を変えてもブラウザのデフォルトサイズに引きずられてしまいます。em は親要素のフォントサイズを基準にするため、このコンポーネントのようにコンテナスコープ内でスケールを制御したい場合に適しています。

localStorage の保存キーはアプリ固有の名前にすることをおすすめします。他のページや機能と同じキー名を使うと設定が上書きされる可能性があります。サンプルコードでは 'fsFontScale' を使っていますが、実プロジェクトに組み込む際は 'myAppFontScale' のようにアプリ名を含めたキー名に変更してください。

HTML・CSS・バニラJavaScriptのみで実装しており、フレームワーク不要でコピペすぐに動きます。

デモ

文字サイズ:

ユーザー管理

基本情報

登録ユーザーの氏名・メールアドレス・所属部署などの基本情報を編集できます。変更後は「保存」ボタンを押してください。

氏名 山田 太郎
メール [email protected]
部署 開発部
権限 管理者

最終更新:2025-06-01 / 変更履歴は管理ログで確認できます。

サンプルソース

3つのファイルを同じフォルダに保存し、index.html をブラウザで開くとすぐに動作確認できます。
ファイル名:index.html / style.css / script.js — 保存時の文字コードは UTF-8 を指定してください(Shift-JISだと日本語が文字化けします)。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>文字サイズ変更 サンプル</title>
  <link rel="stylesheet" href="./style.css">
</head>
<body>

<div class="fs-root" id="fsRoot">
  <!-- サイズ切り替えコントロール -->
  <div class="fs-controls">
    <span class="fs-controls-label">文字サイズ:</span>
    <button class="fs-btn is-active" data-scale="1" aria-pressed="true">標準</button>
    <button class="fs-btn" data-scale="1.2" aria-pressed="false">大</button>
    <button class="fs-btn" data-scale="1.45" aria-pressed="false">特大</button>
  </div>

  <!-- コンテンツ(fs-heading-lg / fs-heading-sm は h2/h3 タグに変更しても動作します) -->
  <div class="fs-content">
    <p class="fs-heading-lg">ユーザー管理</p>
    <p class="fs-heading-sm">基本情報</p>
    <p class="fs-body">登録ユーザーの氏名・メールアドレス・所属部署などの基本情報を編集できます。変更後は「保存」ボタンを押してください。</p>
    <div class="fs-data-rows">
      <div class="fs-data-row">
        <span class="fs-label">氏名</span>
        <span class="fs-value">山田 太郎</span>
      </div>
      <div class="fs-data-row">
        <span class="fs-label">メール</span>
        <span class="fs-value">[email protected]</span>
      </div>
      <div class="fs-data-row">
        <span class="fs-label">部署</span>
        <span class="fs-value">開発部</span>
      </div>
      <div class="fs-data-row">
        <span class="fs-label">権限</span>
        <span class="fs-value">管理者</span>
      </div>
    </div>
    <p class="fs-caption">最終更新:2025-06-01 / 変更履歴は管理ログで確認できます。</p>
  </div>
</div>

<script src="./script.js"></script>
</body>
</html>
*, *::before, *::after { box-sizing: border-box; }

body {
  font-family: sans-serif;
  padding: 24px;
  background: #f0f2f5;
}

/* ===== フォントスケールをCSS変数で管理 ===== */
/* --fs-scale の値を変えると、em 指定のすべての子要素が比例してスケールされる */
.fs-root {
  --fs-scale: 1;
  font-size: calc(14px * var(--fs-scale));
  background: #ffffff;
  border: 1.5px solid #e2e8f0;
  border-radius: 12px;
  max-width: 480px;
  overflow: hidden;
}

/* ===== サイズ切り替えコントロール ===== */
.fs-controls {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 20px;
  background: #f4f6f9;
  border-bottom: 1px solid #e2e8f0;
  flex-wrap: wrap;
}

.fs-controls-label {
  font-size: 13px;
  color: #5a6a7a;
  font-weight: 600;
  white-space: nowrap;
}

.fs-btn {
  padding: 6px 14px;
  font-size: 13px;
  font-weight: 600;
  color: #5a6a7a;
  background: #ffffff;
  border: 1.5px solid #d0d7e0;
  border-radius: 6px;
  cursor: pointer;
  font-family: sans-serif;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.fs-btn:hover {
  background: #e8f0fe;
  border-color: #2b7fe8;
  color: #2b7fe8;
}

/* 選択中のボタン */
.fs-btn.is-active {
  background: #2b7fe8;
  border-color: #2b7fe8;
  color: #ffffff;
}

/* ===== コンテンツエリア ===== */
.fs-content {
  padding: 20px 24px 24px;
}

/* 大見出し(1.5em = 21px at 標準)*/
.fs-heading-lg {
  margin: 0 0 8px;
  font-size: 1.5em;
  font-weight: 700;
  color: #1a2332;
  line-height: 1.3;
  transition: font-size 0.2s ease;
}

/* 中見出し(1.15em = 16.1px at 標準)*/
.fs-heading-sm {
  margin: 0 0 10px;
  font-size: 1.15em;
  font-weight: 600;
  color: #2b4066;
  line-height: 1.4;
  transition: font-size 0.2s ease;
}

/* 本文(1em = 14px at 標準)*/
.fs-body {
  margin: 0 0 16px;
  font-size: 1em;
  color: #5a6a7a;
  line-height: 1.7;
  transition: font-size 0.2s ease;
}

/* ===== ラベル付きデータ行 ===== */
.fs-data-rows {
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  overflow: hidden;
  margin-bottom: 16px;
}

.fs-data-row {
  display: flex;
  align-items: baseline;
  gap: 16px;
  padding: 10px 14px;
  border-bottom: 1px solid #e2e8f0;
}

.fs-data-row:last-child {
  border-bottom: none;
}

.fs-label {
  font-size: 1em;
  font-weight: 600;
  color: #7a8a9a;
  min-width: 4em;
  flex-shrink: 0;
}

.fs-value {
  font-size: 1em;
  color: #1a2332;
}

/* キャプション(0.85em = 11.9px at 標準)*/
.fs-caption {
  margin: 0;
  font-size: 0.85em;
  color: #9aa5b4;
  line-height: 1.6;
  transition: font-size 0.2s ease;
}
var root = document.getElementById('fsRoot');
var buttons = document.querySelectorAll('.fs-btn');

// ページを開いたとき、前回保存した文字サイズを読み込んで反映する
// ※ 実プロジェクトに組み込む際は 'fsFontScale' をアプリ固有のキー名に変更してください
var savedScale = localStorage.getItem('fsFontScale');
if (savedScale) {
  applyScale(savedScale);
}

// 各ボタンにクリックイベントを登録
buttons.forEach(function(btn) {
  btn.addEventListener('click', function() {
    applyScale(btn.dataset.scale);
    // 選択した文字サイズをブラウザに保存しておく(ページを閉じても設定が残る)
    localStorage.setItem('fsFontScale', btn.dataset.scale);
  });
});

// フォントサイズを変更し、ボタンのアクティブ状態を更新する
function applyScale(scale) {
  // CSS変数を更新 → em 指定の子要素がすべて比例してスケールされる
  root.style.setProperty('--fs-scale', scale);

  // ボタンのアクティブ状態と aria-pressed を更新
  buttons.forEach(function(btn) {
    var isActive = btn.dataset.scale === String(scale);
    btn.classList.toggle('is-active', isActive);
    btn.setAttribute('aria-pressed', isActive ? 'true' : 'false');
  });
}

AI用プロンプト

以下のプロンプトをコピーしてAIに渡すと、同様のコンポーネントを生成できます。

ChatGPTやClaudeにこのプロンプトを渡すと、同様のコンポーネントをゼロから生成・カスタマイズできます。ライブラリ指定やスケール値変更など、要件を追記して使うのがおすすめです。

※ このプロンプトを使ってもデモとまったく同じ動作にならない場合があります。AIの解釈や生成タイミングによって差が出ることをご了承ください。

💡 jQuery・Vue・React など特定のライブラリで実装したい場合は、プロンプトの末尾に「〇〇を使って実装してください」と追記してください。

# 文字サイズ変更(アクセシビリティ) 作成依頼

## 概要
Webアプリ全体の文字サイズを「標準・大・特大」の3段階で切り替えられるUIを作成してください。
業務アプリのアクセシビリティ設定として組み込むことを想定したコンポーネントです。

## 要件
- 「標準・大・特大」の3段階切り替えボタンを配置する(スライダーではなくボタン形式)
- ボタンクリックで CSS カスタムプロパティ --fs-scale を変更し、コンテナ内の全文字要素が比例してスケールする
- 見出し・本文・ラベル・キャプションなど元々サイズが異なる要素がすべて連動することをデモで示す
- 現在選択中のボタンをアクティブスタイルで強調し、aria-pressed 属性も更新する
- localStorage を使って選択状態をブラウザに保存し、ページリロード後も設定を引き継ぐ
- ラベルは「小・中・大」ではなく「標準・大・特大」とする(「小」を基準にすると標準サイズが「小さい」という暗示になり、大きい文字を必要とするユーザーが「自分は特別な設定が必要」と感じる問題があるため)

## 技術仕様
- HTML / CSS / バニラJavaScript で実装
- 外部ライブラリ:なし
- レスポンシブ対応:必要(スマホ幅でボタン・コンテンツが崩れないこと)

## 動作詳細
- ベースフォントサイズ: 14px × スケール値(コンテナの --fs-scale で制御)
- 標準: scale = 1(14px 相当)
- 大: scale = 1.2(16.8px 相当)
- 特大: scale = 1.45(20.3px 相当)
- コンテナ(.fs-root)に --fs-scale: 1 を CSS 変数として定義し、font-size: calc(14px * var(--fs-scale)) をベースに設定する
- すべての子テキスト要素は em 単位で相対指定することで、ベースサイズの変化に連動させる
- デモコンテンツ: ページタイトル(大見出し)・セクション見出し(中見出し)・本文テキスト・ラベル+値の行×4・キャプション

## 出力形式
HTML・CSS・JavaScriptを分けて出力してください。
各ファイルは単独でコピー&ペーストして使えるよう記述してください。