dポイントプレゼントキャンペーン実施中!

2カラムレイアウトで良くあるページをスクロールしていくと
「サイドナビの"途中"で固定され、フッター直前で固定解除」されるのを
jQueryで実現したいんです。

「サイドナビの途中で固定(でもフッターに重なる)」と
「最初から固定されてるけどフッター手前で固定解除」という
2種類のjQueryを見つけたので、その2つを合体して
上記の希望する動作にしたいんです。

以下2つのコードです。

■サイドナビの途中(class="kotei")で固定
$(function(){

var nav = $('.kotei'),
offset = nav.offset();

$(window).scroll(function(){
if($(window).scrollTop() > offset.top) {
nav.addClass('fix-on');}
else {nav.removeClass('fix-on');}});

});

※スタイルシート
.fix-on { position : fixed; top : 0; z-index : 10000; }


■フッター(id="footer")手前で固定解除

window.onload=function(){

var onoff =
$("#fotter").offset().top - $(window).height() + 0; //フッターまでの高さを計算=onoff

$(window).scroll(function(){
if($(window).scrollTop() < onoff) //onoffの高さがスクロール量より大きい場合
$(".kotei").addClass("fix-on");   //class="kotei"にfix-onを付与する
else
$(".kotei").removeClass("fix-on"); //それ以外はfix-onを解除
});

}


■自力で合体したけどうまく動作しなかったコード
$(document).ready(function(){

var nav = $(".kotei"),
offset = nav.offset(),
onoff =
$("#footer").offset().top - $(window).height() + 0;

$(window).scroll(function(){

if($(window).scrollTop() > offset.top) {
nav.addClass("fix-on");}

else if($(window).scrollTop() > onoff) {
nav.removeClass("fix-on");}

else {nav.removeClass("fix-on");}});

});

オフセットを2重に設定したのが競合しているのでしょうか。。?



※※※補足※※※現在のホームページレイアウト(html)

<body>
<#wrap>
<#content>

</#content>
</#wrap>

<#header>

</#header>

<#side-nav>
<li>略</li>
</#side-nav>

<#footer>
</body>


普通の2カラムと違うところは<#header>をposition:absoluteでトップに絶対配置している事、
<#content>と<#side-nav>は<#header>分のマージンを上部に取っている事、
<#wrap>は<#content>のみを囲っている事です。

■ヘッダー■←:absoluteでトップに
□□■■■■
□□■コン■
ナビ■テン■←maegin-top+コンテンツだけにwrap
□□■ツ■■
□□■■■■
■フッター■

2つの条件を両方満たしたjQueryを見つけたんですが、
<wrap>で<side-menu>と<content>の両方を包んでいないと
既存のjQueryでは動作しないようです。

それで2つのjQuertを合体したいという経緯に至りました。

A 回答 (2件)

A No1です。



お礼を読みましたが、やりたいことがよくわかりません。
ご質問文の図解とhtmlの構成を参考に作成してみたのですが・・・

>position:absoluteで絶対位置指定しておかないと機能しないのですね。
最初にご提示のようなposition:fixでの方法もあるかと思いますが、結局、この指定と違う動作をさせる時に、position:absoluteなどにしているので、単純化しているだけです。

