mcpField
S
semantic-html

semantic-html

github.com/schalkneethling開発7346 回インストール27 週間前に更新
リポジトリ

semantic-html について

意味が明確でアクセシブルな HTML を書くためのガイダンススキルです。ページやコンポーネントを構築・レビューする開発者向けに、ネイティブ要素、ランドマーク、見出し構造を重視します。

主な機能

  1. 01ページのランドマークと見出し階層を計画
  2. 02冗長な ARIA よりネイティブ HTML を優先
  3. 03内容に適したセマンティック要素を選択
  4. 04キーボード移動用のスキップリンクを追加
  5. 05フォームと操作要素のアクセシビリティに配慮

活用シーン

  1. 01マークアップの意味とアクセシビリティを確認
  2. 02明確な文書構造のページ領域を構築
  3. 03キーボードで操作できるフォームや要素を作成

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/schalkneethling/webdev-agent-skills --skill semantic-html

インストール後、Claude Code で/semantic-htmlを入力して読み込まれたか確認します。

同梱ファイルreferences/element-decision-trees.mdreferences/heading-patterns.md

詳細

セマンティック HTML

意味を伝え、すべてのユーザーに役立ち、ウェブプラットフォームを尊重する HTML を記述します。

このスキルを使用する場面

次の場合にこのスキルを使用します。

  • 新しいコンポーネントやページセクションを作成するとき
  • アクセシビリティとセマンティクスの観点からマークアップをレビューするとき
  • ネイティブ HTML 要素と ARIA 属性のどちらを使うか判断するとき
  • 適切な見出し階層でドキュメントを構成するとき
  • インタラクティブ要素をアクセシブルにするとき
  • 適切なラベル付けとエラー処理を備えたフォームを作成するとき
  • レスポンシブテーブルを作成するとき

基本原則

コンテンツの現実性

デザイン上のコンテンツは理想化されています。実際のコンテンツは雑多です。常に次の点を考慮してください。

  • 長い文や長い単語
  • アスペクト比やサイズがさまざまな画像
  • 多言語への対応(予定がなくても、ユーザーはブラウザーで翻訳できます)
  • 長さや構造が変化する動的コンテンツ

デザインツール上で見栄えがよいものだけでなく、実際のコンテンツを適切に扱えるコンポーネントを構築してください。

ランドマークを最優先にした計画

個々のコンポーネントに取りかかる前に、ページ全体の構造を検討してください。これにより、次のことが可能になります。

  • 支援技術を使うユーザーにとって重要なランドマークを特定する
  • ドキュメント全体の見出し階層を計画する
  • 要素を適切に選択する
  • ランドマークの使いすぎを避ける(使いすぎると有用性が損なわれます)
ARIA よりネイティブ要素を優先

ARIA の第一のルールに従い、必要なセマンティクスと動作を提供するネイティブ HTML 要素がある場合は、汎用要素に ARIA を追加するのではなく、その要素を使用してください。

要注意: 複雑ではないコンポーネントで、div の数と ARIA の数がともに多い場合、基盤ではなくその場しのぎの修正に頼っている兆候です。

冗長な ARIA

すでに適切なセマンティクスを持つ要素に ARIA を追加するのはノイズです。コードが煩雑になり、支援技術を混乱させる可能性があり、本来の意図が見えにくくなります。


<ul role="list">
  ...
</ul>


<img src="avatar.png" alt="" role="presentation" />


<span aria-label="Most Popular">Most Popular</span>
role でネイティブのセマンティクスを上書きしない

ARIA の role は、支援技術による要素の解釈を変更します。ネイティブ要素のセマンティクスを変更する role を適用すると、一貫性が損なわれます。ネイティブの動作(キーボード操作、状態、イベント)は変わらない一方で、読み上げられる role が変わるためです。


<input type="checkbox" role="switch" />


<input type="checkbox" />

