The Outline Algorithm Utopia

Browser and UI #2 HTML/ARIA
saku🌸 / @sakupi01

saku

🤗

Design Technologist / ex- Web Frontend
@Cybozu

🍏 / ☕ / 🌏 > ❤

The Outline Algorithm Utopia

※ このスライドは The Outline Algorithm Utopia の内容に基づきます

ブラウザからのお知らせ

ブラウザからのお知らせ: UA Style が変わります

Intent to unship: UA styles for h1 in article, aside, nav, section

Intent to Deprecate and Remove: Deprecate special font size rules for H1 within some elements
Intent to unship: UA styles for h1 in article, aside, nav, section
Remove UA style for h1-h6 in section (et. al.) and hgroup · Issue #7867 · whatwg/html
Remove UA styles for h1 in article, aside, nav, section by zcorpan · Pull Request #11102 · whatwg/html

何がどう変わる?

<body>
  <h1>I'm a Level 1 Heading.</h1>
  <section>
    <h1>I'm a Level 1. Supposed to act as a Level 2.</h1>
    <section>
      <h1>I'm a Level 1. Supposed to act as a Level 3.</h1>
      <section>
        <h1>I'm a Level 1. Supposed to act as a Level 4.</h1>
        <section>
          <h1>I'm a Level 1. Supposed to act as a Level 5.</h1>
        </section>
      </section>
    </section>
  </section>
</body>

~ 2025/03

section のネストが深くなるにつれて、 margin と font-size が小さくなる

<section> のネストが深くなるにつれて、 marginfont-size が小さくなる

2025/03 ~

section のネスト関係なく、h1 であれば h1 の margin と font-size

<section> のネスト関係なく、h1 であれば h1 の marginfont-size
→ 段階的にロールアウト

なぜ?

なぜ?

そもそもなんでネストによって見た目が変わっていたのか?

なぜ?

そもそもなんでネストによって見た目が変わっていたのか?
それによって何が問題となっていたのか?

なぜ?

そもそもなんでネストによって見た目が変わっていたのか?
それによって何が問題となっていたのか?
この変更が意味するものとは?

なぜ?

そもそもなんでネストによって見た目が変わっていたのか?
それによって何が問題となっていたのか?
この変更が意味するものとは?
次に何が待っている?

Back to over 30 years ago ... 🛸

Flat Content

  • Brian Kardell の主張を借りるのであれば、HTML の設計思想は、その前身となるフラットな構造のマークアップ言語(GML)に遡るとされている
  • 要素は単に視覚的なマーカーとして機能し、特に <p> などの要素では、閉じタグは必要ないと考えられていた節がある
<h1>This marks the top level heading
<p>You can know that this is a paragraph and not heading...

構造的な Document Model - DOM, The Accessibility Tree

  • プログラム的な利用における構造解釈が必要になる
    • DOM, The Accessibility Tree
  • 視覚的な Semantics と 構造的な Semantics の間に不整合が生じるようでは困る!

「見出しレベルの自動ハンドリング」をブラウザ側でやってしまえばいいのでは・・・?

🚀

The Birth of Utopia

🚀

Sectioning & Document Outline Algorithm

  • 文書を Sectioning する
    • <section><article> などの Sectioning Content Element または Sectioning Root を使用する場合
    • h1-6 の見出し要素を使用して作成された、「暗黙のセクション」を使用する場合
    • <hgroup> 要素を使用してグループ化したセクションの見出しを使用する場合
  • それによって、”Outline” という「Heading を持った Section で構成される枠」 を生成する
  • その階層構造を決定するアルゴリズムが、実に Document Outline Algorithm
<!-- as-is -->
<body> <!-- Sectioning Root -->
 <h4>Apples</h4>
 <p>Apples are fruit.</p>
 <section> <!-- Sectioning Content Element -->
  <h2>Taste</h2>
  <p>They taste lovely.</p>
  <h6>Sweet</h6> <!-- 暗黙のセクション -->
  <p>Red apples are sweeter than green ones.</p>
  <h1>Color</h1> <!-- 暗黙のセクション -->
  <p>Apples come in various colors.</p>
 </section>
