
Chrome 129における`container-type: inline-size`の予期せぬ変更への対応
Chrome 129 で、container-type: inline-sizeを指定した要素に関わる Container Queries の動作が変わりました。変更そのものは小さいのですが、Web アプリのレイアウトが崩れることがあります。何が変わったのか、以前はどう動いていたのか、Chrome 129 からはどう動くのかを順に見ていきます。
変更点
Chrome 129 より前のcontainer-type: inline-sizeには、暗黙的に次の 2 つの働きがありました。
- 絶対配置される要素のための包含ブロックを作成
- 新しい重ね合わせコンテキストを確立
実際のコードで見てみます。
<!DOCTYPE html>
<html lang="en">
<head>
<style>
.container {
container-type: inline-size;
width: 300px;
height: 300px;
border: 2px solid black;
padding: 1rem;
margin: 2rem;
contain: layout;
}
.child,
.sibling {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
color: white;
}
.child {
width: 200px;
height: 200px;
}
.child-1 {
background-color: rgba(255, 0, 0, 0.7);
top: 100px;
left: 100px;
z-index: 2;
}
.child-2 {
background-color: rgba(0, 255, 0, 0.7);
top: 30px;
left: 0;
z-index: 1;
}
.sibling {
width: 150px;
height: 150px;
background-color: rgba(0, 0, 255, 0.7);
top: 165px;
left: 50px;
z-index: 1;
}
</style>
</head>
<body>
<div class="container">
<div class="child child-1">Child 1 (z-index: 2)</div>
<div class="child child-2">Child 2 (z-index: 1)</div>
</div>
<div class="sibling">Sibling (z-index: 1)</div>
</body>
</html>
Chrome 129 以前は、このコードがこう表示されていました。

黒い境界線で囲まれた.container div の子要素は絶対配置されています。child-2(緑の div)にはleft: 0が指定されていますが、位置は親要素の.container div の左端の境界線にそろっています。Chrome 128 以前は、container-type: inline-sizeが絶対配置された子要素のための包含ブロックを暗黙的に作っていたからです。
さらにcontainer-type: inline-sizeの要素は、新しい重ね合わせコンテキストも暗黙的に作ります。そのため緑が一番下、赤が中間、青が一番上になっています。
ところが Chrome 129 では、同じ HTML と CSS がこう表示されます。

.container要素の子要素のための包含ブロックが作られないため、絶対配置された要素はコンテナではなくウェブページを基準に配置されます。その結果、緑の四角形はcontainerから完全にはみ出して、ウェブページの左端に接しています。
新しい重ね合わせコンテキストも作られないので、子要素と兄弟要素の重なり順まで変わりました。緑の四角形は相変わらず一番下ですが、青が中間、赤が一番上です。
なぜこの変更が行われたのか?
Chromium の公式バグトラッカーによると、これは意図的な変更です。Chromium チームが元の仕様の設計ミスと考えている点を直すためだそうです。
仕様自体はまだ更新されていません。ただワーキンググループ内で合意が取れたので、仕様の更新を待たずにブラウザ側の動作を変えた、という流れです。
この記事を書いている時点(2024 年 10 月 3 日)では、他の主要ブラウザ(Firefox や Safari)は Chrome 129 以前の動作のままです。
変更への対応方法
Chrome 129 以前の動作に戻したいだけなら(そして Firefox と Safari が Chrome の実装に追いつくまで、ブラウザ間で表示をそろえておきたいなら)、container-type: inline-sizeを指定した要素にcontain: layoutを足すだけで済みます。
包含ブロックの働きは持たせたいけれど、新しい重ね合わせコンテキストは作りたくない、という場合は、container-type: inline-sizeの要素にposition: relativeを指定する手もあります。こうすると子要素の包含ブロックは作られ、重ね合わせコンテキストは新しく作られません。ただし他のブラウザが Chrome に追いつくまでは、ブラウザごとに動作が変わります。
実際に試してみる
ここまでの話は下の CodePen で試せます。Chrome 129 以降なら、.containerのスタイルからcontain: layoutを消すと、2 番目の画像のようなレイアウトになります。一方、執筆時点で最新の Firefox 131 で同じ CodePen を開くと、contain: layoutがあってもなくても表示は変わらないはずです。
Chrome 129 のリリースノートには、この変更についての記述が見つかりませんでした。しかも先に書いたとおり、仕様の変更より先に動作が変わっています。これには完全に不意を突かれ、自社の Web アプリの 1 つでレイアウトが大きく崩れました。同じ問題にぶつかった方の役に立てばうれしいです。