異なるセマンティクスが意図的に必要で、その要素の動作がその role に本当に合致する場合に限り、ネイティブ要素に role 属性を追加してください。

視覚的階層とセマンティック階層の分離

視覚的なスタイルとセマンティックな意味は関連していますが、同一ではありません。CSS クラスがその隔たりを埋めます。

  • ドキュメントの構造に基づいて適切な見出しレベルを使用する
  • 視覚的な外観(サイズ、太さ、色)の調整には CSS クラスを適用する
  • セマンティックレベルにかかわらず一貫した視覚表現にするため、.u-Heading-XXL のようなユーティリティクラスを作成する

ドキュメント構造

ナビゲーションをスキップするリンク

スキップリンクを使うと、キーボードやスクリーンリーダーを利用するユーザーは、繰り返し表示されるナビゲーションブロックを飛ばして、意味のあるコンテンツに直接移動できます。メインコンテンツの前にナビゲーションブロックやその他の繰り返しコンテンツがあるページでは、必ず設置してください。

スキップリンクは<body>内の最初にフォーカス可能な要素として配置します。視覚的には非表示にし、フォーカス時に表示できます。

<body>
  <a href="#main-content" class="skip-link">Skip to main content</a>
  
  <a href="#search" class="skip-link">Skip to search</a>

  <header>...</header>
  <nav>...</nav>

  <main id="main-content" tabindex="-1">...</main>
</body>
.skip-link {
  position: absolute;
  transform: translateY(-100%);
}
.skip-link:focus {
  transform: translateY(0);
}

<main>にtabindex="-1"を指定する理由: <main>要素は標準ではフォーカスできません。tabindex="-1"がない場合、スキップリンクを有効にすると要素までスクロールしますが、すべてのブラウザーでキーボードフォーカスがそこに移るとは限りません。tabindex="-1"を追加すると、通常のタブ順序には追加せずに、プログラムからフォーカス可能(スキップリンクや.focus()で到達可能)にできます。

スキップリンクを追加する場合: ページに目立つ検索バー、サイドバー、または長いセカンダリナビゲーションがある場合は、それらのリンク先へのスキップリンクも検討してください。目的は、主要なコンテンツに到達するまでに必要なTabキーの押下回数を減らすことです。

サイドバーのレイアウトには「ナビゲーションへスキップ」リンクが必要です: サイドバーのナビゲーションがDOMの先頭から離れた位置(たとえば、ソース順で<main>の後や、レイアウトの深い階層)に配置されている場合は、キーボードユーザーがメインコンテンツ全体をタブ移動せずに到達できるよう、<nav>を指すスキップリンクを追加してください。

最初のスキップリンクは<main>を指す必要があります: 最初のスキップリンクは、必ず<main id="main-content">を指すようにしてください。ページの複雑さに応じて、追加のスキップリンクで、その他の意味のあるランドマークやコントロール(<search>要素、サイドバーの<nav>、目立つフォームなど)を指すことができます。

重要な理由: スキップリンクがないと、キーボードユーザーはページを読み込むたびに、すべてのナビゲーション項目をタブ移動する必要があります。リンクが12個あるナビゲーションでは、ページを開くたびにキーを12回余分に押すことになります。

ランドマーク要素

ランドマーク要素を使って、ページ構造を伝えます。

要素使用する場面備考
headerページまたはセクションのヘッダー異なるコンテキストで複数回使用できます
footerページまたはセクションのフッター連絡先情報、著作権表示、関連リンク
navナビゲーションセクションラベルを付ける必要があります。ラベルに「ナビゲーション」を含めないでください(スクリーンリーダーがこれを読み上げます)
main主要なコンテンツ1ページに1つだけ使用でき、主要な<h1>を含める必要があります
aside関連はあるが補足的なコンテンツページの主要な内容を変えずに削除できるコンテンツ(サイドバー、広告など)
search検索機能検索フォームを含み、検索結果は含みません
formユーザー入力aria-labelledbyまたはaria-labelでラベルを付けた場合にのみ、ランドマークになります
article独立したコンテンツ配信されたり、単独で掲載されたりしても意味が通じる内容
sectionテーマごとのグループ化ラベルを付けた場合にのみ、ランドマークになります
<main>には主要な<h1>を含める必要があります