</body>
<!-- to-be -->
<body>
 <h1>Apples</h1>
 <p>Apples are fruit.</p>
 <section> <!-- Sectioning Content Element -->
  <h2>Taste</h2>
  <p>They taste lovely.</p>
  <section> <!-- 暗黙のセクション -->
   <h3>Sweet</h3>
   <p>Red apples are sweeter than green ones.</p>
  </section>
 </section>
 <section> <!-- 暗黙のセクション -->
  <h2>Color</h2>
  <p>Apples come in various colors.</p>
 </section>
</body>
<!-- as-is -->
<body> <!-- Sectioning Root -->
  <h1>I'm a Level 1 Heading.</h1>
  <section> <!-- Sectioning Content Element -->
    <h1>I'm a Level 1. Supposed to act as a Level 2.</h1>
    <section> <!-- Sectioning Content Element -->
      <h1>I'm a Level 1. Supposed to act as a Level 3.</h1>
      <section> <!-- Sectioning Content Element -->
        <h1>I'm a Level 1. Supposed to act as a Level 4.</h1>
        <section> <!-- Sectioning Content Element -->
          <h1>I'm a Level 1. Supposed to act as a Level 5.</h1>
        </section>
      </section>
    </section>
  </section>
</body>
<!-- to-be -->
<body>
  <h1>I'm a Level 1 Heading.</h1>
  <section>
    <h2>I'm a Level 1. Supposed to act as a Level 2.</h2>
    <section>
      <h3>I'm a Level 1. Supposed to act as a Level 3.</h3>
      <section>
        <h4>I'm a Level 1. Supposed to act as a Level 4.</h4>
        <section>
          <h5>I'm a Level 1. Supposed to act as a Level 5.</h5>
        </section>
      </section>
    </section>
  </section>
</body>

「フラットな構造」を基本としていた HTML に、階層構造を表現するという画期的なアイディアが持ち込まれた

... もしかして、、、

「全部 <h1> 使っても、Sectioning しとけば、ブラウザが ”いい感じ” にしてくれる?!」

Sections may contain headings of any rank, but authors are strongly encouraged to either use only h1 elements, or to use elements of the appropriate rank for the section’s nesting level.


セクション内には任意のランクを含めることができますが、著者はh1 要素のみを使用するか、セクションのネストに応じたランクの見出しを記述することを推奨します。
4.3 Sections — HTML 5.1 Nightly https://web.archive.org/web/20121214011658/http://www.w3.org/html/wg/drafts/html/master/sections.html#headings-and-sections

ブラウザ:「実装したよ!」

section のネストが深くなるにつれて、 margin と font-size が小さくなる

「ほんとだ!」

「ほんとうに?!」

sectioningでの見出し階層は支援技術に伝わらない

“The Algorithm” was the only missing piece

ブラウザは Sectioning を全く具現化しなかったわけではない

  • <section><article><nav> といった Sectioning Content Element を実装
  • Section のネストレベルに応じた UA Style を提供

Section のネストが深くなるほど marginfont-size が小さくなるようなスタイルが適用され、見た目上は「見出しレベルが自動調整」されるように

“The Algorithm” was the only missing piece

  • Sectioning を駆使したマークアップをしても、Outline Algorithm 自体は実装されていないので、構造的な Semantics としてプログラムに伝わらない。支援技術に伝わらない
  • 問題だったもの(「視覚的な Semantics」と「構造的な Semantics」の不整合)が、何も解決されていない

sectioningでの見出し階層は支援技術に伝わらない

Outline Algorithm in HTML5 Era

Outline Algorithm を前提とした記述を削除、警告文を追加

