2025年11月30日
こんにちは!今日もプログラミングを楽しんでいますか?
ぜんかいの記事では CSS の重なり順を、ペイントアプリのレイヤーとレイヤーコンテナにたとえて解説しました。こんかいは予告通り、「ルートコンテキストよりも上位にあるコンテキスト(レイヤーコンテナ)」から、「ルートコンテキストのきょうだいレイヤー」のご紹介を中心に、学んでゆきましょう。
「ルートよりも上位」とは?
そもそも「ルート」コンテキストなのに、その上位とはいったい……? 確かにあまりピンと来ないですよね。実はここでいう「ルート」とは、文書ルート (Document Root) 、すなわち HTML 文書そのもののことなのです。
HTML 文書は単なる .html ファイルですが、それを読み取って構造を解析し、画面に描画してくれる「もの」があります。
それこそが、文書ルートよりも上位に存在する――Web ブラウザです。
Web ブラウザ自身も「レイヤーコンテナ」
Web ブラウザは仕組みとして、その表示領域を重ね合わせコンテキストに似た実装(※「コンポジットレイヤー」と呼ばれます)で、レイヤーコンテナとして扱います。そしてそこに属するレイヤーは、HTML文書全体の解析結果、すなわちルートコンテキストです。「ルートコンテキスト自身も、ひとつのレイヤー」というわけですね。
最上位層(Top Layer)
さて、ブラウザが「ルートコンテキストというレイヤーの、レイヤーコンテナ」ということは、「ルートコンテキストというレイヤーにも、きょうだいレイヤーがある」ことを意味します。そしてそのレイヤーは、最上位層という、ブラウザが自動的に生成する仮想的な要素から生み出されます。
ルートコンテキストの「手前」の要素をまとめる構造
最上位層そのものは重ね合わせコンテキストを形成しませんが、最上位層に配置された要素群はそれぞれ独立したレイヤーとして扱われ、かつ、ルートコンテキストよりも手前に描画されます。ただしそれでも、それぞれのレイヤーはルートコンテキストのきょうだいであることには変わりません。
……言葉で説明するより、図で見たほうがわかりやすいですね。

つまり、どちらもブラウザという“レイヤーコンテナ”の直下に配置されます。
常にビューポートに固定!
最上位層のもうひとつの特徴として、HTML 文書ではなくブラウザのビューポートに対して固定されていることが挙げられます。

これが何を意味するのかは、このすぐ後の最上位層で遊ぼう! で解説します。
最上位層で遊ぼう!
ではお待ちかね、この最上位層による機能を使って、一緒に遊んでみましょう!
<dialog>
まずは <dialog> をご紹介します。画面中央のボタンを押してみてください。そのブラウザのデフォルトのモーダルウインドウが表示されるはずです(ブラウザによっては背景が見づらいので、背景色を濃くしています)。
<dialog> 要素は、いわゆる「ダイアログ」や「モーダルウインドウ」を手軽に実装するために考案されました。
HTML ではこのように記述しますが、この要素は、最上位層の子要素として表示されます。
<!-- この要素は「最上位層」の子要素になる -->
<dialog closedby="any">
<p>薄暗い半透明の背景に、このダイアログが浮かんでいますね。</p>
<button id="close">閉じる</button>
</dialog>さて、画面をスクロールさせて、「ダイアログを開く」ボタンを押してみましょう。


画面をスクロールさせても、常に「見えている部分(ビューポート)」が薄暗くなり、その中央にダイアログが表示されます。「最上位層は常にビューポートに対して固定される」とは、こういう意味なのです。
<popover>
自作のドロップダウンリストや、いわゆる「トースト通知」を実現する <popover> も見てみましょう。
画面中央のボタンを押してみてください。画面左下に、通知のような小さい窓(トースト)が出現するはずです。
このコードで現れるトースト(ポップオーバー)は、一つ一つが最上位層の子要素です。ではこれも、画面をスクロールさせて、「トースト表示」ボタンを押してみましょう。


ダイアログと同様、HTMLでの位置ではなく、ビューポートに対する位置に出入りしていることを確認してください。これが最上位層の子要素の性質です。
「ルートコンテキストのきょうだいレイヤ」がそんなに重要?
はい、もちろんです! 以前の記事「どうしてフィルタが効かないの?」を読み返してから、以下のコードを試してみてください。
みごと、ダイアログの表示で、ルートコンテキスト全体をぼかすことができました! 先の記事の、「フィルタがかかるのは、直接の親コンテキストのみ!」を思い出してください。このシリーズ風に言い換えれば、
フィルタがかかるのは、自身のレイヤーコンテナ(と、そこに属するきょうだいレイヤー)のみ!
となります。ゆえに、同じブラウザというレイヤーコンテナを持つきょうだいレイヤー「ルートコンテキスト」に、フィルタを掛けられたというわけなのです!
この状態……コンテキストを持たない包含構造を無視した階層構造……を、一般的なペイントアプリの「レイヤーUI」になぞらえると、こんな感じになります(一般的な「レイヤーUI」とは逆に、下にある方が手前に表示されることに注意してください)。

現時点で、レイヤー(コンテナ)は、このように積み重なっています。「cntnr ▼」は、レイヤーコンテナを展開して内容を表示していること、「fltr ▼」は、そのレイヤーに設定しているフィルターを展開して内容を表示していることだと思ってください。
ここで「ダイアログ」レイヤーから伸びている白い矢印にご注目ください。「ダイアログ」レイヤーに「バックドロップフィルタ→ぼかし」という設定がされると、白い矢印は「ブラウザ」レイヤーコンテナに伸びてゆきます。その結果、バックドロップフィルタは、「ブラウザ」と、自身より奥にいるきょうだい「ルートコンテキスト」に適用されるのです。
次回は「レイヤーグループ」!
さて、ここでおさらいをしましょう。こんかいは「最上位層」という、ルートコンテキストのきょうだいを中心に解説してゆきました。そして、この最上位層に配置された要素は、ルートコンテキストよりも必ず手前に描画されることもお伝えしました。
次回は、ルートコンテキスト以下のレイヤーを入れ子にするテクニック、いわゆるレイヤーグループについて解説してゆく予定です。これが理解できれば、z-indexを「設計」できるようになるため、効率的な重ね合わせを組み立てられるようになります。それでは、お楽しみに!