CSS Gridでposition: sticky;のスティッキーが効かないときの原因とその対応方法
Post on:2021年12月7日
sponsorsr
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















