CSS Gridでposition: sticky;のスティッキーが効かないときの原因とその対応方法
Post on:2021年12月7日
CSS Gridで2カラムのレイアウト(メインとサイドバー)を実装し、サイドバーにposition: sticky;
を定義したけど、機能しなかったことはありませんか?
CSS Gridでスティッキーが効かないときの原因とその対応方法を紹介します。
Using Position Sticky With CSS Grid
by Ahmad Shadeed
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
はじめに
position: sticky;
がgridコンテナの子で期待通りに機能しなかったことはありませんか? 数日前、私は友人がまさにその問題を解決するのを手伝っていたので、それについて解説したいと思います。
position: sticky;
の使い方については、以前の記事をご覧ください。
gridコンテナの子でposition: sticky;が機能しない
gridコンテナの子でposition: sticky;
が機能しないのは、バグや実装方法が間違っているではありません。それはCSSの仕様、デフォルトの動作です。
なぜそうなるのか、見てみましょう。
1 2 3 4 |
<div class="wrapper"> <aside></aside> <main></main> </div> |
1 2 3 4 5 |
.wrapper { display: grid; grid-template-columns: 250px minmax(10px, 1fr); grid-gap: 1rem; } |
シンプルな2カラムのレイアウトです。aside
要素に幅250px
を設定し、利用可能な残りスペースはmain
要素です。
メインとサイドバーのシンプルなグリッド
aside
要素にposition: sticky;
を追加して、スクロール中に固定されるようにしたいと思います。
1 2 3 4 |
aside { position: sticky; top: 0; } |
しかし、これでは機能しません!
なぜ機能しないのか、解説します。
align-itemsのデフォルトの動作
aside
要素に背景を与えてみると、高さがmain
要素と同じであることが分かります。
aside
要素の高さは、main
要素と同じ
これは、align-items
プロパティのデフォルトの動作です。align-items
プロパティのデフォルト値はstretch
で、その結果グリッド内の最大のカラムに合わせて、高さが同じになります。
参考: CSS Gridでどのように配置されるかをまとめたチートシート
この問題をより分かりやすく説明するために、別の例を紹介しましょう。シンプルなgridコンテナを用意しました。
シンプルなgridコンテナ
1 2 3 4 5 |
.cards__list { display: grid; grid-template-columns: 1fr 1fr 1fr; grid-gap: 1rem; } |
align-items
プロパティを定義していない状態ではstretch
になるため、各カードの高さは最大のカード(右端)と同じになります。
このデフォルトの動作を無効にするには、align-items
の値をstart
にして明示する必要があります。
1 2 3 4 5 6 |
.cards__list { display: grid; grid-template-columns: 1fr 1fr 1fr; grid-gap: 1rem; align-items: start; } |
これで、各カードの高さはそれぞれに適した高さになります。
align-items: start;
を定義
最初の例に戻ります。
この問題をさらに分かりやすくするために、aside
要素に背景を与えました。下記のデモはチェックボックスでalign-items: start;
を切り替えて、サイドバーの高さがどのように変化するかが分かります。
See the Pen
Sticky: eg 1 - debug by Ahmad Shadeed (@shadeed)
on CodePen.
サイドバーをスティッキーにするためにはデフォルトのstretch
上書きして、aside
要素の高さをサイドバー内のコンテンツと同じにする必要があります。aside
要素にalign-self
を使用することもできます。
1 2 3 |
aside { align-self: start; } |
または、親要素(ラッパーなど)にalign-items
を使用すると、すべての子要素に適用されます。
1 2 3 4 5 6 |
.wrapper { display: grid; grid-template-columns: 250px minmax(10px, 1fr); grid-gap: 1rem; align-items: start; } |
どちらを選択するかは、使用目的によって異なります。2つ以上のカラムがあって、そのうちの1つだけを揃えたいという場合もあるでしょう。
See the Pen
Sticky: eg 1 by Ahmad Shadeed (@shadeed)
on CodePen.
別の例
CSS Gridのデフォルトの動作を共有できる非常に似た例として、チームのリストページがあります。
チームのリストページ
スクロール時にはサイドバーの「Design」を固定して、表示されているチームリストが「Design」であることを分かるようにしています。「Design」の見出しにalign-self: start;
を使用しないと、期待通りには動作しません。
1 2 3 4 5 6 7 8 9 10 11 |
.section { display: grid; grid-template-columns: 100px 1fr; grid-gap: 2rem; } .section__headline { position: sticky; top: 1rem; align-self: start; } |
実際の動作は、下記をご覧ください。
See the Pen
Sticky: eg 2 by Ahmad Shadeed (@shadeed)
on CodePen.
終わりに
CSS Gridでposition: sticky;
が期待通りに機能しない問題はバグでも実際の問題でもなく、仕様です。この仕様はわたし達デベロッパーが場合によっては恩恵を受けるCSSの機能で、別の値に上書きすることで対応できます。
同じトピックについての記事があることが分かりました(同じトピックを異なる声で聞くことができるのが、Webのいいところですね)。Melanie Richardsの記事もぜひ読んでみてください!
この記事があなたのお役に立てれば幸いです。
コメントや提案があれば、@shadeed9までお願いします。
sponsors