HTML の hidden 属性が列挙型に変更され hidden="until-found" が追加

すべての HTML 要素に指定できる hidden 属性(WHATWG)はこれまで真偽属性(WHATWG)でしたが、このたび列挙型に変更され、新たに until-found が定義されました。

  • hidden="": Hidden 状態
  • hidden="hidden": Hidden 状態
  • hidden="until-found": Until found 状態 ← New!
  • 2022年3月24日現在、 Chrome 102 (canary) は hidden="until-found" に対応しており、本記事で例示する挙動を確認できます。

これは以下の issue で提案されていたものです。

例えばこんな HTML の場合。

<section>
	<h2 id="section1-hdg">Section-1</h2>
	<p>no hidden</p>
</section>

<section hidden="">
	<h2 id="section2-hdg">Section-2</h2>
	<p>Hidden state</p>
</section>

<section hidden="until-found">
	<h2 id="section3-hdg">Section-3</h2>
	<p>Until found state</p>
</section>

ページロード時は1番目のセクションのみがレンダリングされます。

ブラウザのページ内検索機能で文字列 "Section-2" を検索してもヒットしませんが、 "Section-3" を検索すると3番目のセクション見出し文字がヒットし、セクション全体(hidden="until-found" を指定した要素全体)が表示されます。

また、フラグメント識別子付きの URL #section3-hdg でアクセスすると3番目のセクションは最初から表示された状態になります。

ページ内検索やフラグメントナビゲーションで一度表示されると hidden 属性は削除されるため、ページ内検索を終了したり、フラグメントを別の値に書き換えても3番目のセクションは表示されたままとなります。任意に閉じることが有用ならば <details> 要素を使う必要があるでしょう。なお、 hidden 属性が削除される前に beforematch イベントが発生するため JavaScript で検知することが可能です。

document.querySelector('[hidden="until-found"]').addEventListener('beforematch', () => {
	console.debug('beforematch event occurred');
});

CSS 実装上の注意点として、 hidden="until-found" が指定された要素は display: none ではなく content-visibility: hidden が適用されます。とくに共通系の CSS で

[hidden] {
	display: none;
}

などと真偽属性であること前提の指定をしていると、いざコンテンツで hidden="until-found" が使われたときにページ内検索でヒットしなくなる不具合が発生してしまいます(上記のコード例だと "Section-3" がヒットしなくなる)。今のうちに精査しておくと良いでしょう。