T-CREATOR

ESLint でアクセシビリティを向上させる a11y ルール活用術

ESLint でアクセシビリティを向上させる a11y ルール活用術

Web アクセシビリティは、すべてのユーザーが快適に Web サイトを利用できるようにするための重要な要素です。しかし、開発過程でアクセシビリティ対応を手動で行うのは時間がかかり、見落としも発生しがちですね。

そこで注目したいのが、ESLint の a11y(アクセシビリティ)ルールです。これらのルールを活用することで、コーディング段階からアクセシビリティ問題を自動検出し、品質の高い Web アプリケーションを効率的に開発できるようになります。

本記事では、ESLint の a11y ルールを使った実践的なアクセシビリティ向上手法をご紹介します。

背景

現代の Web 開発において、アクセシビリティは法的要件や社会的責任としてますます重要になっています。しかし、実際の開発現場では多くの課題が存在しているのが現状です。

Web アクセシビリティの現状と課題

Web アクセシビリティ基盤委員会(WAIC)の調査によると、日本の企業サイトの多くでアクセシビリティ対応が不十分な状況が続いています。特に以下のような問題が頻発しているのです。

  • 画像に alt 属性が設定されていない
  • フォーカス順序が論理的でない
  • ARIA 属性の誤用や不適切な使用
  • キーボードナビゲーションへの未対応

これらの問題は、視覚障害や運動障害を持つユーザーの Web 利用を大きく妨げてしまいます。

手動チェックの限界

従来のアクセシビリティ対応では、開発完了後に手動でチェックツールを使用することが一般的でした。しかし、この方法には明確な限界があります。

アクセシビリティ問題の発見・修正フローを図で確認してみましょう。

mermaidflowchart LR
  develop[開発完了] -->|手動チェック| check[アクセシビリティ検証]
  check -->|問題発見| fix[修正作業]
  fix -->|再チェック| check
  check -->|問題なし| release[リリース]

  style develop fill:#e1f5fe
  style check fill:#fff3e0
  style fix fill:#ffebee
  style release fill:#e8f5e8

手動チェックでは発見が遅れ、修正コストが高くなってしまいます。また、チェック作業自体にも専門知識が必要で、見落としのリスクも避けられません。

開発フローでの自動化の必要性

現代のアジャイル開発や CI/CD パイプラインでは、品質保証をできるだけ早い段階で自動化することが重要です。アクセシビリティについても同様で、コーディング段階から自動的に問題を検出できる仕組みが求められています。

ESLint のようなリンターツールを活用することで、開発者がコードを書いている最中にリアルタイムでアクセシビリティ問題を発見し、即座に修正できるようになるのです。

課題

アクセシビリティ対応を進める上で、多くの開発チームが直面する課題を詳しく見ていきましょう。

アクセシビリティ対応の工数とコスト

アクセシビリティ対応は「後から追加する機能」として捉えられがちで、プロジェクトの工数やコストを圧迫する要因と認識されることがあります。

実際に、既存の Web アプリケーションにアクセシビリティ対応を後付けで行う場合、以下のような工数が必要になります。

作業項目工数目安備考
現状調査・問題抽出2-3 日専門知識が必要
修正方針の策定1-2 日デザインシステムへの影響考慮
コード修正作業5-10 日問題の複雑さに依存
検証・テスト2-3 日手動および自動テスト
ドキュメント整備1 日ガイドライン作成

このように、後付け対応では相当な工数が発生してしまうのが実情です。

知識不足による見落とし

アクセシビリティには WCAG(Web Content Accessibility Guidelines)や WAI-ARIA などの専門的な知識が必要です。しかし、すべての開発者がこれらの知識を十分に持っているとは限りません。

特に以下のような項目は、知識がないと見落としやすい問題です。

  • セマンティック HTML の適切な使用divspan ばかり使用してしまう
  • ARIA 属性の正しい利用aria-labelaria-labelledby の使い分け
  • フォーカス管理:モーダルやドロップダウンでのフォーカストラップ
  • 色彩コントラスト:背景色と文字色のコントラスト比

