うぇぶわんこ
position: sticky を書いたのに、ぜんぜん追従してくれないワン……。top も書いてるのに、どこを見ればいいの?
さとけん
sticky自身より、親要素や overflow が原因になっていることも多いです。今回は、私が実際に確認している順番で整理してみます。
position: sticky を指定した。top も指定した。それなのに、スクロールしてもまったく追従してくれない。CSSを書いていると、こういうことが意外とあります。書き方だけを見ると間違っていないので、stickyを指定した要素ばかり見直してしまいがちですが、原因が親要素や、さらに外側の祖先要素にあることも少なくありません。この記事では、top、overflow、高さ、Flexbox・Gridなど、stickyが効かないときによくある原因を実例コードと一緒に紹介します。
この記事でわかること
まず確認したいポイント
「仕組みはあとでいいので、とりあえず今のstickyを直したい」という場合は、まず次の項目を確認してみてください。
クイックチェック
私の場合、top に問題がなければ、次は親要素の overflow を疑います。
原因と確認場所の早見表
position: sticky はどこに固定されるのか
原因を見る前に、stickyの仕組みをほんの少しだけ整理しておきます。
よく使うのは、こんな書き方です。
.sidebar {
position: sticky;
top: 20px;
}
top: 20px は、「スクロールして、この要素が上から20pxの位置まで来たら、そこからstickyする」という基準になります。
ここで覚えておきたいのは、position: sticky が単純な「画面に固定するCSS」ではないということです。
stickyは通常のレイアウトの中にいるまま、スクロール位置に応じて追従します。さらに、祖先要素にスクロールの仕組みを持つ overflow があると、その要素との関係で動作します。
sticky自身だけを見ても原因が分からないことがある
stickyが効かないときは、sticky自身 → 親要素 → さらに外側の祖先要素と、少しずつ外側へ見ていくのがポイントです。
原因1:top などの位置を指定していない
まず最初に確認したいのが、top などの位置指定です。
例えば、これだけでは縦方向に期待したstickyの動きになりません。
.sidebar {
position: sticky;
}
縦方向にstickyさせたいなら、top や bottom など、どこまで来たらstickyさせるのかを指定します。
.sidebar {
position: sticky;
top: 20px;
}
画面上端に付けたいなら top: 0 でも大丈夫です。
かなり基本的なところですが、ほかの原因を探し始める前に一度確認しておくと、あれこれCSSを触らずに済みます。
原因2:親・祖先要素の overflow が影響している
top も書いている。それでもstickyしない。
そんなとき、私なら次に親・祖先要素の overflow を見ます。
例えば、こんな構造があったとします。
<div class="wrapper">
<div class="layout">
<main class="main">
メインコンテンツ
</main>
<aside class="sidebar">
サイドバー
</aside>
</div>
</div>
stickyは .sidebar に指定しています。
.sidebar {
position: sticky;
top: 20px;
}
ところが、少し外側の .wrapper にこんな指定があったとします。
.wrapper {
overflow: hidden;
}
この overflow: hidden が、stickyの動きに影響することがあります。
stickyは、スクロールの仕組みを持つ直近の祖先との関係で動きます。そのため、例えば次の指定が親や祖先要素にないか確認します。
overflow: hidden;
overflow: auto;
overflow: scroll;
ここで少しやっかいなのが、stickyのすぐ上の親だけを確認すればいいわけではないことです。
DevToolsでsticky要素を選んだら、親、そのまた親と必要に応じて上へたどっていきます。
「stickyのCSSは合っているのに、なんで動かないんだろう?」というときに、何階層か上の要素で原因が見つかることは珍しくありません。
overflow-x: hidden だけでも確認する
ここは個人的にも見落としやすいところです。
横スクロールを防ぐために、次の指定を使うことがあります。
body {
overflow-x: hidden;
}
見た感じでは、「横方向だけだから、縦方向のstickyには関係なさそう」と思いますよね。
ただ、overflow-x に hidden、scroll、auto などが指定され、overflow-y が visible の場合、overflow-y の計算値は auto になります。
つまり、「縦方向には何も指定していないから大丈夫」とは限りません。
overflow だけで検索して終わらない
stickyが効かないときは、overflow だけでなく、overflow-x と overflow-y まで確認してみてください。
overflow: hidden を消せないなら clip も選択肢
はみ出した要素を隠すために overflow: hidden を使っている場合、用途によっては overflow: clip が選択肢になります。
.wrapper {
overflow: clip;
}
overflow: clip もはみ出した内容を切り取りますが、hidden と違ってスクロールコンテナを作りません。
ただし、私は overflow: hidden を見つけたからといって、すぐ全部 clip に変更することはしません。
まず、「このoverflowは、そもそも何のために入っているんだろう?」を確認します。
stickyだけ直って別のところが使いづらくなった、では意味がないので、周りへの影響まで見ながら変更するのが安心です。
原因3:stickyが動ける高さがない
次に確認したいのが、stickyを囲んでいる要素の高さです。
stickyは、親要素を無視してページの最後までずっと付いてくるわけではありません。
<div class="sidebar-wrap">
<aside class="sidebar">
サイドバー
</aside>
</div>
.sidebar {
position: sticky;
top: 20px;
}
CSSだけを見ると問題なさそうですが、.sidebar-wrap と .sidebar の高さがほぼ同じなら、stickyが動ける場所がほとんどありません。
stickyには動ける範囲が必要
「どこで貼り付くか」だけでなく、「どこまで動けるか」も確認する。ここが分かると、途中でstickyが止まるケースも理解しやすくなります。
stickyが効かないときは、「CSSは合っているか?」だけではなく、「この要素が動ける余白はあるか?」も見てみてください。
原因4:sticky要素そのものが高すぎる
反対に、sticky要素そのものが大きすぎる場合もあります。
ブログのサイドバーなら、プロフィール、カテゴリ、人気記事、バナー、お問い合わせなどを全部まとめてstickyにしているケースです。
.sidebar {
position: sticky;
top: 20px;
}
.sidebar 自体が表示領域より高ければ、すべてを見せたままきれいに追従させるのは難しくなります。
そんな場合は、サイドバー全体ではなく、本当に追従させたい部分だけを分ける方法もあります。
<aside class="sidebar">
<div class="sidebar__normal">
...
</div>
<div class="sidebar__sticky">
...
</div>
</aside>
.sidebar__sticky {
position: sticky;
top: 20px;
}
CSSだけを見るのではなく、「そもそも、どこまでstickyにする必要がある?」と考え直すと、レイアウト自体がすっきりすることもあります。
原因5:FlexboxやGridの stretch で高さが伸びている
2カラムレイアウトでstickyを使うときに、もうひとつよく確認するのがFlexboxやGridです。
ポイントは、sticky要素の高さが、自分の想像以上に伸びていないかです。
Flexboxの場合
例えば、こんな2カラムレイアウトです。
.layout {
display: flex;
}
.main {
flex: 1;
}
.sidebar {
width: 300px;
position: sticky;
top: 20px;
}
Flexboxでは、交差軸方向の配置によって子要素が高さいっぱいに伸びることがあります。
メインコンテンツが長いと、sidebarまでその高さに合わせて伸びていて、結果としてstickyが動ける範囲がなくなっていることがあります。
その場合は、例えば次のように調整します。
.layout {
display: flex;
align-items: flex-start;
}
sticky要素だけを調整するなら、
.sidebar {
position: sticky;
top: 20px;
align-self: flex-start;
}
ここで覚えておきたいのは、「Flexboxだからstickyが使えない」のではないということです。
Flexboxによってsticky要素が今どんな高さになっているのかを見るのが先です。
Gridの場合
CSS Gridも考え方は同じです。
.layout {
display: grid;
grid-template-columns: 1fr 300px;
gap: 40px;
}
.sidebar {
position: sticky;
top: 20px;
}
Gridでも、配置条件によってアイテムが高さ方向へ伸びることがあります。
その場合は、次の指定を検討します。
.sidebar {
position: sticky;
top: 20px;
align-self: start;
}
FlexboxでもGridでも、私はまずDevToolsで実際の要素サイズを見ます。
「思っていたよりsidebarがかなり縦に伸びている」と分かれば、原因もかなり絞れます。
原因6:実はstickyしているけれど、ヘッダーの裏に隠れている
最後は、stickyそのものはちゃんと効いているケースです。
例えば上部に固定ヘッダーがあるとします。
.site-header {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 80px;
}
そこへ、次のstickyを指定します。
.sidebar {
position: sticky;
top: 0;
}
sidebarはちゃんと画面上端にstickyします。でも、その場所には高さ80pxの固定ヘッダーがあります。
そのため、stickyしているのにヘッダーの裏へ入り、「効いていないように見える」ことがあります。
この場合は、ヘッダーの高さを考慮して位置を調整します。
.sidebar {
position: sticky;
top: 100px;
}
要素同士が重なっているなら、必要に応じて z-index も確認します。
.sidebar {
position: sticky;
top: 100px;
z-index: 1;
}
z-index: 9999 を足す前に
まず、「stickyしていない」のか、「stickyしているけれど見えない」のかを切り分けます。そのほうが、あとでCSSがややこしくなりません。
私がstickyが効かないときに確認している順番
ここまでいろいろな原因を紹介しましたが、実際の制作中に全部を一度に疑う必要はありません。
私の場合は、だいたい次の順番で確認しています。
position: stickyが本当に適用されているか
DevToolsで、別のCSSに上書きされていないか確認します。topが入っているか
ここまではすぐに確認できます。- 親から上へ
overflowをたどるoverflowだけでなく、overflow-xとoverflow-yまで見ます。 - stickyが動ける高さを見る
sticky要素と親要素の高さがほぼ同じになっていないか確認します。 - sticky要素自身の高さを見る
表示領域より大きくなっていないか確認します。 - Flexbox・Gridなら
stretchを確認する
DevToolsで実際の高さを見ると分かりやすいです。 - 最後に重なりを見る
stickyは動いているのに、固定ヘッダーなどの裏へ入っていないか確認します。
この順番で見るようにしておくと、「検索して出てきたCSSを、とりあえず全部足してみる」という状態になりにくくなります。
長くCSSを書いていても、原因が何階層か上の要素にあると一瞬迷うことはあります。そんなときほど、ひとつずつ切り分けたほうが結果的には早く直せます。
CSSを増やす前に、原因を切り分ける
Web制作では、コードをたくさん書くことより、原因を見つけて、必要なところだけ直すことのほうが大事な場面も多いです。stickyも、指定した要素自身だけでなく周りのレイアウトを見ると原因が見つかりやすくなります。
参考情報
今回の記事では、position: sticky、overflow、Flexbox・Gridの配置について、MDN Web Docsの仕様も確認しています。
まとめ
position: sticky が効かないときは、stickyの書き方そのものが間違っているとは限りません。
まずは top を確認して、問題がなければ親・祖先要素の overflow、高さ、Flexbox・Grid、最後に重なりという順番で見ていくと原因を絞り込みやすくなります。
stickyが効かないときの確認順
私の場合、top に問題がなければ、次はDevToolsで親要素をひとつずつたどりながら overflow を確認します。
stickyは便利なCSSですが、周りのレイアウトとの関係で動くので、原因が少し離れた場所にあることがあります。
「stickyが効かない」ときは、新しいCSSを足す前に、一度その要素の周りを見てみてください。意外とシンプルなところで原因が見つかるかもしれません。
Contact
細かなCSSの実装も、
サイト全体を見ながら考えます
ホームページは、完成した画面だけを見ると同じように見えても、HTMLやCSSの組み方はサイトによってかなり違います。
stickyひとつでも、「とりあえず動けばOK」にするのか、周りのレイアウトやスマホ表示、今後の更新まで考えて組むのかで、あとから修正するときの扱いやすさは変わります。
KU NEL WEBLEでは、見た目を整えるだけではなく、「あとで触る人が困らないか」「別の画面幅でも無理がないか」「必要以上に複雑なCSSになっていないか」といったところまで見ながら実装しています。
こんなご相談も大丈夫です
ご相談いただくときに、CSSやWordPressのことを詳しく知っている必要はありません。
「なんとなくここが使いづらい」「今のサイト、このままで大丈夫かな?」くらいのところからでも大丈夫です。制作する本人が直接お話を伺いながら、必要なところから一緒に整理します。
小さな違和感をひとつずつ直していくことも、ちゃんとしたホームページをつくる仕事のひとつだと思っています。
Webサイト制作・リニューアルのご相談
見た目だけでなく、
更新しやすいWebサイトを制作します。
KU NEL WEBLEでは、デザイン・コーディング・WordPress実装・スマホ対応・アクセシビリティまで含めて、長く使いやすいWebサイト制作を行っています。新規制作やリニューアルをご検討中の方は、お気軽にご相談ください。