スタイルシートだけで サイド部分をスクロール固定する。
ホームページは、2列構成になるケースがあります。
メインカラムと、サイドカラムです。
たいていメインカラムのほうが縦に長く、サイドカラムは上へ流れて行ってしまいます。
その場合、サイドカラムはほとんど見てもらえなくなります。
これを何とかするために、サイドカラムを位置固定する方法があります。
特定位置になったら固定し、フッターが来たら固定を解除するものです。
今まではJqueryで実装していましたが、スタイルシートだけで実現できることがわかりました。
忘備録として記録いたします。
まずはできたものがこちら
右サイド部分がスタイルシートだけで固定できています。
いったいどうやっているのでしょうか?
position:sticky; を使えば簡単に実現できます。
position:は、fixed、absoluteなどを指定します。
その仲間で、stickyがあります。
意味合い的には、「特定位置になったら固定」というものです。
なんとも便利なスタイルシートです。
基本構成
基本的な構成は次のようになります。
いわゆるよくあるパターンです。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<body> <article> <main> メインカラム </main> <div id="side"> サイド部分 </div> </article> </body> |
基本スタイルシートはこのようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
article { display: flex; justify-content: space-between; align-items: flex-start; } #main { width: 76%; } #side { width: 20%; position: sticky; top: 20px; } |
基本これだけでサイドカラムがスクロール固定されます。
全体枠(article)は必ずflexにする
2カラム構成にする場合、「float」を使う方法がありますが、今回はNGです。
なぜならば、ちゃんと動作しなくなるためです。
サイドカラムを包括するタグには必ずflexで2カラム構成にします。
justify-content: space-between;の意味
これは、flexに対して、横位置を均等割り当てをするという意味です。
今回は、メインカラムは一番左よせ、サイドカラムは一番右よせにしたいので、「均等割り当て」で配置しています。
こちらの解説をみると、わかりやすいです。
align-items: flex-start;の意味
これは、flexに対して縦位置を上に割り当てるという意味です。
今回は、サイドカラムが画面の一番上に来たら固定するため、上位置を指定しています。
こちらの解説をみると、わかりやすいです。
サイド部分(#side)はstickyとtopを指定する
実際に固定化する部分に「sticky」を設定します。
さらに、topを数字で指定します。
topを指定しないとうまく動きません。
ちなみに、必ず0にする必要はなく、固定化する位置によって変えてOKです。
ソースはこちら
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
<!doctype html> <html> <head> <meta charset="shift_jis"> <title>サイド固定(上固定)</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style type="text/css"> html { scroll-behavior: smooth; } body { margin: 0px; padding: 0px; text-align: center; } header { color: #FFF; background-color: #333; padding-top: 50px; padding-bottom: 50px; } footer { color: #FFF; background-color: #333; padding-top: 100px; padding-bottom: 100px; } article { display: flex; justify-content: space-between; align-items: flex-start; width: 1200px; margin-right: auto; margin-left: auto; padding-top: 30px; padding-bottom: 30px; } #main { width: 860px; } #side { width: 300px; position: sticky; top: 20px; } article section { padding-top: 200px; padding-bottom: 200px; border: 3px solid #CCC; margin-bottom: 30px; } #side section { padding-top: 100px; padding-bottom: 100px; background-color: #FFC; } @media screen and (max-width:767px) { header { padding-top: 20px; padding-bottom: 20px; } article { display: block; width: auto; padding-top: 20px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; } #main { width: auto; } #side { width: auto; } article section { margin-bottom: 10px; } } </style> </head> <body> <header>ヘッダー部</header> <article> <div id="main"> <section>セクション01</section> <section>セクション02</section> <section>セクション03</section> <section>セクション04</section> <section>セクション05</section> </div> <div id="side"> <section>サイド部分01<br>上固定されます</section> <section>サイド部分02</section> <section>サイド部分03</section> <section>サイド部分04</section> </div> </article> <footer>フッター部</footer> </body> </html> |
これってサイド部が上固定だけど、下固定にはできないのか?
サンプルは、サイド部分が上固定になっています。
ですが、下固定にしたいケースもあります。
それって実現できないのか、調べてみました。
調べてみたら、スタイルシートのオプションを変えるだけで実現できることがわかりました。
サイド部分下固定のサンプル
右サイド部分が下固定で動きます。
下固定にする方法
下固定にするには、2カ所変更すれば実現できます。
(1)article のalign-items: flex-start;をalign-items: flex-end;にする
包括部分(article)をalign-items: flex-end;にすれば「下位置合わせ」になります。
flex-startが基準位置上に対し、flex-endは基準位置下になります。
(2)#sideのtop を削除し、bottomを追加する。
stickyを指定しているサイド部分には、スタイルシートでtopを指定します。
これを削除し、代わりにbottomを指定します。
下基準にするので、bottomです。
この2カ所変えるだけで下固定に代わります。
下固定のソースはこちら
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
<!doctype html> <html> <head> <meta charset="shift_jis"> <title>サイド固定(下固定)</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style type="text/css"> html { scroll-behavior: smooth; } body { margin: 0px; padding: 0px; text-align: center; } header { color: #FFF; background-color: #333; padding-top: 50px; padding-bottom: 50px; } footer { color: #FFF; background-color: #333; padding-top: 100px; padding-bottom: 100px; } article { display: flex; justify-content: space-between; align-items: flex-end; width: 1200px; margin-right: auto; margin-left: auto; padding-top: 30px; padding-bottom: 30px; } #main { width: 860px; } #side { width: 300px; position: -webkit-sticky; position: sticky; bottom: 20px; } article section { padding-top: 200px; padding-bottom: 200px; border: 3px solid #CCC; margin-bottom: 30px; } #side section { padding-top: 100px; padding-bottom: 100px; background-color: #FFC; } @media screen and (max-width:767px) { header { padding-top: 20px; padding-bottom: 20px; } article { display: block; width: auto; padding-top: 20px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; } #main { width: auto; } #side { width: auto; } article section { margin-bottom: 10px; } } </style> </head> <body> <header>ヘッダー部</header> <article> <div id="main"> <section>セクション01</section> <section>セクション02</section> <section>セクション03</section> <section>セクション04</section> <section>セクション05</section> </div> <div id="side"> <section>サイド部分01</section> <section>サイド部分02</section> <section>サイド部分03</section> <section>サイド部分04<br>固定されます</section> </div> </article> <footer>フッター部</footer> </body> </html> |
次のような場合はちゃんと動かないので注意です。
stickyは便利ですが、文法にうるさいです。
次の場合は動作しないので注意が必要です。
- 親要素に「overflow:hidden;」を指定している
- align-items: stretch;(デフォルト)になっている
動かない理由はほかにもありますが、大きくはこの2つです。
position指定は、もともと癖が強いので、使い場合には文法をよく確認する必要があります。
まずカラム分けは、float指定からflex指定に変えることこちからが大事なんだと気づきました。