スクリーンリーダーのユーザーは、<main>に直接移動することがよくあります。ページの<h1>が<header>と<main>の間にある<div>内に配置されていると、ユーザーはタイトルの後に移動し、重要な文脈が失われます。<h1>(およびページを紹介するサブタイトルや導入文)は、<main>内に配置してください。


<header>...</header>
<div class="page-header"><h1>FAQ</h1></div>
<main>
  
</main>


<header>...</header>
<main id="main-content" tabindex="-1">
  <h1>FAQ</h1>
  ...
</main>
Section要素

アクセシブルな名前のないsectionは、意味的にはdivと同じように動作します。sectionを使う場合:

  • aria-labelledbyを使って見出しと関連付けます
  • これにより、有効なランドマーク領域になります
  • 意味のあるラベルを付けられない場合は、sectionが適切な選択かどうかを検討してください
article 要素

ブログ記事に限らず考えましょう。単独でも意味が通じる自己完結型のコンテンツには、article を使用します。

  • ブログ記事やニュース記事
  • 投稿へのコメント
  • 一覧に表示する製品カード
  • フィード内のソーシャルメディア投稿
  • フォーラムへの投稿

**判断基準:**このコンテンツを切り出して、周囲の文脈がない別の場所に配置しても意味が通じますか?

address 要素

誤解されることがよくあります。HTML 仕様では、次のように定義されています。

address 要素は、最も近い article または body 要素の祖先要素に関する連絡先情報を表します。

著者や所有者の連絡先情報に使用し、一般的な住所には使用しないでください。住所には、標準的な <p> や、文脈に適した構造化マークアップを使用します。

<aside> と <section> の違い

**<aside> の判断基準:**このコンテンツをページから完全に取り除いても意味が通じますか?メインコンテンツはそのまま成立しますか?

  • 広告、関連記事へのリンク、著者の略歴 → <aside>(取り除いてもメインのメッセージは変わりません)
  • FAQ ページの「まだサポートが必要ですか?」という CTA、記事の主な調査結果の要約、目立つ登録プロンプト → <section>(取り除くとページが不完全に感じられる、または意図した流れが崩れます)

判断に迷った場合は、ページの主な目的に関わるコンテンツは、<aside> ではなく、ラベル付きの <section> に含めます。

aside 要素とプルクオート

<aside> は、記事内のテキストを目立たせるタイポグラフィ上の手法であるプルクオートに適しています。ただし、ページ内のコンテンツから抜き出したプルクオートに <blockquote> を使用しないでください。<blockquote> は、外部からの引用や別個の引用であることを示します。同じ記事の内容を言い換えたプルクオートには、<aside> の中で <p>(またはスタイルを適用したテキスト)を使用します。


<aside aria-label="Pull quote">
  <p>
    "The biggest gains came not from new features, but from removing old ones."
  </p>
</aside>


<blockquote cite="https://example.com/source">
  <p>Quote from an external source.</p>
</blockquote>

見出し

見出しの階層

論理的な見出し構造を維持します。

  • ページごとに h1 を 1 つ使用します(通常はメインタイトルです)
  • 階層を飛ばさないでください(h1 → h3)
  • 見出しはアウトラインを作成します。順に読んだときに意味が通じることを確認してください
コンポーネント内の見出し

見出しを含む再利用可能なコンポーネントでは、次の点に注意してください。

  1. 見出しレベルを設定可能にする — コンポーネントは異なる文脈で使用される場合があります
  2. 適切なデフォルト値を設定する — すべてのコンテンツ作成者が見出しの階層を理解しているとは限りません
  3. 継承を考慮する — 汎用コンポーネントが具体的なものになる場合、見出しの設定も引き継がれるようにします

