ページをスクロールするとサイドバーが画面上部に固定されるコードを書いてみました。
デモでは、サイドバーの項目が1~40番目までスクロールされたら、サイドバーが固定されるようになっています。
このサイトでもアレンジを加えて利用していますので(2015年3月現在)、動きを確認してみてください。
このサイドバーの概要
以下の条件で作成しました。
- 一定の長さをスクロールすると、サイドバーが画面の上部を基準に固定される
- ページの最後までスクロールしたら、サイドバーは親要素の下部(フッターの上)に固定される
- 横幅が特定のサイズ以下になったら、サイドバーが固定されるのを解除する
- メインエリアの方がサイドバーより短かったら固定しない
html
htmlでキモなのが、固定したいサイドバーの要素を覆う要素が必要ということです。
ここでは#side-wrapになります。これがないとサイドバーをposition:fixedにした時にsafariでは基準値が左上になってしまい、メインエリアに重なってしまいます。
<header id="header"> <h1>タイトル</h1> </header> <div id="wrap" class="clearfix"> <div id="main-wrap"> <div id="main"> <p>メインエリア</p> </div> </div> <!-- #side-wrap がないとsafariで表示が崩れます --> <div id="side-wrap"> <div id="side"> <ol> <li>サイドバーのリスト</li> <li>サイドバーのリスト</li> <!--中略--> <li>サイドバーのリスト</li> <li>サイドバーのリスト</li> </ol> </div> </div> <!--/ #wrap--></div>
CSS
#wrapが#sideの親要素になるよう、position: relative; にします。
#sideは display:inline-block; で回りこむようにします。
34~44行は、jQueryで付け替えるクラス名のプロパティを指定しています。
レスポンシブにも対応していますが、メディアクエリを使用せずにCSSを書けば、固定されたレイアウトも可能です。
/*PC用のCSS*/ @media screen and (min-width: 641px) { h1 { padding: 80px 0 0; font-size:30px; } #header, #footer { height: 200px; text-align: center; max-width: 1000px; margin: 10px auto; } #wrap { position: relative; max-width: 1000px; margin: 0 auto; } #main-wrap { float: left; max-width: 700px; width: 70%; } #main { margin: 0 20px 0 0; height: 8000px; } #side { max-width: 300px; width: 30%; display:inline-block; background: #ddd; } .fixed-side { position: fixed; top:0; } .bottom-side { position: absolute; bottom: 0; } .static-side { position: static; } } /*SP用のCSS*/ @media screen and (min-width: 0px) and (max-width: 640px) { h1 { padding: 30px 10px; font-size:20px; } #main { margin: 10px; height: 1000px; } #side { padding: 5px; display: block; margin: 10px; background: #ddd; } }
jQuery
サイドバーの固定を解除するタイミングなどは、長さによって変えたほうが良い場合があるので、適宜変数の値を調整してみてください。
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script> $(function(){ //各エリアの高さを取得 var pageH = $('body').height(); var windowH = $(window).height(); var mainH = $('#main').outerHeight(); var sideH = $('#side').outerHeight(); var headerH = $('#header').outerHeight(); var footerH = $('#footer').outerHeight(); //サイドバーの高さ+ヘッダーの高さ var viewSide = sideH + headerH ; //サイドバーを固定する高さ var fixedSide = headerH + sideH - windowH; //ページを最後までスクロールした時の高さ var scrollBottom = pageH - windowH - footerH ; //ウィンドウサイズを変更した時にウィンドウの高さを取得し直す $(window).resize(function(){ windowH = $(this).outerHeight(); windowW = $(this).outerWidth(); }); $(window).scroll(function(){ //スクロールの値を取得 var scrollTop = $(this).scrollTop(); $('.scroll').text('スクロール値:' + $(this).scrollTop()); /*ウィンドウサイズよりサイドバーの方が長く、 尚かつサイドバーの最後までスクロールされたら*/ if(windowH < viewSide && scrollTop > fixedSide ) { //サイドバーを固定 $('#side').addClass('fixed-side'); }else{ //条件から外れたらサイドバーの位置を初期値にする $('#side').removeClass('fixed-side'); } //ページの最後までスクロールされたら if( scrollTop > scrollBottom){ //#wrapの下を基準としてサイドバーを絶対配置 $('#side').removeClass('fixed-side'); $('#side').addClass('bottom-side'); } else{ $('#side').removeClass('bottom-side'); } //メインエリアの方がサイドバーより短かったら if( mainH < sideH ){ //サイドバーの位置を初期値にする $('#side').addClass('static-side'); } }); }); </script>