
みなさん、こんにちは。
MEGIDO(メギド)です。
最近のwebサイト制作で「サイドバーをメインコンテンツ間で追従させる」挙動を実装してほしいという依頼がありました。
「CSSだけで出来ないかなぁ」と調べてみると「position:sticky」を使えば実現できることが判明!
これならすぐに出来そうだと思いましたが、思わぬところに落とし穴があり実装に時間がかかりました、、、
原因はメインコンテンツとサイドバーを「Flex-box」で横並びにしていたことです。
自分の備忘録とwebサイト制作初心者向けに「position:sticky」が効かなかった原因を書き残します。
position:stickyを簡単に説明
「position:sticky」を知らない人もいると思うので、使うとどうなるのかを簡単に説明したいと思います。
「position:sticky」は相対位置指定と固定位置指定の良い部分を組み合わせて出来てるCSSです。
top、right、left、bottomのいずれかを指定して、スクロールして要素の位置が指定した位置までくれば固定されるような挙動になります。
- 指定している位置をスクロールで越えない→相対位置で特定の位置に留まる
- 指定している位置をスクロールで越える→固定位置になり要素がスクロールに追従してくる
要するに「ある位置までスクロールするとそれ以降は要素が固定されてい追従するようになる」って感じです。
詳しい説明が知りたい方は下記のMDNの説明を読んでみてください。
参考:position|MDN
実際にどんな動きをするのか見た方が理解できると思うのでデモをご覧ください。
See the Pen
position: sticky サンプル by skfm (@skfm)
on CodePen.
こちらのコードは下記のサイトを参考にしています。
参考:CSSだけでサイドバーを固定/追従/解除する方法が超簡単!しかも軽くて滑らか!
実装が難しそうなサイドバーのスクロール時の追従が簡単に出来ていますね。
痒い所に手が届くめっちゃ便利なCSSだと思います。
position:stickyが上手く効かない…
さてメギドは「position:sticky」なぜ効かなかったのでしょうか。
下記のデモが「position:sticky」が効かなかった時に似ているコードです。
See the Pen
position:sticky 失敗 by skfm (@skfm)
on CodePen.
ぱっと見だと「何が変わっているか全く分からない」感じですよね。
ただこのデモだと「position:sticky」が効いておらず、スクロール時にサイドバーが追従しません。
「position:sticky」が効いているデモと違うのはただ1つで、「サイドバーに高さをしていない」ことだけです。
このデモではCSSでいうと「.side」に高さを指定していません。
たったこれだけのことで「position:sticky」が効かなくなります。
その理由はなんなのか?
結論からいうと「サイドバーの高さがメインコンテンツの高さと同じ」になっているからです。
今回のデモではメインコンテンツとサイドバーをFlex-boxで横並びにしています。
そしてFlex-boxで高さの違う要素を横並びにするとデフォルトでは1番高さが大きい要素の高さが、すべての要素に継承されます。
その為、今回の場合はサイドバーに高さがメインコンテンツと同じ2000pxになっています。
なのでスクロール時にサイドバーが追従しなくなります。
最初のデモのサイドバーの高さの指定を外すとこんな感じに。
これだとスクロールしてもサイドバーが追従しないのは一目瞭然ですよね(笑)
ただ実際だとサイドバーに背景色を使用することはほぼないと思うので中々気づきにくい。
デベロッパーツールで要素の検証をすれば簡単に分かるんですが、今回はこの検証を見落としてて解決に時間がかかりました。
もしFlex-boxした要素で「position:sticky」を使いたい場合は
- デフォルトの設定を変更してそれぞれの要素の高さになるようにcss「align-items: baseline;」をFlex-boxの親要素に設定する
- 「position:sticky」を指定している要素にcss「align-self: baseline;」を指定して元の要素の高さになるようにする
このどちらをすることで「position:sticky」が効かないことは解決されるでしょう。
最後にposition:stickyの注意点
痒い所に手が届く「position:sticky」には注意点があります。
それはIE11では作動しないということ、、、
2019年10月時の「position:sticky」のサポート状況は上記になっています。
IE11もサポートする場合は別途、javascript系のライブラリなどが必要になるかと思うので注意してください。
では今回はこの辺で。
最後までお読みいただきありがとうございました!