
2026/01/31 14:32
リファレンス・ターゲット:あなた自身で包み込んだものを食べること。
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
概要:
Reference Target は ShadowRoot オブジェクトに新しく追加されたプロパティで、ホスト要素が属性ベースの参照(例:、for)に対して内部要素を指し示すことを可能にします。commandForElementを使って宣言的に設定するか、<template shadowRootReferenceTarget="…">で命令的に設定できます。この仕組みはクロスシャドウ参照を再帰的に解決し、以前の提案が必要とした属性ごとの転送を排除します。shadowRoot.referenceTarget = 'inner-input'
この機能は、隠れた入力要素へのラベル付け、ポップオーバーターゲットの設定、ARIA 属性の適用、およびシャドウツリー内でフォームを関連付けるなどの一般的な問題に対処します。また、仕様には新しい「element reference」属性タイプが導入されます。
解決済み対象と未解決対象:解決済み対象は実行時効果(例:ポップオーバーのトリガ)に使用され、未解決対象は開発者に実装詳細を露出します。
実装状況:Chromium はフラグ後ろで完全実装しています。WebKit と Firefox はそれぞれ機能フラグ(Experimental Web Platform Features、ShadowRootReferenceTargetEnabled)の背後にプロトタイプ実装を提供しています。dom.shadowdom.referenceTarget.enabled
残された課題は、任意のクロスシャドウ参照(例:、aria-activedescendant)とアクセシビリティツールが更新されたツリーと同期し続けることです。これらの API の WPT サポートを通じてアクセシビリティテストが拡張されています。aria-labelledby
資金は NLNet Foundation(WebKit/Firefox)および Microsoft エンジニア(Chromium/Edge)から提供されます。
この改訂された概要では、解決済み/未解決対象の区別を追加しつつ、他の主要ポイントはすべて維持しています。
本文
2026年1月30日
shadowdom html accessibility aria
3年前、私は 「Shadow DOM とアクセシビリティが衝突する理由」 というブログ記事を書きました。そこで、シャドウルートによって提供されるカプセル化は、特にアクセシビリティの観点から両刃の剣であると説明しました。ある要素から別の要素へプログラム的に関係を表現できることは、視覚的ヒントに頼らないユーザー体験を構築する上で不可欠です。しかし、シャドウルート内の要素はライトDOM の要素から参照できません。このカプセル化こそが、コンポーネント作成者が依存関係や追加ビルド手順なしに、安全に再利用可能なアクセシブルなコンポーネントを構築できる理由でもあります。
その後数年でさらに英雄的な試みが続きました。最終的に残りそうなのは Reference Target です。本稿ではこの機能の仕組み、私が好きな点、現在の仕様・実装状況(Igalia の NLNet 資金援助のおかげ)について解説します。
簡単な紹介
referenceTarget はシャドウルートオブジェクトに新たに追加されたプロパティで、シャドウホストへの属性ベースの参照先として、シャドウルート内のサブツリーにある要素を指名できます。
例 –
コンポーネントがそのシャドウルートに隠れた<custom-input>を持っているケース。<input>
このパターンはカスタムエレメントライブラリで広く使われ、組み込み要素の振る舞いをコンポジションで拡張できるためです。
<label for="track">Track name:</label> <custom-input id="track"> <!-- #shadowRoot --> <input id="inner-input"> </custom-input>
シャドウルートの
referenceTarget を設定すると、 <label> が内部 <input> を正しくラベル付けできるようになります。
// custom-input のコンストラクタ内: const shadowRoot = this.attachShadow({mode: 'open'}); shadowRoot.referenceTarget = 'inner-input'; shadowRoot.innerHTML = '<input id="inner-input">';
これにより、
<label> は <custom‑input> を <input> と同様に参照できるようになり、 <custom‑input> が内部の <input> へ参照を透過的にプロキシします。
referenceTarget は <template> 要素でシャドウルートを作成する際にも宣言的に設定できます。
<label for="track">Track name:</label> <custom-input id="track"> <template shadowRootMode="open" shadowRootReferenceTarget="inner-input"> <input id="inner-input"> </template> </custom-input>
これは、属性が他の要素を参照する場合(例:
commandForElement のように反射プロパティで設定したとき)にも同様に機能します。
<button id="settings-trigger">Site settings</button> <custom-dialog id="settings-dialog"> <!-- #shadowRoot referenceTarget="inner-dialog" --> <dialog id="inner-dialog"> <button id="close" aria-label="close" commandFor="inner-dialog" command="request-close"></button> <slot></slot> </dialog> <fieldset> <legend>Colour scheme:</legend> <label for="dark"> <input type="radio" id="dark" name="appearance" value="dark" checked> Dark </label> <!-- TODO: more colour schemes --> </fieldset> </custom-dialog> <script> const settingsButton = document.getElementById('settings-trigger'); settingsButton.command = 'show-modal'; settingsButton.commandForElement = document.getElementById('settings-dialog'); </script>
これにより、
<custom‑dialog> は command と commandForElement プロパティの目的で <dialog> と同一視されます。
私が好きな理由
前回の記事では「Cross-root ARIA デリゲーション」と「反射」の提案について懸念を示しました。これらは属性ごとに参照できる要素を1つに限定するボトルネック問題を生み出します。問題自体を解決しませんが、重要性を相対的に低減させます。
referenceTarget の大きな違いは、シャドウホストへの参照を一括で処理できる点です。各属性ごとに転送する必要はありません。この機能は「組み込み HTML 要素の振る舞いをカスタム要素がカプセル化しつつ、他の要素からそのカスタム要素を組み込み要素として参照できる」という特定の問題を解決します。
この狭義の問題設定は、シャドウルート内へクロスする参照が必要なケース(全てではないものの、多く)に適用できます。API はより直感的になります:
for 属性で <custom-input> を指定するとき、実際には内部の <input> を指していることを意識する必要はありません。シャドウルートはホストを一つしか持たないため、 referenceTarget も1つだけに制限されます。
隣接する未解決課題
任意のクロス-シャドウ参照
属性がシャドウルート内の特定要素(例:combobox の
aria-activedescendant、aria-labelledby など)を指す必要があります。これは referenceTarget が扱う単一要素ケースより複雑です。問題を一般化する際には注意が必要で、具体的なユースケースから解決策が見えてくるかもしれません。他の例があれば issue にコメントしてください。
属性転送
カスタムエレメント作成者は、ホスト要素に標準 HTML / ARIA 属性を適用し、それが内部要素へ影響するようにしたい場合があります。例えば:
<custom-button popoverTarget="languages">Language</custom-button> <custom-menu id="languages" popover> <custom-menuitem>Nederlands</custom-menuitem> <custom-menuitem>Fryslân</custom-menuitem> <custom-menuitem>Vlaams</custom-menuitem> </custom-menu>
属性転送のアイデアについては issue が存在します。追求したい場合はコメントしてください。
フォーム関連付け
カスタム要素はフォームに関連付けできますが、内部にあるフォーム関連付け済み組み込み要素(例:
<input>)を外部 <form> と結びつける手段はありません。上記の <custom-input> を <form> 内に入れた場合、内部 <input> はそのフォームと紐づきません。setFormValue() で値をコピーする必要があります。
仕様・実装状況
簡潔に言えば:仕様変更は整備済みで、Chromium が最も機能完備な実装を持ち、WebKit / Firefox は追いついています。
仕様変更
HTML と DOM のプルリクエスト(まだレビュー中):
- DOM – シャドウルートに「参照ターゲット」の概念と
プロパティを追加。referenceTarget - HTML – 実際の効果を定義し、ID 参照を形式化する「要素参照」属性タイプを導入。
参照ターゲット解決手順
- 要素がシャドウホストでなく、またはシャドウルートの
が null の場合、その要素自体を返す。referenceTarget
をシャドウルートのreferenceTargetValue
の値とする。referenceTarget- シャドウルート内で ID が一致する最初の要素(
)を探し、無ければ null を返す。candidate
に対して再帰的に参照ターゲット解決を行い、その結果を返す。candidate
ネストされたシャドウルートは自分自身の
referenceTarget 値を持ち、再帰的に探索されます。
無効な
referenceTarget(空文字や ID 不一致)の場合、解決対象は null であり、ホスト要素ではありません。これが popoverTarget や commandForElement 等の属性にも適用されます。
未解決 vs 解決された属性ターゲット
- 未解決 – 属性が 主張 する参照先(IDL 対応で反映時に使用)。
- 解決済み – 実際に振る舞いに使われる要素(例:ポップオーバーを開く、ラベル名を計算する)。
「参照している」
属性
attr が要素 X にある場合、その属性が指すのは解決済みターゲット要素 Y です。
実装状況
- Chromium – 最も完全な実装。最新仕様変更に若干遅れが出る可能性があります。「Experimental Web Platform Features」を有効化して試せます。
- WebKit / Firefox – フィーチャーフラグ(
/ShadowRootReferenceTargetEnabled
)後のプロトタイプ実装。既存 WPT テストはほぼ通過しますが、一部機能は未実装です。dom.shadowdom.referenceTarget.enabled
アクセシビリティツリーへの影響(例:支援技術への通知)のテストには、より豊富なインフラが必要です。現在進行中のプロジェクト:
- ブラウザがアクセシビリティ API に何を公開しているか直接検証する WPT テスト作成。
- 「アクセス可能プロパティ」API の開発。
期待される挙動を完全にテストできるようになれば、参照ターゲットは正式な相互運用性の焦点領域となります。
資金提供:WebKit / Firefox のプロトタイプ作業と多くの仕様作業は NLNet Foundation からの助成で実施されました。Chromium の実装および追加仕様作業は、Microsoft エンジニア(Edge チーム)によって行われました。