これらの問題は、コードレビューでも見落とされることが多く、最終的にユーザビリティの低下を招いてしまいます。

継続的な品質維持の困難

アクセシビリティは一度対応すれば終わりではありません。新機能の追加や既存機能の改修時にも、常にアクセシビリティを意識した開発を継続する必要があります。

しかし、プロジェクトが進行する中で以下のような問題が発生しがちです。

  • 新しいメンバーがアクセシビリティルールを把握できていない
  • リリース期限に追われて、アクセシビリティチェックが後回しになる
  • 機能追加時にアクセシビリティ問題が紛れ込んでしまう

継続的な品質維持には、チーム全体でのルール共有と自動化の仕組みが不可欠なのです。

解決策

これらの課題を解決するために、ESLint の a11y プラグインを活用した自動化アプローチをご紹介します。

eslint-plugin-jsx-a11y の導入

eslint-plugin-jsx-a11y は、React/JSX コードのアクセシビリティ問題を自動検出する ESLint プラグインです。Airbnb 社が開発し、現在も活発にメンテナンスされています。

まず、必要なパッケージをインストールしましょう。

javascript// パッケージのインストール
yarn add -D eslint eslint-plugin-jsx-a11y

パッケージインストール後、ESLint 設定ファイルにプラグインを追加します。

json// .eslintrc.json
{
  "extends": ["plugin:jsx-a11y/recommended"],
  "plugins": ["jsx-a11y"],
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    }
  }
}

この設定により、基本的なアクセシビリティルールが有効になり、コーディング時にリアルタイムで問題を検出できるようになります。

基本的な a11y ルール設定

eslint-plugin-jsx-a11y には、用途に応じて選択できる複数の設定プリセットが用意されています。

json// 推奨設定の比較
{
  "extends": [
    // 基本的なルール(初心者向け)
    "plugin:jsx-a11y/recommended",

    // より厳密なルール(上級者向け)
    "plugin:jsx-a11y/strict"
  ]
}

プロジェクトの状況に応じて、段階的にルールを強化していくことをおすすめします。まずは recommended から始めて、チームが慣れてきたら strict に移行する方法が効果的です。

個別ルールのカスタマイズも可能です。

json// カスタムルール設定
{
  "rules": {
    // 画像のalt属性を必須にする
    "jsx-a11y/alt-text": "error",

    // クリッカブル要素でのrole属性チェック
    "jsx-a11y/click-events-have-key-events": "warn",

    // フォーカス可能な要素の管理
    "jsx-a11y/no-autofocus": "error"
  }
}

チーム開発での運用方法

ESLint a11y ルールをチーム開発で効果的に運用するには、以下の仕組みを整備することが重要です。

開発フローにおける a11y チェックの統合を図で確認しましょう。

mermaidflowchart TD
  code[コーディング] -->|リアルタイム| lint[ESLint チェック]
  lint -->|エラー検出| fix[即座に修正]
  fix --> commit[コミット]
  commit --> pr[プルリクエスト]
  pr -->|自動実行| ci[CI/CDチェック]
  ci -->|合格| merge[マージ]
  ci -->|不合格| review[コードレビュー]
  review --> fix

  style code fill:#e1f5fe
  style lint fill:#fff3e0
  style fix fill:#ffebee
  style ci fill:#f3e5f5
  style merge fill:#e8f5e8

この仕組みにより、アクセシビリティ問題を早期発見し、継続的な品質維持が可能になります。

エディタ統合の設定

VS Code を使用している場合、ESLint 拡張機能と組み合わせることで、コーディング中にリアルタイムで a11y エラーを確認できます。

json// .vscode/settings.json
{
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact"
  ],
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  }
}

これにより、ファイル保存時に自動修正が実行され、開発体験が大幅に向上します。

具体例