パターンの例:

Card (generic) → heading level configurable, default h3
  └─ ProductCard (specific) → inherits config, may set default based on known context
       └─ Used in section with h2 → heading level set to h3
セマンティックな見出しではない視覚的な見出し

テキストが見出しのように見えても、意味的には見出しにすべきでない場合があります。CSS クラスを使用して見出しのようなスタイルを適用し、ドキュメントのアウトラインに影響を与えないようにします。

<p class="u-Heading-L">This looks like a heading</p>

リスト

リストを使用する場面

項目数を把握するとユーザーにとって役立つ場合、リストが特に便利です。

  • ナビゲーションメニュー(選択肢はいくつありますか?)
  • 検索結果(一致するものはいくつありますか?)
  • 画像ギャラリー(画像はいくつありますか?)
  • 手順

確認する点:

  • これらの項目は、本当に同列のものですか?
  • 1 つ取り除くと、ほかの項目も不完全に感じられますか?
  • 「N 個の項目があります」ということが暗に伝わっていますか?
リストの種類
種類使用する場面例
ul項目数に意味がある順不同の集合ナビゲーション項目、検索結果
ol順序のある手順や順位付きの項目レシピ、説明書、トップ 10 リスト
dl用語と説明の組み合わせ用語集、メタデータ、キーと値の組み合わせ
menuツールバーのコマンドアクションボタン。ナビゲーションには使用しません

**順序付きリストの属性:**カウントダウン形式のリスト(例:トップ 10 を 10 から 1 の順に表示する場合)には reversed を使用します。特定の値から番号を開始するには start を使用します。どちらも HTML に標準で用意されているため、JavaScript は不要です。

定義リスト

見落とされたり、details/summaryと混同されたりすることがよくあります。次の用途にはdlを使用します。

  • 用語集の定義
  • メタデータの表示(ラベルと値のペア)
  • 1つ以上の説明を持つあらゆる用語

注:1つのdtに複数の関連する説明を付けるため、複数のdd要素を使用できます。

装飾的なリストの区切り

CSSの::beforeまたは::afterを使って視覚的な区切り(パンくずリストの›など)を挿入する場合、ブラウザーは生成されたコンテンツをアクセシビリティツリーから自動的に除外します。追加のマークアップは不要です。CSSプロパティとしてaria-hidden: "true"を使って隠そうとしないでください。これは無効で、効果もありません。CSSではなくHTMLで区切りを挿入する場合は、HTML要素に<span aria-hidden="true">を使用します。

インタラクティブ要素

ボタンとリンク

従来のルール: ボタンは操作を実行し、リンクは別の場所に移動します。

プログレッシブエンハンスメントの観点: JavaScriptが失敗した場合でもURLが意味のあるフォールバックを提供するなら、操作のようなインタラクションであってもリンクが適切です。

インタラクションデフォルトの選択リンクを検討する場合
コンテンツをさらに表示buttonURLパラメーターを使ってサーバー側でコンテンツを読み込める
表示を切り替える(グリッド/リスト)buttonURLで表示設定を保持できる
クリップボードにコピーbuttonコピーするコンテンツが共有可能なURLである
タブを選択するbuttonURLで特定のタブのコンテンツを読み込める

重要な問い: JavaScriptが失敗した場合、どうなりますか?URLによって適切な段階的機能低下が実現されるなら、リンクの方が適切な場合があります。

繰り返し使われるボタンに一意のアクセシブル名を付ける

同じ操作がページ内に複数回登場する場合(各商品カードの「カートに追加」や各記事の「続きを読む」など)、スクリーンリーダーの利用者がどの項目に対する操作なのかを理解できるよう、各ボタンに一意のアクセシブル名が必要です。

方法(最もシンプルなものを選びます):


<button aria-label="Add Nike Pegasus 41 to cart">Add to cart</button>