>コードの意味を調べたり、~~
数行のコードなので、大して難しくはないと思いますが、念のため説明しておきますと、
移動したい部分(今回の場合は#side-navと解釈)の縦の位置指定をすれば良いだけですので、移動可能な範囲(縦位置の最小値、最大値)を求めておいて、その中で位置を指定しているだけです。計算上範囲からはみ出した場合は、最大値(又は最小値)にセットしているだけです。


よくわかりませんが、こういうこと?
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="ja">
<head><title>test</title>
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript">

<style type="text/css">
html, body{ margin:0; padding:0; }
.header{ height:100px; background-color:#aff; }
.content{ height:1000px; background-color: #ddd; }
.footer{ clear:both; height:50px; background-color:#ffa; }

#side-bar{
width:150px;
float:left;
background-color: #ffa;
}

#side-nav{
position:absolute;
width:150px; left:0;
background-color:#faf;
list-style-type:none;
margin:0; padding:0;
}
</style>

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7. …

<script type="text/javascript">
$(function(){
var nav = $("#side-nav"); //移動する部分の要素を取得

//位置調整関数
var adjust = function(){
var sTop = $(window).scrollTop(); //全体のスクロール量
var sMin = $("#side-bar").offset().top + $("#side-bar").height(); //縦位置の最小値
var sMax = $(".footer").offset().top - nav.height(); //縦位置の最大値
nav.css("top", Math.min(Math.max(sTop, sMin), sMax)); //要素の縦位置を設定
}

//スクロール時、リサイズ時のイベント設定
$(window).scroll(function(){ adjust(); })
.resize(function(){ adjust(); });

//初期設定での位置調整表示
adjust();
});
</script>
</head>
<body>

<div class="header">
header略
</div>

<div id="side-bar">
<ul>
<li>スクロールされるメニュー1</li>
<li>スクロールされるメニュー2</li>
<li>スクロールされるメニュー3</li>
</ul>
</div>
<ul id="side-nav">
<li>navi1 略</li>
<li>navi2 略</li>
<li>navi3 略</li>
</ul>


<div class="content">
content略
</div>
<div class="footer">
footer
</div>

</body>
</html>
    • good
    • 0
この回答へのお礼

2度もご回答ありがとうございます。

今回ご提示下さったコードで正常に動作させる事が出来ました。

配布されているjQueryをそのまま使っているような人間ですので
数行の簡単なコードでも//補足コメントはありがたいです。


ネットで探し回ったコードよりもシンプルな記述ですし、
希望していた動作通りに機能するので非常に感謝しております。

ご親切にありがとうございました。

お礼日時:2013/07/13 08:15

回答がないみたいなので…




headerとfooterにかからない範囲で、side-navを上下に移動させたいということと解釈しました。
headerをabsoluteにする必然性がないのと、どうせスクリプトに頼ることになるのですから、side-navだけをabsoluteにしておいて、スクリプトで上下に移動するという方式にしています。
最初に計算をしておいても良いのですが、ブラウザのサイズをリサイズすると計算値が変わる可能性があるので、都度計算するようにしています。

*HTML4.01になっていますので、HTML5にする場合は適宜修正を。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="ja">
<head><title>test</title>
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript">

<style type="text/css">
html, body{ margin:0; padding:0; }
.header{ height:100px; background-color:#aff; }
.content{ height:1000px; margin-left:100px; }
.footer{ height:50px; background-color:#ffa; }

#side-nav{
position:absolute;
width:100px;
top:100px; left:0;
background-color:#faf;
list-style-type:none;
margin:0; padding:0;
}
</style>

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7. …
<script type="text/javascript">
$(function(){
var nav = $("#side-nav");
var adjust = function(){
var sTop = $(window).scrollTop();
var sMin = $(".header").height()
var sMax = $(".footer").offset().top - nav.height();
nav.css("top", Math.min(Math.max(sTop, sMin), sMax));
}

$(window).scroll(function(){ adjust(); })
.resize(function(){ adjust(); });
});
</script>
</head>
<body>

<div class="header">
header略
</div>

<ul id="side-nav">
<li>navi1 略</li>
<li>navi2 略</li>
<li>navi3 略</li>
</ul>

<div class="content">
content略
</div>
<div class="footer">
footer
</div>

</body>
</html>
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
ご返事遅くなってしまいスミマセン。

ご提案下さったコードを元に
コードの意味を調べたり、
色々いじくって自分なりに検証しておりました。

position:absoluteで
絶対位置指定しておかないと機能しないのですね。


サイドナビの途中から固定したいもので、

<div id="side-bar">
 <ul>
 <li>スクロールされるメニュー1</li>
 <li>スクロールされるメニュー2</li>
 <li>スクロールされるメニュー3</li>
 </ul>
 <ul id="side-nav">
 <li>navi1 略</li>
 <li>navi2 略</li>
 <li>navi3 略</li>
 </ul>
</div>

こんな風にDIVで囲ってみると、
スクロールされるメニューと重なってしまって



<div id="side-bar">
<ul>
<li>スクロールされるメニュー1</li>
<li>スクロールされるメニュー2</li>
<li>スクロールされるメニュー3</li>
</ul>
 <div id="relative">
 <ul id="side-nav">
 <li>navi1 略</li>
 <li>navi2 略</li>
 <li>navi3 略</li>
 </ul>
 </div>
</div>

と<ul id="side-nav">の親要素として
さらにDIVを追加し、position:relative;を指定すると

今度はside-nav自体が表示されなくなったりでお手上げ状態なんです。。


どうも相談内容が悪かったのか、なかなか回答も頂けないので
半ば諦めモードなんですが

締め切らずにもう少しだけ待ってみようと思います。


ご回答ありがとうございました。

お礼日時:2013/07/12 06:57

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!