実際のプロジェクトで ESLint a11y ルールを活用する具体的な方法を、コード例とともにご紹介します。

推奨ルール設定の実装

プロダクション環境で使用できる、実践的な ESLint 設定をご紹介します。

json// .eslintrc.json (完全版)
{
  "extends": [
    "eslint:recommended",
    "@typescript-eslint/recommended",
    "plugin:react/recommended",
    "plugin:jsx-a11y/recommended"
  ],
  "plugins": ["react", "jsx-a11y", "@typescript-eslint"],
  "env": {
    "browser": true,
    "es2021": true,
    "node": true
  },
  "settings": {
    "react": {
      "version": "detect"
    }
  }
}

TypeScript + React プロジェクト向けの包括的な設定です。この設定により、言語仕様からアクセシビリティまで幅広い品質チェックが可能になります。

プロジェクトの段階に応じて、ルールの厳密度を調整することもできます。

json// 段階的なルール導入
{
  "overrides": [
    {
      // 新規ファイルは厳密にチェック
      "files": ["src/components/**/*.tsx"],
      "rules": {
        "jsx-a11y/alt-text": "error",
        "jsx-a11y/aria-props": "error",
        "jsx-a11y/aria-proptypes": "error"
      }
    },
    {
      // レガシーファイルは段階的に対応
      "files": ["src/legacy/**/*.jsx"],
      "rules": {
        "jsx-a11y/alt-text": "warn",
        "jsx-a11y/click-events-have-key-events": "warn"
      }
    }
  ]
}

よくあるアクセシビリティ問題の修正例

実際のコード例を通じて、ESLint a11y ルールがどのように問題を検出し、修正につながるかを見ていきましょう。

1. 画像の alt 属性問題

ESLint が検出するエラーメッセージ:

vbnetimg elements must have an alt prop, either with meaningful text, or an empty string for decorative images. (jsx-a11y/alt-text)

修正前のコード:

typescript// ❌ 問題のあるコード
const ProductImage: React.FC<{ src: string }> = ({
  src,
}) => {
  return <img src={src} />; // alt属性がない
};

修正後のコード:

typescript// ✅ 修正後のコード
const ProductImage: React.FC<{
  src: string;
  productName: string;
}> = ({ src, productName }) => {
  return <img src={src} alt={`${productName}の商品画像`} />;
};

// 装飾的な画像の場合
const DecorativeIcon: React.FC<{ src: string }> = ({
  src,
}) => {
  return <img src={src} alt='' />; // 装飾画像は空文字
};

2. クリッカブル要素のキーボード対応

ESLint が検出するエラーメッセージ:

arduinoVisible, non-interactive elements with click handlers must have at least one keyboard listener. (jsx-a11y/click-events-have-key-events)

修正前のコード:

typescript// ❌ 問題のあるコード
const CustomButton: React.FC<{ onClick: () => void }> = ({
  onClick,
}) => {
  return (
    <div onClick={onClick} className='button-style'>
      クリックしてください
    </div>
  );
};

修正後のコード:

typescript// ✅ 修正後のコード
const CustomButton: React.FC<{ onClick: () => void }> = ({
  onClick,
}) => {
  const handleKeyPress = (event: React.KeyboardEvent) => {
    if (event.key === 'Enter' || event.key === ' ') {
      event.preventDefault();
      onClick();
    }
  };

  return (
    <div
      onClick={onClick}
      onKeyDown={handleKeyPress}
      tabIndex={0}
      role='button'
      className='button-style'
    >
      クリックしてください
    </div>
  );
};

3. フォームラベルの関連付け

ESLint が検出するエラーメッセージ:

cssA form label must be associated with a control. (jsx-a11y/label-has-associated-control)

修正前のコード:

typescript// ❌ 問題のあるコード
const LoginForm: React.FC = () => {
  return (
    <form>
      <label>ユーザー名</label>
      <input type='text' name='username' />

      <label>パスワード</label>
      <input type='password' name='password' />
    </form>
  );
};

修正後のコード:

typescript// ✅ 修正後のコード
const LoginForm: React.FC = () => {
  return (
    <form>
      <label htmlFor='username'>ユーザー名</label>
      <input type='text' id='username' name='username' />

      <label htmlFor='password'>パスワード</label>
      <input
        type='password'
        id='password'
        name='password'
      />
    </form>
  );
};

CI/CD パイプラインでの自動チェック

GitHub Actions を使用した CI/CD パイプラインに ESLint a11y チェックを組み込む方法をご紹介します。

yaml# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  lint:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Node.js のセットアップ
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'yarn'

      - name: 依存関係のインストール
        run: yarn install --frozen-lockfile

      - name: ESLint実行(a11yチェック含む)
        run: yarn lint

      - name: TypeScript型チェック
        run: yarn type-check

さらに詳細な設定として、a11y エラーがある場合に PR をブロックする設定も可能です。

yaml# より厳密なa11yチェック設定
- name: ESLint a11y チェック
  run: |
    yarn eslint --ext .ts,.tsx,.js,.jsx src/ \
      --config .eslintrc.a11y.json \
      --format @microsoft/eslint-formatter-sarif \
      --output-file eslint-results.sarif

- name: SARIF結果のアップロード
  uses: github/codeql-action/upload-sarif@v2
  if: always()
  with:
    sarif_file: eslint-results.sarif

この設定により、GitHub のセキュリティタブで a11y 問題を確認でき、プロジェクト全体の品質管理が強化されます。

図で理解できる要点:

  • ESLint による自動検出により、開発中にリアルタイムで問題を発見できる
  • 手動チェックから自動チェックへの移行で、工数削減と品質向上を同時に実現
  • CI/CD パイプライン統合により、継続的な品質保証が可能

まとめ

ESLint の a11y ルールを活用することで、Web アクセシビリティの向上を効率的かつ継続的に実現できることをご紹介してきました。

a11y ルール活用の効果

ESLint a11y ルールの導入により、以下のような効果が期待できます。

開発効率の向上

  • コーディング時のリアルタイム検出により、早期の問題解決が可能
  • 手動チェック工数の大幅削減(従来比 60-70%減)
  • 自動修正機能による修正作業の効率化

品質の向上と維持

  • 一定品質のアクセシビリティを自動的に保証
  • チームメンバーのスキルレベルに関係なく、基本品質を確保
  • 継続的な CI/CD チェックにより品質劣化を防止

コスト削減効果

  • 後戻り修正コストの削減
  • 専門知識習得にかかる時間短縮
  • 法的リスク対応への準備

継続的な改善のポイント

ESLint a11y ルールを長期間にわたって効果的に運用するために、以下の点を意識することが重要です。

1. 段階的な導入と運用

まずは基本的なルールから始めて、チームの習熟度に応じて段階的に厳密化していきましょう。一度にすべてのルールを有効にすると、開発メンバーの負担が大きくなり、継続が困難になる可能性があります。

2. チーム全体での知識共有

ESLint ルールが検出する問題の背景にある、アクセシビリティの基本概念をチーム全体で共有することが重要です。単純にルールに従うだけでなく、「なぜそのルールが必要なのか」を理解することで、より質の高いコードを書けるようになります。

3. 定期的な設定見直し

プロジェクトの成長や要件変更に応じて、ESLint 設定を定期的に見直すことをおすすめします。新しいルールの追加や、プロジェクトに適さないルールの無効化など、柔軟に設定を調整していきましょう。

最後に、ESLint a11y ルールは万能ではありません。自動検出できない問題もありますので、定期的な手動テストや専門家によるレビューも並行して実施することで、より包括的なアクセシビリティ対応を実現できるでしょう。

Web アクセシビリティの向上は、すべてのユーザーにとってより良い Web 体験を提供するための重要な取り組みです。ESLint a11y ルールを活用して、効率的で継続可能なアクセシビリティ対応を進めていきましょう。

関連リンク