⚠Warning! There are currently no known native implementations of the outline algorithm in graphical browsers or assistive technology user agents, although the algorithm is implemented in other software such as conformance checkers and browser extensions. Therefore the outline algorithm cannot be relied upon to convey document structure to users. Authors should use heading rank (h1-h6) to convey document structure.
HTML 5.2: 4.3. Sections https://html.spec.whatwg.org/multipage/sections.html#creating-an-outline

「構造的な Semantics」 を「視覚的な Semantics」に合わせることを諦め、白紙に戻そうとしはじめた

Outline Algorithm in HTML Living Standard Era

Outline Algorithm in HTML Living Standard Era

  • Living Standard の仕様から Outline Algorithm に関して誤解を招く記述を削除する PR
  • 単に仕様と矛盾した警告を載せるにとどまらず、アルゴリズム自体を消すか実装するかの問題まで波及しており、これが議論を難航させる原因になった?

「Outline Algorithm は一向に実装されないが、Structural なコンテンツは現代の Web にとって欠かせない。ならば、別の手段で Structural な意味を HTML に持たせることはできないか?」

「Outline Algorithm は一向に実装されないが、Structural なコンテンツは現代の Web にとって欠かせない。ならば、別の手段で Structural な意味を HTML に持たせることはできないか?」

  • <h>
  • Heading Level Concept

Over 34 year’s old, yet brand-new: <h>

<h> というアイディア自体は、実は Tim Berners-Lee が Web を始めたばかりの 1991 年から存在した

I would in fact prefer, instead of <H1>, <H2> etc for headings [those come from the AAP DTD] to have a nestable <SECTION>..</SECTION> element, and a generic <H>..</H> which at any level within the sections would produce the required level of heading.
www-talk from September to October 1991: Re: status. Re: X11 BROWSER for WWW

<h>

既に実装済みの Sectioning Content Elements と組み合わせ、Outline Algorithm によってSection のコンテキストに応じた見出しレベルを自動的に決定するために提案された要素

<section>
  <h>I can be any Level depending on the section context!</h>
  <p>paragraph</p>
</section>

<h> 以外の Headings を deprecated 候補とし、XHTML2.0 の仕様にはこれが含まれることに

結局 h1-6 は残されたままで、それどころか XHTML 2.0 自体も放置され、謎だらけのまま終わる ...

Re-visit <h>

HTML5 でも <h> の追加が提案される

<h>の持つ矛盾

課題:HTML として、「Outline Algorithm が実装されないこと」が課題だったのに、
解決策:<h>は「Outline Algorithm を利用した新規方法」だった

根本的な解決策にはならず・・・

Heading Level Concept

「Outline Algorithm で Outline を生成すること」ではなく「Sectioning Content 内の見出しレベルを調整すること」に焦点を当てた Anne van Kesteren提案

// https://github.com/annevk/html-heading-level-polyfill/blob/main/polyfill.js
function determineLevel(el) {
  let level = 1;
  // Arguably the parentNode being null check can be removed as it will never be null when this and
  // the function below are run on a document, as is the case.
  //
  // This is "sectioning content" and "sectioning roots"
  while (el.parentNode && (el = el.parentNode.closest("article,aside,nav,section,blockquote,details,dialog,fieldset,figure,td"))) {
    level += 1;
  }
  return level;
}

これぞ顧客が本当に求めていたもの・・・?

  • Outline Algorithm という机上の空論を主張し続けない
    • Outline Algorithm を大幅に簡略化し、Section Content のネストレベルをカウントするだけ
  • ”プログラム的な利用における構造解釈の重要性” という今の Web が、支援技術を利用するユーザが、 喫緊で必要としているものにアプローチしている

Heading Level Concept は頓挫。Outline Algorithm 廃止へ

h1が消失する後方互換の問題が発生:

