先祖要素にoverflow:hidden;
を使用せず、スクロールバーのことを気にしないで画面幅いっぱいに表示する方法について学びました。
@property、コンテナクエリ、画面幅いっぱい表示の仕組みについては以下の記事を参照してください↓
追記
container-typeを指定した子孫要素のposition:fixed;
が効かなくなるため、このやり方はあんまり便利ではないかもです
サンプルとコード
サンプルと抜粋したコードです↓
<div class="l-page">
<div class="parent">
<p>親</p>
<div class="child">画面幅いっぱい</div>
</div>
</div>
@property --page-width {
syntax: "<length>";
initial-value: 0%;
inherits: true;
}
body{
container-type: inline-size;
}
.l-page {
--page-width:100cqw;
}
.child {
width: var(--page-width);
margin-inline:calc(50% - calc(var(--page-width)/2)); ;
}
なぜコンテナクエリを使うのか
横スクロールを発生させないためです。
vw単位を使うとスクロールバーの幅も含めて計算されるため、横スクロールが発生します↓
この横スクロールを防ぐために既存の方法では、先祖要素にoverflow:hidden;
を記述していました。しかし、このプロパティを記述した要素の子孫要素ではposition:sticky;
が効きません。
そのため、cqw単位を使用します。この単位はスクロールバーの幅を含めない幅を取得できます。
cqwはコンテナコンテキストがない場合、svw単位と同等になるためbody要素にcontainer-type:inline-size;
を記述しています。
body要素にcontainer-typeを記述している理由は、Safariではhtml要素にcontainer-typeを記述してもうまく働かないためです↓
なぜ@propertyを使うのか
簡単にいうと画面幅の値を保持するためです。
cqw単位は一番近いコンテナコンテキストの幅が基準になります。例えば、以下のコードのようにbody要素の子孫にcontainer-typeが指定されているとそこがcqwの基準になります↓
<div class="l-page">
<div class="parent">
<!-- .parentにcontainer-typeを指定 -->
<p>親</p>
<div class="child">画面幅いっぱい</div>
</div>
</div>
body {
container-type:inline-size;
}
.parent {
container-type:inline-size;/*.childのcqwはbodyではなく、.parentが基準になる*/
width: min(800px,90%);
margin: 5rem auto;
border: 1px solid;
text-align: center;
}
.child {
width: 100cqw;
margin-inline:calc(50% - 50cqw);
}
このため、カスタムプロパティを使ってbody要素の画面幅の値を保持します。
このときなぜ@propertyを使用するかというと、単純にカスタムプロパティを使うだけでは上記と同じでcqw単位の基準が変わってしまうためです。
上記コードで考えると、.parentの幅が基準になり.childが親要素を飛び越えることはできません↓
よって@propertyを使ってカスタムプロパティを登録しています。
まとめ
container-typeやcqw単位、@propertyは比較的新しい機能のため、古いブラウザではうまく表示されない可能性があります。そのため、使用するのはもう少し後になるかもです。