ページをスクロールするとサイドバーが画面上部に固定されるコードを書いてみました。
デモでは、サイドバーの項目が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>