Unfortunately, this was not a success (too many h1s got adjusted to be h2s) so we’ve removed this code and abandoned this particular plan for dealing with heading levels in HTML: https://bugzilla.mozilla.org/show_bug.cgi?id=1590366.
Intent to prototype: heading levels

<body>
  <main> <!-- Sectioning Content Element -->
    <article> <!-- Sectioning Content Element -->
      <h1>Level 3・・・?</h1> <!-- レベル = 1+2 = 3 になってしまう -->
    </article>
  </main>
</body>

Outline Algorithm の概念を廃止する PR への契機となった:

replace current outline algorithm with one based on heading levels by stevefaulkner · Pull Request #7829 · whatwg/html

全て、終わった・・・?

問題: 「視覚的な Semantics」と「構造的な Semantics」の不整合

解決策: 以下の 2 条件が揃うこと

  1. ✅ 「視覚的な Semantics」を 「構造的な Semantics」 に合わせる
    1. Sectioning を意識したスタイルの実装
  2. 「構造的な Semantics」 を 「視覚的な Semantics」 に合わせる(こっちを頑張ってた
    1. Outline Algorithm を実装する

問題: 「視覚的な Semantics」と「構造的な Semantics」の不整合

解決策: 以下の 2 条件が揃うこと

  1. ✅ 「視覚的な Semantics」を 「構造的な Semantics」 に合わせる
    1. Sectioning を意識したスタイルの実装
  2. 「構造的な Semantics」 を 「視覚的な Semantics」 に合わせるこっちが頓挫した
    1. Outline Algorithm を実装する
      • <h> の提案は Reject
      • Anne の Heading Level Concept (v1)は頓挫
      • Outline Algorithm を仕様から削除

問題: 「視覚的な Semantics」と「構造的な Semantics」の不整合

解決策: 以下の 2 条件が揃うこと

  1. ✅ 「視覚的な Semantics」を 「構造的な Semantics」 に合わせる(こっちだけ残った
    1. Sectioning を意識したスタイルの実装
  2. 「構造的な Semantics」 を 「視覚的な Semantics」 に合わせる (こっちが頓挫した)
    1. Outline Algorithm を実装する
      • <h> の提案は Reject
      • Anne の Heading Level Concept (v1)は頓挫
      • Outline Algorithm を仕様から削除

30 年以上、「視覚的な Semantics」と「構造的な Semantics」の不整合という問題を抱え続け、ずっと「「構造的な Semantics」 を 「視覚的な Semantics」 に合わせる」方向で解決しようとしていたのに、結局ずっと不整合なままだった

問題: 「視覚的な Semantics」と「構造的な Semantics」の不整合

解決策: 以下の 2 条件が揃うこと

  1. ✅ 「視覚的な Semantics」を 「構造的な Semantics」 に合わせる(こっちを削除する方向で揃えるときが来た
    1. Sectioning を意識したスタイルの実装
  2. 「構造的な Semantics」 を 「視覚的な Semantics」 に合わせる (こっちが頓挫した)
    1. Outline Algorithm を実装する
      • <h> の提案は Reject
      • Anne の Heading Level Concept (v1)は頓挫
      • Outline Algorithm を仕様から削除

ブラウザからのお知らせ: UA Style が変わります

Intent to unship: UA styles for h1 in article, aside, nav, section

これが削除される:

In the following CSS block, x is shorthand for the following selector: :is(article, aside, nav, section)

@namespace "http://www.w3.org/1999/xhtml";

x h1 { margin-block: 0.83em; font-size: 1.50em; }
x x h1 { margin-block: 1.00em; font-size: 1.17em; }
x x x h1 { margin-block: 1.33em; font-size: 1.00em; }
x x x x h1 { margin-block: 1.67em; font-size: 0.83em; }
x x x x x h1 { margin-block: 2.33em; font-size: 0.67em; }

15.3.6 Sections and headings | HTML Standard

問題: 「視覚的な Semantics」と「構造的な Semantics」の不整合

解決策: 以下の 2 条件が揃うこと

  1. 「視覚的な Semantics」を 「構造的な Semantics」 に合わせる
    1. Outline Algorithm の UA Style を実装する
  2. 「構造的な Semantics」 を 「視覚的な Semantics」 に合わせる
    1. Outline Algorithm を実装する
      • <h> の提案は Reject
      • Anne の Heading Level Concept (v1)は頓挫
      • Outline Algorithm を仕様から削除

→ どっちも削除するということで整合した

Outline Algorithm の閉幕

Outline Algorithm を取り巻く 30 余年の中で、何がどう変わった・・・?

「視覚的な Semantics」と「構造的な Semantics」の不整合は、30 年以上かけてやっと解消されたけど、

ずっと Outline Algorithm は実装されず、フラットな文書構造の中にいた

Outline Algorithm の閉幕が示唆すること:

(とりあえず今は・・・)構造的に正しいマークアップを

  • 見出しレベルを適切に使用する:h1 から順に階層的に使い、レベルをスキップしない
  • 見た目ではなく構造で:CSSで見た目を調整するのは自由だが、まずは意味的に正しい構造を構築する
  • アクセシビリティを念頭に置く:スクリーンリーダーなどの支援技術が正しく解釈できる文書構造の構築をする

markuplint とか、HTML validator とか...

次に何が待っている?

[WIP!] Mechanism for opting-in for Heading Level Concept:

🤩 Heading Level Concept (v2) 🤩

Heading Level Concept (v2)

  • Anne の Heading Level Concept を実現する新たな解決策として、headingoffset & headingreset を導入
    • 「h1 がドキュメントから消滅する」などの問題を解消しつつ、Heading Level Concept をオプトイン
    • Outline Algorithm でない方法で見出しの自動調整
  • 見出しレベルが h1~6 に限られなくなる → :heading&:heading(N)

More Details: #[WIP!] Mechanism for opting-in for Heading Level Concept

headingoffset & headingreset attributes

Outline Algorithm 亡き今、 ✨ Heading Level Concept ✨ による見出しの自動調整に期待・・・?!

Thank you!

Appendix

HTMLにおいて「視覚的な Semantics」が「構造的な意味」より優先された結果、多くの混乱が生じた。視覚が正しいように見えれば構造がメチャクチャでも気にしないという状況を生み出してしまった

見出しレベルの適切なハンドリングは、完全に開発する側に委ねられている 「見出しレベルの自動ハンドリング」を実現すれば、ブラウザ側でアクセシブルな DOM 構造を担保できていいのでは...?

この間は HTML の標準が W3C の HTML5.x から WHATWG の Living Standard に変遷していった期間でもあり

この間は HTML の標準が W3C の HTML5.x から WHATWG の Living Standard に変遷していった期間でもあり

それに対して Steve Faulkner が 2015 年に Issue を立て、Living Standard の仕様から Outline Algorithm に関して誤解を招く記述を削除する PR を提出し、これが約 7 年間も議論されることになります。 WHATWG での議論は、仕様と矛盾した警告を載せるのではなく、アルゴリズム自体を消すか実装するかの問題になっており、これが議論を難航させる原因になったのだと思います。

じゃあその 7 年間、周りはただ待っていただけなのかというとそういうわけではない

HTML として ”課題” だったのは「Outline Algorithm が実装されないこと」だったのに、 結果として出た ”解決策” は「Outline Algorithm を利用した新規方法」

Anne の作った Heading Levels の Polyfill この Polyfill のアルゴリズムは非常にシンプルで、<h1> か <hgroup> の Sectioning Content をたどり、Sectioning にネストされる毎にレベルを加算して aria-level 属性に設定するというもの

この点で、Heading Level Concept は非常に筋の通った提案だった

とはいえ、Heading Level Concept によって、長年滞っていた Outline Algorithm の議論にメスが入り、これが Outline Algorithm の概念を廃止する PR につながりました。