<button>
  Add to cart
  <span class="visually-hidden">Nike Pegasus 41</span>
</button>


<article>
  <h3 id="product-42">Nike Pegasus 41</h3>
  ...
  <button aria-describedby="product-42">Add to cart</button>
</article>

表示ラベルは「カートに追加」のままにします(視覚のある利用者は位置から文脈を理解できます)。アクセシブル名には商品名を加え、ボタン一覧から移動する利用者に情報を伝えます。

コントロールを無効にする

aria-disabled="true"は無効状態を伝えますが、インタラクションを防止するわけではありません。ボタンでは、disabledを使うと状態を伝えると同時に、クリックやキーボードによる有効化も抑止できます。リンクでは、aria-disabled="true"だけでは不十分です。フォーカスを受け取り、アクティブ化もできます。以下の方法があります。

  • 操作が本当に利用できない場合は、リンクではなく<button disabled>を使用する
  • アクティブ化を防ぐため、href属性を削除する(リンクがインタラクティブでなくなります)
  • 要素にフォーカスを当てられる状態を維持する必要がある場合は、keydown/clickイベントを明示的に処理する
軽量なオーバーレイにはPopover APIを使用する

ユーザーのドロップダウン、操作メニュー、モーダルでないオーバーレイには、カスタムのARIAウィジェットパターンではなく、Popover API(popover属性)を使うのが最新の推奨方法です。


<button popovertarget="user-menu">
  <img src="avatar.png" alt="" />
  <span>Alice</span>
</button>


<ul id="user-menu" popover>
  <li><a href="/profile">Profile</a></li>
  <li><a href="/settings">Settings</a></li>
  <li><button>Sign out</button></li>
</ul>

ブラウザーは、呼び出し元のボタンのaria-expandedと、ポップオーバーがDOM上で直後に隣接していない場合のaria-detailsを自動的に処理します。トリガーに手動でARIA属性を付ける必要はありません。

ARIAメニューパターンより優れている理由:

  • キーボード操作、フォーカス管理、外側のクリックによる閉じる動作をブラウザーがネイティブに処理します
  • role="menu"、role="menuitem"、role="none"は不要です。リストはリンクとボタンを含む意味的な<ul>のまま維持されます
  • ARIAメニューパターンには厳格な操作要件(Home、End、文字によるナビゲーション)があり、実装を誤りやすく、多くの利用者にもなじみがありません

ARIAメニューパターンが適切な場合: デスクトップアプリケーションの動作を模した、真のアプリケーションメニュー(メニューバー、メニュー項目、サブメニュー)を構築する場合に限られます。ほとんどのウェブサイトのナビゲーションやユーザードロップダウンには、Popover APIまたはシンプルな開示パターンを使用してください。

Details/Summary パターン

段階的な情報開示に使用します。

  • FAQ セクション
  • 展開可能なコンテンツセクション
  • 折りたたみ可能なナビゲーション

ARIA ロール(例:role="menu"、role="dialog")が必要な場合に、<button>で制御する情報開示ウィジェットの代わりとして使用しないでください。ユーザーのドロップダウン、メニュー、モーダルのトリガーには、適切な ARIA パターンを適用できるように<button>が必要です。<details>/<summary>には独自の暗黙的なセマンティクスがあり、aria-expandedやメニューのロールを適切に設定することはできません。

フォーム

Fieldset/Legend によるグループ化

レイアウトではなく、テーマごとのグループ化にfieldsetとlegendを使用します。

  • 住所の入力欄
  • 個人情報のセクション
  • プライバシー/同意のチェックボックス
  • 支払い情報
  • 設定のセクション(プロフィール、通知、プライバシー)

