見出しにまつわるエトセトラ
記事の背景
HTML 要素の中でももっとも基本的かつ最重要と言える見出し要素。社内でもそのセマンティクスや適切な内容について議論されることが少なくないのですが、ふと振り返ってみるとつまみ食いのような Tips の積み重ねばかりで体系的な理解を怠っていたな…という反省があります。自分自身の理解やチームへの説明のため、改めてしっかり見出しについてまとめておきたいと考えて本記事を作成しました。
公開時点で書いていないこと
スクリーンリーダーでの動作
スクリーンリーダーの使用時に見出しがどのように機能するのかについては後日追記する予定です。
見出し要素の HTML 仕様
まずは HTML の仕様を確認してみます。
4.3.6 h1、h2、h3、h4、h5、h6要素によれば、見出し要素を使用できるコンテキストは以下の2つとされています。
- hgroup 要素の子として
- ヘディングコンテンツが期待される場所
ヘディングコンテンツは、あるセクションが明示的に <section>
などのセクショニングコンテンツ要素を使用してマークアップされているか否かに関わらず、そのセクションの見出しを定義するものです(3.2.5.2.4 ヘディングコンテンツを参照)。
見出しとアウトライン
4.3.11 見出しとアウトラインでは見出し要素の具体的な仕様が定義されています。
- 見出し要素はその数字に対応した見出しレベルを持つ
- 見出しレベルが低いほど、その見出しが持つ祖先セクションの数が少なくなる
- アウトラインとは、文書内のすべての見出しをツリー順に並べたものである
- 文書に1つ以上の見出しがある場合、アウトライン内の少なくとも1つの見出しの見出しレベルは1(
<h1>
)でなければならない - アウトライン内の別の見出しリードに続く各見出しは、リードの見出しレベルよりも小さい、等しい、または1つ大きい見出しレベルを持たなければならない
以下は見出しレベルがスキップされているため、仕様に違反してます。
<body>
<h1>Apples</h1>
<p>Apples are fruit.</p>
<section>
<h3>Taste</h3>
<p>They taste lovely.</p>
</section>
</body>
1つ大きい見出しレベルを使用して以下のように修正することで仕様に適合したものになります。
<body>
<h1>Apples</h1>
<p>Apples are fruit.</p>
<section>
<h2>Taste</h2>
<p>They taste lovely.</p>
</section>
</body>
見出しとアクセシビリティ
Heading off confusion: When do headings fail WCAG? - TPGi を参考にしながら WCAG 達成基準の失敗と成功という観点で見出しのアクセシビリティを考えてみます。
見出しに関連する WCAG 達成基準
WCAG の中で見出しに関連する達成基準は以下で、A ~ AAA の各レベルで見出しに言及していることが分かります。
1.3.1 情報及び関係性: 何らかの形で提示されている情報、構造、及び関係性は、プログラムによる解釈が可能である、又はテキストで提供されている。(レベル A)
セマンティックなマークアップと適切な構造化によるマシンリーダビリティやテキストの提供を求める達成基準です。ここではセマンティクスが求められており、すべての画面やページに見出しが必要であるとまでは述べられていません。
2.4.1 ブロックスキップ: 複数のウェブページ上で繰り返されているコンテンツのブロックをスキップするメカニズムが利用できる。(レベル A)
見出しそのものを求めるものではありませんが、何らかの障害のあるユーザーがウェブページのメインコンテンツへ素早くかつ容易に到達できるようにすることを意図した達成基準であり、見出しがその役割を果たすことは明らかです。実際、「十分な達成方法」のひとつとして「H69: コンテンツの各セクションの開始位置に見出し要素を提供する」が紹介されています。
2.4.6 見出し及びラベル: 見出し及びラベルは、主題又は目的を説明している。(レベル AA)
見出しの内容に関するもので、前の2つと同様、見出しそのものを求めるものではありません。
2.4.10 セクション見出し: セクション見出しを用いて、コンテンツが整理されている。(レベル AAA)
ここで初めて見出しの存在を求められます。
この達成基準が AAA となっている理由として、あらゆる種類のコンテンツに見出しを挿入することが常に可能であるとは限らないため、とされています。例えばウェブコンテンツであっても、ユーザー生成型のコンテンツや、管轄外の CMS から供給されるコンテンツなどは後から任意の見出しを入れることは困難であるため、達成の難易度は非常に高いと言えます。
WCAG で失敗とみなされない例
次に、WCAG の観点で失敗とみなされない例を見てみます。
見出しの欠如
上記で確認した通り、見出しの欠如自体は失敗とみなされません。とはいえ見出しの重要性は明らかであり、例えばコンテンツの制作者と提供者が一致する(= 見出しの有無をコントロールできる)ウェブコンテンツに適用範囲を限定するなどして独自の達成基準とする、という対応は可能ではないかと思います。
<h1>
の欠如
画面やページに <h1>
が存在しないこと自体が失敗とみなされることはなさそうです。しかし一般論として、ページのタイトルと一致したり、主題を適切に表現するような <h1>
が提供されることが望ましいことに変わりはありません。
<h1>
が存在すること
複数の 逆もまた然りで、複数の <h1>
の存在が失敗とみなされるとは言及されていません。
HTML の仕様上でも禁止はされていませんが、MDN には「1つのページに複数の <h1>
要素を使用しない」として以下のように述べられています。
1 つのページに複数の
<h1>
要素を使用することは HTML 標準では認められていますが(入れ子でない限り)、これはよい習慣とはみなされません。1 つのページには、ページの内容を説明する 1 つの<h1>
要素(文書の<title>
要素と同様)を置くのが一般的です。
また補足として以下のようにも述べられています。
メモ: 入れ子になったコンテンツ区分要素の中で複数の <h1> 要素を入れ子にすることは、HTML 標準の古いバージョンでは認められていました。しかし、これはよい習慣とはみなされず、現在は非適合となっています。詳しくは、There Is No Document Outline Algorithm をご覧ください。
アウトラインアルゴリズムの導入が検討されていた時代は複数の <h1>
を運用することが認められていたものの、結局アルゴリズム自体が仕様からドロップしたため、その点からも現在は推奨されないものであることが付記されています。アウトラインアルゴリズムの刷新に関する一連の動きはHTML のアウトラインアルゴリズムが見出しレベルをベースとしたものに刷新されそう | 富永日記帳に詳しいです。
一般論として文書内の <h1> 要素は一つにとどめた方が良いでしょう。
という記述のとおり、よほど特殊な事情がなければページ内の <h1>
は1つであるべきでしょう。理想的には <main>
要素の内容を表す最初の子孫要素であることが望ましいと言えます。
見出しレベルのスキップ
こちらも WCAG の中では明確な失敗とはみなされませんが、1.3.1 情報及び関係性 や 2.4.1 ブロックスキップ、2.4.10 セクション見出し の達成方法として「G141: 見出しを用いてウェブページを構造化する」や「H42: 見出しを特定するために、h1 要素~ h6 要素を使用する」、「H69: コンテンツの各セクションの開始位置に見出し要素を提供する」といったものが紹介されています。特に G141 の中では以下のように述べられています。
文書の全体的構造のナビゲーション及び理解を助けるには、コンテンツ制作者は適切に入れ子にした見出しを使用すべきである (たとえば h1 には h2 が続き、h2 には h2 か h3 が続き、h3 には h3 または h4 が続き……といったように)。
また MDN の見出し要素のページには以下のような記述があります。
スクリーンリーダーの利用者のよくあるナビゲーションテクニックとして、ページの内容を手早く特定するために、見出しから見出しへとジャンプすることがあります。このため、見出しレベルを飛ばさないようにすることが重要です。見出しレベルを飛ばしてしまうと、このようにナビゲーションしている人が、見つからない見出しがどこにあるのかわからなくなり混乱してしまいます。
HTML の仕様の観点では、「見出しとアウトライン」で確認した通り見出しレベルのスキップは不適合とみなされます。
総合的に考えて、意図的であれ不注意であれ、やはり見出しレベルはスキップすべきでないと結論付けることができるでしょう。HeadingsMap や HTML5 Outliner などの拡張機能を利用して見出しレベルとアウトラインをチェックする習慣を身に付けたいところです。
同じテキストの複数の見出し
一見すると「2.4.6 見出し及びラベル」の失敗例となりそうですが、これは文脈に依存します。
例えば以下のように、同階層に同じテキストの複数の見出しが存在する場合は明らかに混乱を招くため失敗とみなすのが適切でしょう。
<body>
<h1>フルーツ</h1>
<p>リンゴはフルーツ</p>
<h1>フルーツ</h1>
<p>レモンはフルーツ</p>
<h1>オレンジ</h1>
<p>オレンジはフルーツ</p>
</body>
一方で、以下のように分割された各セクションに同じサブ見出しが存在するようなシチュエーションは比較的一般的です。
<body>
<h1>フルーツ</h1>
<section>
<h2>リンゴ</h2>
<h3>このフルーツについて</h3>
</section>
<section>
<h2>レモン</h2>
<h3>このフルーツについて</h3>
</section>
<section>
<h2>オレンジ</h2>
<h3>このフルーツについて</h3>
</section>
</body>
このことから、同じテキストを持つ複数の見出しが失敗となるかどうかは文脈や構造に依存するということが言えます。
WCAG で失敗とみなされる例
それでは逆に失敗とみなされる例とはどのようなものでしょうか。
見出しとしてマークアップされていない見出しのようなテキスト
あるテキストが見出しを意図されながら見出し要素を用いてマークアップされていない場合、「プログラムによる解釈」が不可能となることから 1.3.1」の失敗とみなすことができます。
「達成基準 1.3.1 の失敗例 - 情報を伝えるために、適切なマークアップ又はテキストを用いずに、テキストの提示の変化を使用している」では、具体的な失敗例として以下が挙げられています。
- CSS を用いて p 要素を見出しのような見た目にする
- 見出しとして用いられる文字画像で、その画像が見出しタグでマークアップされていない
- 単語やフレーズを強調するために CSS を用いて見た目を制御しているが、その強調のセマンティックを表すマークアップが行われていない場合
非論理的な見出し順
例えば、直前の見出しが <h3>
であるにもかかわらず、その次に来る見出しが <h2>
であるようなケースを「非論理的な見出し順」と言うことができ、1.3.1」 の失敗とみなされます。「達成基準 1.3.1 の失敗例 - コンテンツにおける関係を表さない方法で、構造的なマークアップを使用している」では「プレゼンテーション上の効果を目的とした見出し要素の使用」という例が示されています。
<h1>Study on the Use of Heading Elements in Web Pages</h1>
<h3>Joe Jones and Mary Smith<h3>
<h4>March 14, 2006</h4>
<h2>Abstract</h2>
<p>A study was conducted in early 2006 ...
</p>
これはあくまで順序についての失敗例であり、見出しレベルをスキップできないということを意味するものではありません。
説明的でない見出し
「達成基準 2.4.6: 見出し及びラベルを理解する」では見出しの内容について言及されており、「見出しが明快かつ内容が分かるように記述」することを要求しています。
以下の例では、それぞれのセクションを説明するのに十分な見出しが提供されているとは言えないため失敗とみなすことができます。
<h2>レシピ</h2>
<p>完璧なリゾットを作るには…が不可欠です。</p>
<h2>レシピ</h2>
<p>コック・オ・ヴァンはフランスの伝統的な煮込み料理です。</p>
何が「説明的」か、という点について絶対的な基準は存在しないものの、その見出しを見たときに関連するセクションの内容が把握できるか?という観点でチェックできるとよいかもしれません。
見出しと WAI-ARIA
WAI-ARIA では heading
ロールが定義されており、aria-level
属性とともに用いることで任意の要素が見出しとして扱われるべきであることをスクリーンリーダー等の支援技術に伝えます。また、heading
ロールにはアクセシブルな名前が必須となっています。<h1>
~ <h6>
の見出し要素には暗黙の ARIA セマンティクスとして role=heading
と、見出しレベルの数字に対応した aira-level
が付与されます。
参考:
- heading ロール | Accessible Rich Internet Applications (WAI-ARIA) 1.3
- aria-level | Accessible Rich Internet Applications (WAI-ARIA) 1.3
- h1 - h6 | ARIA in HTML
aria-level
の仕様を確認すると、この属性に設定できる値は 1 以上の任意の整数であるとされていますが、現時点では 1~9 の範囲のみをサポートするユーザーエージェントと支援技術の組み合わせがほとんどであるという状況のようです。また、heading
ロールを持つ要素が 6 を超える aria-level
を持つとユーザーに問題が発生する可能性があることが付記されています。
ARIA: heading ロール | MDN でにおいても「アクセシビリティに関する懸念」として以下のように述べられています。
見出し (
heading
) ロールとaria-level
属性を使用する必要がある場合は、HTML との整合性を保つために、レベル 6 を超えないようにしてください。 理論的にはもっと大きくすることができ、一部のスクリーンリーダーはそれをサポートしているかもしれませんが、他のブラウザーとスクリーンリーダーの組み合わせでは結果が予測できない場合があります。
見出しと WAI-ARIA に関する達成方法としては「ARIA12: 見出しを特定するために role=heading を使用する」があり、その中では「可能な場合、ネイティブな見出しマークアップを直接使用すること」と述べられています。
仕様上は <div role="heading" aria-level="7">
のような 7 以上の aria-level
を設定することは可能であるものの、原則として 9 以下を使用すること、さらに言えば基本的に <h1>
~ <h6>
要素を使用することが望ましい言えるでしょう。
見出しの検証を考える
ここまで見てきた HTML の仕様と WCAG の観点から、検証すべき項目を考えてみます。
ここでは一から検討するのではなく、すでに網羅的な視点でチェック内容が整理されたfreeeアクセシビリティー・ガイドライン(Ver. 202403.0-RELEASE+4.3.7)をもとに、各項目の着眼点を確認していきます。
freeeアクセシビリティー・ガイドラインにおける見出しのチェック項目
freeeアクセシビリティー・ガイドラインでは「ページ全体」に対するガイドラインとして「適切なセクション分けと見出しの付与」という節が設けられており、見出しに関するおもなチェック項目が列挙されています。
これらのチェック内容の意図が「視覚障害者が、ページ内で目的のコンテンツを見つけやすくする」とされていることに注目しましょう。つまり、単に仕様や WCAG の達成基準を満たす、という観点のものではなく、ユーザー、中でも視覚障害者の実際的な便益を考慮したものになっているということです。
意図
視覚障害者が、ページ内で目的のコンテンツを見つけやすくする。
・多くのスクリーン・リーダーは、見出し間で移動する機能、見出しのリストを表示する機能がある。
・適切な見出しが付けられていれば、見出しを追うことで斜め読みのような読み方ができる。
内容を箇条書きで抜き出すと以下の通りです。
- 見出しとして表現されるべきものが、設計資料で明示されている
- 見出しには適切な見出しレベルが指定されている
- ページ内の機能や内容の区切り、本文の先頭部分などに適切に見出しが配置されている
- 複数の種類の情報を含む画面においては、情報の区切りに見出しが配置されている
- 見出しが、設計資料に従って適切に実装されている
- 見出しは、設計資料で示されている見出しレベルの見出しとしてスクリーン・リーダーに認識されている
1つずつみていきましょう。
見出しとして表現されるべきものが、設計資料で明示されている
デザインカンプや設計書等で見出しとして表現されるべき要素が明示されていることを確認する項目かと思います。
弊社の場合、デザインレベルで見出しをはじめとしたセマンティクスの定義が提供される状態にはなっていないため、まずはここから始める必要がありそうです。
見出しには適切な見出しレベルが指定されている
HTML Living Standard 4.3.11 見出しとアウトラインの仕様に則った実装がなされているかを確認する項目かと思います。以下の項目がチェックされます。
- 文書の階層構造を反映した見出しレベルが指定されている
- ページ全体では、見出しレベルは1から始まっている
- 見出しレベルは、1の下位は2、2の下位は3のように1ずつ増加していて、抜けがない状態になっている
ページ内の機能や内容の区切り、本文の先頭部分などに適切に見出しが配置されている
達成基準 2.4.10 に則り、セクション見出しによってコンテンツが整理されていることを確認する項目かと思います。
達成基準そのもののレベルとしては AAA ですが、スクリーンリーダーユーザー向けの便益を重視していることから優先度の高いチェック内容とされていると考えられます。
複数の種類の情報を含む画面においては、情報の区切りに見出しが配置されている
こちらも達成基準 2.4.10](https://waic.jp/translations/WCAG22/#section-headings) に則った項目かと思われます。基本的には前項と併せてチェックされるものと考えてよいのではないでしょうか。
見出しが、設計資料に従って適切に実装されている
セマンティクスが定義された設計資料の存在を前提としており、当該資料との整合性をチェックする項目かと思われます。
見出しは、設計資料で示されている見出しレベルの見出しとしてスクリーン・リーダーに認識されている
こちらも設計資料の存在を前提としており、特にスクリーンリーダーで意図通りに動作するかがチェックされます。
まとめ:チェック内容はエンドユーザー、特に視覚障害者の実際的な便益を十分考慮すること
以上、freeeアクセシビリティー・ガイドラインをもとにチェック内容を確認してきました。
全体として「アウトラインがどうなっているか」「仕様に則っているか」という形式的なことよりも、それを使用するユーザー、特にスクリーンリーダーを使う視覚障害者の便益が十分に満たされているかどうかという観点での内容になっていることが伺えます。これは当然のことと言うこともできますが、スクリーンリーダーユーザーが身近にいない、または利用が想定しづらい制作環境ではつい仕様を満たすことに意識が偏りがちであるということもまた事実です。
これらのチェック内容を生かすために、以下のステップを踏みチェック体制を構築することが必要となりそうです。
- デザイナーや他の開発者と協力して、設計資料で見出しを定義する
- 設計資料内の見出しの定義について、関係者間で合意する
- スクリーンリーダーによる検証を行いながら開発を進める
- QA と協力して、スクリーンリーダーによる検証を行ってもらえるようにする
エンドユーザーのユースケースに沿った開発と検証を行うという点は通常のプロダクト開発プロセスと何ら変わらない、ということが確認できました。
トピック
ここからは個別のトピックについて考えていきます。
<h1>
にサイトロゴやブランドロゴを入れるのは適切か?
<h1>
にサイトロゴやブランドロゴを入れることを明確に禁止する仕様や言説は見当たりませんが、見出しによって文書のアウトライン(≒ 目次)が形成される、という観点に立つならば、一般論として <h1>
はその文書のタイトルであるべきであると言えるでしょう。
古い記事ですが、Should Your <h1> Tag Be Your Logo?の「見出しは実際に何をするのか?」というセクションでは「サイトの最初の見出しは、あなたのページの内容を最もよく説明するものであるべきです。これがロゴになることもありますが、ほとんどの場合はそうではありません。」として、ロゴを <h1>
にすべきでない具体的な理由を「ユーザビリティ」「アクセシビリティ」「ロボット対策」の3つの側面から述べています。
1. ユーザビリティ
見出し要素は情報を整理し、ユーザーを適切にナビゲートするため使われるべきです。ロゴは実際には情報やナビゲーションではなく、サイトに関するメタデータであり、ページの内容に関する関連情報ではありません。
2. アクセシビリティ
ロゴのような「インチキ」な見出しをつけることは、スクリーンリーダーを使うユーザーにとって、すべてのページで余分なテキストを聞かなければならないことを意味します。
3. ロボット対策
クローラーは様々な理由でウェブサイトをスキャンします。偽の <h1>
を追加することでページの構造とコンテンツについて彼らを混乱させ、コンテンツを誤って表示したり、他のアグリゲーターで誤って分類したりする可能性があります。
上記は「なぜ見出しを正しく用いることが重要なのか」という疑問の回答にもなっています。これらを考慮すると、ロゴを <h1>
にするメリットは存在しないどころか、様々な点でデメリットとなり得る場面の方が多いと結論づけることができそうです。
具体的な例として、amazon.co.jp では商品名が <h1>
になっています。
また、ameba ブログでは記事タイトルが <h1>
で、左上のサービスロゴは <div>
でマークアップされています。
<section>
に見出しは必須か?
必須ではありませんが、慣習として見出しとセットで使用されることが一般的であると言えます。 また、文書のアウトラインを形成するのはあくまで見出し要素自体であり、 <section>
と見出し要素をセットで使用することによって何らかの機能が発生するわけではありません。
<section>
がアクセシブルな名前を持つ場合は role=region(ランドマーク) に、そうでない場合は role=generic となります。
<section>
が見出しを持つ場合、その見出し要素がアクセシブルな名前として利用されることが一般的です。<section>
にアクセシブルな名前を与える方法は優先順位の高い順に以下のとおりです。
aria-labelledby
aria-label
title
ただし title
は macOS Safari 等で意図しない動作をすることがあるため推奨されていません。
参考:Accessibility of the section element | scottohara.me
以下は aria-labelledby
を使用して<section>
にアクセシブルな名前を与える例です。
<body>
<main>
<h1>Apples</h1>
<p>Apples are fruit.</p>
<!-- この section は role=region になる -->
<section aria-labelledby="section-heading">
<h2 id="section-heading">Taste</h2>
<p>They taste lovely.</p>
</section>
</main>
</body>
以上のことから、以下の通り認識しておけば良さそうです。
- 必ずしも
<section>
と見出し要素をセットで使う必要はない - アウトラインを形成するのは見出し要素。アウトラインだけが必要なのであれば
<section>
にアクセシブルな名前は必要ない -
<section>
をランドマークとして公開したいのであればアクセシブルな名前を与えること -
<section>
のアクセシブルな名前は、そのセクションに内包される見出し要素であることが一般的である
まとめ
見出し要素について HTML の仕様を確認することから始まり、WCAG 達成基準の観点から適切な見出しについて考えてきました。仕様の確認だけでは解消できなかった疑問はトピックとして個別に扱い、個人的には対外的な説明に足る資料として一定の水準にまとめられたのではないかと思っています。
本記事で言及されていない仕様や検討されていないトピック、また記載内容の不備にお気付きの場合、遠慮なくコメントや編集リクエストを頂けますと幸いです。
Discussion
2点ほど。
1つ目として、「見出しと WAI-ARIA」では
とありますが、WAI-ARIA 1.3仕様には次のように記載されています。
2つ目として、この記事でH69を参照していますが、2.4.1ブロックスキップに言及していないのはなぜでしょう…?
解説書には十分な達成方法として記載されています。
ご指摘ありがとうございます!
aria-level についてですが、「値が6を超えると、ユーザーに問題が発生する可能性がある」ことと「ユーザーエージェントと支援技術のほとんどの組み合わせは、見出しの aria-level 整数1~9のみをサポートしている」ことは、自分の直感としては矛盾するように感じます。aria-level 1~9 がサポートされているのであれば 6 以上の値はやはり「理論上は」設定可能と解釈できてしまう気がするのですが、これはどのように理解すればよいのでしょうか?
2.4.1ブロックスキップについては単純に私の見落としです。のちほど追記いたします!
見出しレベル6まではHTMLで設定できるのは明らかですが、下記URLにあるように、見出しレベル7~9はそれなりにスクリーンリーダーにサポートされていることに由来すると思われます。
個人的な推測ですが、MS Wordでは見出しレベル9を設定できるので、それにつられてレベル9まではスクリーンリーダーがサポートするのではないか、と思われます。
issue のご紹介、ありがとうございます 🙇
aria-level
の仕様上は「1 以上の整数であること」のみが求められるaria-level
1〜9 をサポートしているaria-level
を持つrole=hedaing
要素はユーザーに問題を引き起こす可能性があるという解釈で問題ないでしょうか?「1〜9 がサポートされているのに 6 を超える値は問題となる可能性がある」という矛盾した状況からどう結論付けて伝えるべきか悩んでいます…。
ある機能(この場合はHTMLの属性)について、想定するブラウザーの全部でサポートされているかどうかは、きちんと調べないとわからないわけですが、スクリーンリーダーの場合は、(特定の国でのみ使用されているかもしれない)スクリーンリーダー自身と、スクリーンリーダーと組み合わせるブラウザーで(ときにはOSによっても)挙動が変わることがあります。
その全部の組み合わせでWAI-ARIAを使用することで表現できる、見出しレベル7~9が確実にサポートされている保証はない、ということかと思います。
返信が遅くなり申し訳ありません 🙇
なるほど、理解できた気がします!頂いたご指摘をもとに以下の項目を更新しました。
ご指摘の趣旨に沿っているかやや不安ではありますが、ご確認頂けますと幸いです。