position:fixed 要素のスタック変更

Tom Wiltzius
Tom Wiltzius

Chrome 22 では、position:fixed 要素のレイアウト動作が以前のバージョンと若干異なります。すべての position:fixed 要素が新しいスタッキング コンテキストを形成するようになりました。これにより一部のページの積み重ね順序が変更され、ページ レイアウトが崩れる可能性があります。新しい動作は、モバイル デバイス(iOS Safari と Chrome for Android)の WebKit ブラウザの動作と一致します。

何を積み重ねるか?

ページ上の要素の深度の順序を決定する z-index は、誰もが知っていて愛用しています。ただし、すべての Z-Index が同じように作成されているわけではありません。要素の z-index は、同じスタッキング コンテキスト内の他の要素との相対的な順序を決定するだけです。ページのほとんどの要素は単一のルート スタッキング コンテキストにありますが、自動ではない z-index 値を持つ絶対的または相対的に位置付けられた要素は、独自のスタッキング コンテキストを形成します(つまり、すべての子は親内で Z オーダーとなり、親外のコンテンツとはインターリーブされません)。Chrome 22 以降、position:fixed 要素も独自のスタッキング コンテキストを作成します。

スタッキング コンテキストの一般的な概要については、こちらの MDN 記事をご覧ください。

position:fixed新しい position:sticky 属性と比較します。参考として、position:sticky は常に新しいスタック コンテキストを作成します。

目的

モバイル ブラウザ(Mobile Safari、Android ブラウザ、Qt ベースのブラウザ)は、position:fixed 要素を独自のスタッキング コンテキストに配置し、特定のスクロールの最適化を可能にするため、しばらくの間(iOS5、Android Gingerbread など)、ウェブページのタップに対する応答性を高めています。この変更は、次の 3 つの理由でパソコンに適用されます。

  1. ウェブ作成者にとって、「モバイル」ブラウザと「パソコン」ブラウザでレンダリングの動作が異なることは容易なことではありません。CSS は可能な限りどこでも同じように動作する必要があります。
  2. タブレットでは、「モバイル」と「パソコン」のどちらのスタッキング コンテキスト作成アルゴリズムが適切かが明確ではありません。
  3. モバイルからデスクトップにスクロールのパフォーマンスを最適化することは、ユーザーと作成者の双方にとって有益です。

変更の詳細

さまざまなレイアウト動作の例を次に示します。https://codepen.io/paulirish/pen/CgAof

この変更により、どちらのバージョンも右側のバージョンと同じように表示されます。

この例では、緑色のボックスには z-index: 1、ピンク色のボックスには z-index: 3、オレンジ色のボックスには z-index: 2 があります。青いボックスはオレンジ色のボックスの祖先で、position:fixed を持っています。

青いボックスが独自のスタッキング コンテキストを取得する場合、オレンジ色のボックスの z-index は、青いボックスのスタッキング コンテキストに応じて計算されます。青いボックスの z-indexauto であり、ルート スタッキング コンテキストのスタッキング レベルが 0 であるため、オレンジ色のボックスは、ルート コンテキストの Z インデックスがそれぞれ 1 と 3 である緑とピンクのボックスの背後にあります。

青いボックスが独自のスタッキング コンテキストを取得しない場合、オレンジ色のボックスの z-index は、(緑とピンクのボックスとともに)ルート スタッキング コンテキストとの相対値で計算されます。したがって、オレンジ色のボックスは、最終的にピンクと緑色のボックスと交互に配置されます。

スタッキング コンテキストの作成の基準(およびスタッキング コンテキストの一般的な動作)の詳細については、こちらの MDN 記事をご覧ください。この例の右側のバージョンでは、不透明度が 1 より小さいため、常に青いボックスに独自のスタッキング コンテキストが与えられています。動作の変更により、個別のスタッキング コンテキスト、つまり position:fixed の要素を作成するための別の条件が実質的に追加されます。

テストと今後について

ページが変更されるかどうかをテストするには、Chrome の about:flags に移動し、[固定位置要素でスタッキング コンテキストを作成する] をオンまたはオフにします。どちらの場合もレイアウトが同じように動作するのであれば完了です。そうでない場合は、そのフラグを有効にして問題がないことを確認してください。Chrome 22 ではデフォルトで有効になります。

この変更により、1 つの機能、つまり position:fixed サブツリー内にコンテンツをインターリーブする機能と、スクロールしないコンテンツが外部から存在するという機能が削除されます。ウェブ デベロッパーが意図的にこれを行っている可能性は考えられません。複数の position:fixed 要素に DOM の各部分を割り当てることで、同様の効果が得られます。例として、次の 2 つの例を考えてみましょう。

https://codepen.io/wiltzius/pen/gcjCk

このページでは、 position:fixed 要素の 2 つの子 div(overlayA と overlayB)を使用し、1 つの div を個別の content div の上に配置し、1 つずつを同じ個別の content div の下に配置しようとします。現在、position:fixed 要素は独自のスタッキング コンテキストであり、(すべての子とともに)content div 2 の完全に上または下に完全に配置されるため、これを行うことはできません。

これを修正するには、2 つのオーバーレイを独自の position:fixed 要素に分割します。それぞれが独自のスタッキング コンテキストで、そのうちの 1 つを content div の上に、もう 1 つを content div の下に配置できます。Chrome 21 と 22 で動作する固定例をご覧ください。

https://codepen.io/wiltzius/pen/vhFzG

この例の起源は、inimitable hixie にあります。

Chrome は、position:fixed 要素を使用して独自のスタッキング コンテキストを作成する初のデスクトップ ブラウザです。関連する基準は CSS の Z-Index 仕様です(例: https://www.w3.org/TR/CSS21/zindex.html)。モバイル ブラウザとデスクトップ ブラウザの違いについてはまだコンセンサスが得られていませんが、モバイルとデスクトップで 2 種類の動作が異なるという混乱を考慮し、Chrome は当面、両方のプラットフォームで単一の動作に移行することにしました。

2012 年 10 月 1 日更新: この記事の元のバージョンでは、CSS の z-index 仕様が、位置の新しい動作である「固定要素」を反映するようすでに変更されていることが示唆されていました。これは不正確です。www スタイルのリストで議論されていますが、現時点では仕様には変更されていません。