**セクションと見出しだけでは不十分な場合:**フォームコントロールのグループには、<fieldset>/<legend>を使うと、<section>/<h2>では提供できないグループの文脈を支援技術に伝えられます。スクリーンリーダーはグループ内の各フィールドの前に凡例を読み上げるため、ユーザーは一貫した文脈を把握できます。フォーム以外のコンテンツ領域には<section>/<h2>を使用し、入力欄のグループを含む領域には常に<fieldset>/<legend>を使用します。

メリット:

  • 段階的な情報開示が可能になります(ユーザーがほかの項目を完了するとセクションを表示できます)
  • 圧倒されるのを防ぎます(「フォーム項目の壁」を避けられます)
  • スクリーンリーダーのユーザーに文脈を提供します

アクセシブルな名前を提供したまま、凡例を視覚的に非表示にできます。

検索コントロールとフィルターコントロールのグループ化

<search>はテキスト入力だけでなく、検索/フィルターインターフェイス全体を囲みます。ツールバーに検索入力と関連するフィルターの選択欄がある場合、それらは1つの<search>またはラベル付きの<form>にまとめます。


<search aria-label="Filter employees">
  <label for="q">Search</label>
  <input type="search" id="q" name="q" />

  <label for="dept">Department</label>
  <select id="dept" name="dept">
    ...
  </select>

  <label for="status">Status</label>
  <select id="status" name="status">
    ...
  </select>

  <button type="submit">Apply filters</button>
</search>


<search>
  <input type="search" />
</search>
<select>
  ...
</select>

ラベル

**必ずlabel要素を使用してください。**例外はありません。

  • デザイン上必要な場合は、視覚的に非表示のラベルを使用できます
  • プレースホルダーテキストをラベルの代わりに使用しないでください
  • 適切なlabel要素を使用できる場合は、aria-labelを使用しないでください

プレースホルダーでは不十分な理由:

  • 入力すると消えてしまいます(認知上の困難、ストレス、注意散漫がある場合に問題となります)
  • コントラストが不十分なことがよくあります
  • 入力欄を継続的に識別する情報を提供しません
必須項目

HTML のrequired属性は、必須状態を支援技術に伝えますが、視覚に障害のないユーザーにも視覚的な表記が必要です。requiredには必ず視認できる表示を併用してください。


<fieldset>
  <legend>
    Contact details <span aria-hidden="true">*</span> required fields
  </legend>

  <label for="name">Full name <span aria-hidden="true">*</span></label>
  <input type="text" id="name" required />
</fieldset>

アスタリスクのaria-hiddenは、スクリーンリーダーが「アスタリスク」と読み上げるのを防ぎます。必須状態はすでにrequired属性から伝わるためです。凡例またはページレベルの注記で、視覚に障害のないユーザーに表記方法を説明します。

ヒントテキスト

入力欄に形式のヒントや補助テキストがある場合は、aria-describedbyを使って入力欄に関連付けます。これにより、スクリーンリーダーはラベルの後にヒントを読み上げるため、ユーザーは入力を始める前に必要な文脈を把握できます。

<label for="email">Email address</label>
<p id="email-hint" class="hint">We'll only use this to send your receipt.</p>
<input type="email" id="email" aria-describedby="email-hint" />

複数の関連付けが可能です。カンマ区切りの ID を使って、ヒントとエラーの両方を関連付けられます。

<input
  type="email"
  id="email"
  aria-invalid="true"
  aria-describedby="email-hint email-error"
/>
エラーメッセージ

現在のベストプラクティス(aria-errormessageのブラウザーサポートに不足があるため):

  1. 無効な入力欄にaria-invalid="true"を設定します
  2. aria-describedbyを使ってエラーメッセージを関連付けます
  3. エラーメッセージを実行可能な内容にします(問題を示すとともに、修正方法を案内します)
  4. 動的なエラー(フォーカスが外れたときに表示するもの)では、エラーコンテナーへのaria-liveの使用を検討します
<label for="email">Email</label>
<input
  type="email"
  id="email"
  aria-invalid="true"
  aria-describedby="email-error"
/>
<p id="email-error" class="error">
  Enter a valid email address, like [email protected]
</p>

テーブル

テーブルを使用する場合

データに縦横両方の軸で意味のある関係がある場合は、テーブルを使用します。

  • データを行と列の両方で提示する必要がある
  • 見出しとデータが明確に対応している
  • すべての行に同じ列がある
  • 各列のデータが同じ種類である
テーブルを使用しない場合
  • 単純なリスト(1つの軸)
  • キーと値のペア(dlを使用)
  • フォームのレイアウト
  • 階層データ(入れ子のリストを使用)
テーブルのセマンティクスの基本

必ず以下を含めます。

  • caption — テーブルの目的を説明します
  • thead、tbody、tfoot — 構造的にグループ化します
  • scopeを指定したth — 見出しセルとその方向を示します
レスポンシブテーブル

優先順位順:

  1. 必須でない列を非表示にする — ユーザーは主な要点を確認でき、ボタンでテーブル全体を表示できます
  2. 横スクロール — セマンティクスを維持できますが、運動機能に困難のあるユーザーには使いにくい場合があります
  3. コンポーネントの重複(モバイルではカード) — 最終手段です。どちらのバージョンでもアクセシビリティを維持してください

注:Safari を含む最新のブラウザーでは、display: grid や display: flex を適用してもテーブルのセマンティクスは失われなくなり、レスポンシブ対応の新たな可能性が広がっています。

コードレビューのチェックリスト

マークアップをレビューする際は、次の点を確認してください。

良い兆候
  • スキップナビゲーションリンクが、最初にフォーカス可能な要素として配置されている
  • ランドマーク要素が適切に使用されている
  • 見出しの階層が論理的である
  • ネイティブのインタラクティブ要素(ボタン、リンク)が正しく使用されている
  • 繰り返し表示されるアクションボタンに、それぞれ固有のアクセシブルな名前が付いている
  • フォームに適切なラベル、フィールドセット、ヒントとの関連付けがある
  • 必須フィールドが視覚的に示され、その表記規則を説明する凡例がある
  • テーブルがセマンティクスに沿った完全な構造になっている
  • ARIA が必要最小限に、かつ正しく使用されている
警告すべき兆候
  • <nav> または繰り返し表示されるヘッダーコンテンツの前に、スキップナビゲーションリンクがない
  • 複雑でないコンポーネントに <div> が多用されている
  • ネイティブのセマンティクスが欠けていることを補うために ARIA 属性が使われている
  • ネイティブ要素に冗長な ARIA ロールが指定されている(<ul> の role="list"、<img alt=""> の role="presentation")
  • role 属性によってネイティブ要素のセマンティクスが変更されているのに、動作がそれに対応していない
  • aria-label が表示テキストと重複している(支援技術で二重に読み上げられたり、わかりにくく表示されたりする)
  • 単純なユーザードロップダウンに ARIA メニューのパターン(role="menu"、role="menuitem")が使われている(代わりに Popover API を使用してください)
  • プレースホルダーがラベルとして使われている
  • 見出しレベルが構造ではなく見た目のサイズを基準に選ばれている
  • ボタンやリンクの代わりに、クリックハンドラー付きの汎用要素が使われている
  • レイアウトにテーブルが使われている
  • フォームラベルがない
  • 繰り返し表示されるボタンに同じアクセシブルな名前が付いている(「カートに追加」× 6)
  • <a> 要素のキーボード操作を防止せずに aria-disabled が指定されている
  • フィルター/検索コントロールが、<search> または <form> によるグループ化の外に散在している
  • 設定フォームのセクションに <fieldset>/<legend> ではなく <section>/<h2> が使われている

リソース

参考資料

特定のトピックに関する詳細なガイダンスは、references/ ディレクトリを参照してください。

  • element-decision-trees.md — 要素選択のための簡易判断フレームワーク
  • heading-patterns.md — コンポーネントの見出しパターンと設定方針

コメント