質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.61%

  • JavaScript

    15970questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

サイドメニューが下まで行ったらそこで固定するJS

受付中

回答 3

投稿 編集

  • 評価
  • クリップ 3
  • VIEW 2,308

KSS

score 12

下記リンクを参考にスクロールを作成したのですが
メイン部分がJSにより長さが変わることがある(例:クリック押下でheightが伸びる等)ため、うまく動作しません。

理想としては、サイドバーは常に上に固定され、かつメイン部分のボトムまできたら下に固定されることなのですが、、、、
メインの長さが動的に変化する場合、どのように対処したらよいでしょうか。

> リンク


$(window).load(function () {
 
      //該当のセレクタなどを代入
       
      var mainArea = $("#main"); //メインコンテンツ
      var sideWrap = $("#sideWrap"); //サイドバーの外枠
      var sideArea = $("#side"); //サイドバー
 
      /*設定ここまで*/
       
      var wd = $(window); //ウィンドウ自体
       
       
      //メインとサイドの高さを比べる
       
      var mainH = mainArea.height();
      var sideH = sideWrap.height();
       
       
      if(sideH < mainH) { //メインの方が高ければ色々処理する
             
            //サイドバーの外枠をメインと同じ高さにしてrelaltiveに(#sideをポジションで上や下に固定するため)
            sideWrap.css({"height": mainH,"position": "relative"});
       
            //サイドバーがウィンドウよりいくらはみ出してるか
            var sideOver = wd.height()-sideArea.height();
       
            //固定を開始する位置 = サイドバーの座標+はみ出す距離
            var starPoint = sideArea.offset().top + (-sideOver);
             
            //固定を解除する位置 = メインコンテンツの終点
            var breakPoint = sideArea.offset().top + mainH;
       
            wd.scroll(function() { //スクロール中の処理
                   
                  if(wd.height() < sideArea.height()){ //サイドメニューが画面より大きい場合
                        if(starPoint < wd.scrollTop() && wd.scrollTop() + wd.height() < breakPoint){ //固定範囲内
                              sideArea.css({"position": "fixed", "bottom": "20px"}); 
       
                        }else if(wd.scrollTop() + wd.height() >= breakPoint){ //固定解除位置を超えた時
                              sideArea.css({"position": "absolute", "bottom": "0"});
       
                        } else { //その他、上に戻った時
                              sideArea.css("position", "static");
       
                        }
       
                  }else{ //サイドメニューが画面より小さい場合
                   
                        var sideBtm = wd.scrollTop() + sideArea.height(); //サイドメニューの終点
                         
                        if(mainArea.offset().top < wd.scrollTop() && sideBtm < breakPoint){ //固定範囲内
                              sideArea.css({"position": "fixed", "top": "20px"});
                               
                        }else if(sideBtm >= breakPoint){ //固定解除位置を超えた時
                         
                              //サイドバー固定場所(bottom指定すると不具合が出るのでtopからの固定位置を算出する)
                              var fixedSide = mainH - sideH;
                               
                              sideArea.css({"position": "absolute", "top": fixedSide});
                               
                        } else {
                              sideArea.css("position", "static");
                        }
                  }
                         
             
            });
       
      } 
 
});
```
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+1

要素のリサイズイベントを取得出来るjQueryプラグインがある様です。
次のリンクなどが参考になると思います。

要素のリサイズイベントを取得 - Qiita

要素の中身が変更されたことを知る - Qiita

Ben Alman » jQuery resize event
※上記のQiitaで紹介されているものとは別のプラグインですが、参考になるのではないでしょうか

あとは最初のリンクで紹介されているプラグインexResizeを利用して次の様にすると、変化した高さの分も考慮された動作が得られるのではないでしょうか。
// #mainがリサイズされた時
$("#main").exResize(function() {
    // メインの高さを取得し直す
    mainH = mainArea.height();
}

追記
リサイズイベントではなくスクロールイベント内で処理しても良いかもしれません。
wd.scroll(function() {
    // #mainの高さがmainHよりも高くなった時
    if ( mainArea.height() > mainH ) {
        // メインの高さを取得し直す
        mainH = mainArea.height();
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/06/18 10:15

    事情によりプラグインを追加することができない条件となっており、なんとか今のままでの対応を考えております。

    また、追記にありました対応も実験済みですがスクロールがヘッダーに合わせようとすることで動きがカクカクしてしまいました。

    キャンセル

0

メイン部分がJSにより長さが変わることがある(例:クリック押下でheightが伸びる等)

上記のタイミングで下記の位置や高さ、画面ロードにのみしているスクロール時の処理を最定義してやれば適切に動くと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/06/18 08:15

    いかんせんクリック処理が多いため、スクロール時に処理しようとしています

    キャンセル

0

こんな感じでしょうか?
スクロール時の処理の中に高の取得や判別の部分を入れました。
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
  <meta charset="utf-8">
  <title></title>
  <style>
    body{text-align:center; margin:0; padding:0;}
    .demoLink{margin:15px 0;}
    p{font-weight:bold;font-size:20px; color:#fff; padding:10px; line-height:1.5; margin:0;}
    #header{width:1000px; margin:0 auto 30px;background:#666; padding:30px 0;}
    #contents{width:1000px; margin:0 auto 30px; overflow:hidden;}
    #main{width:720px; float:left;background:#aaa;}
    #sideWrap{width:260px; float:right;position:relative;border-bottom:2px solid red;}
    #side{width:260px; background:#eee;}
    #side p{color:#333;font-size:15px; border:1px solid #ccc;}
    #footer{background:#444;padding:20px 0; height:600px;}
    #nobiru{background:#000; height:30px; color:#fff; text-align:center; transition:height 0.5s;}
    #nobiru.nobita{height:500px;}
  </style>
  <script>
    $(window).load(function () {
 
      //該当のセレクタなどを代入
       
      var mainArea = $("#main"); //メインコンテンツ
      var sideWrap = $("#sideWrap"); //サイドバーの外枠
      var sideArea = $("#side"); //サイドバー
 
      /*設定ここまで*/
       
      var wd = $(window); //ウィンドウ自体
      
      var sideOffsetTop = sideArea.offset().top; //サイドバーの座標
      
      
      function setSidePosition(){
       
        //メインとサイドの高さを比べる
        var mainH = mainArea.height();
        var sideH = sideArea.height();
        
        if(sideH < mainH) { //メインの方が高ければ色々処理する
             
          //サイドバーの外枠をメインと同じ高さにしてrelaltiveに(#sideをポジションで上や下に固定するため)
          sideWrap.css({"height": mainH,"position": "relative"});

          //サイドバーがウィンドウよりいくらはみ出してるか
          var sideOver = wd.height()-sideArea.height();

          //固定を開始する位置 = サイドバーの座標+はみ出す距離
          var starPoint = sideOffsetTop + (-sideOver);

          //固定を解除する位置 = メインコンテンツの終点
          var breakPoint = sideOffsetTop + mainH;
        }else{
          //メインの方が高くなければsideWrapの高さをリセット
          sideWrap.css({"height": "auto","position": "static"});
        }
        
        if(wd.height() < sideArea.height()){ //サイドメニューが画面より大きい場合
          if(starPoint < wd.scrollTop() && wd.scrollTop() + wd.height() < breakPoint){ //固定範囲内
            sideArea.css({"position": "fixed", "bottom": "20px"}); 

          }else if(wd.scrollTop() + wd.height() >= breakPoint){ //固定解除位置を超えた時
            sideArea.css({"position": "absolute", "bottom": "0"});

          } else { //その他、上に戻った時
            sideArea.css("position", "static");

          }

        }else{ //サイドメニューが画面より小さい場合

          var sideBtm = wd.scrollTop() + sideArea.height(); //サイドメニューの終点

          if(mainArea.offset().top < wd.scrollTop() && sideBtm < breakPoint){ //固定範囲内
            sideArea.css({"position": "fixed", "top": "20px"});

          }else if(sideBtm >= breakPoint){ //固定解除位置を超えた時

            //サイドバー固定場所(bottom指定すると不具合が出るのでtopからの固定位置を算出する)
            var fixedSide = mainH - sideH;

            sideArea.css({"position": "absolute", "top": fixedSide});

          } else {
            sideArea.css("position", "static");
          }
        }
        
      }
      
      wd.on("scroll",function(e){
        setSidePosition(); //スクロールで実行
      });
      setSidePosition(); //最初にも1回実行
      
    });
    
    
    $(function(){
      //mainAreaが伸びたり縮んだりするボタン
      $("#nobiru").click(function(){
        $(this).toggleClass("nobita");
      });
    });
  </script>
</head>
<body>
<div id="header">
  <p>私はヘッダー。</p>
</div><!-- / #header -->
 
<div id="contents">
 
  <div id="main">
    <p style="height:700px">それがしがメインエリア。</p>
    <div id="nobiru">ココ押すと伸びたり縮んだり</div>
  </div><!-- / #main -->

  <div id="sideWrap">
    <div id="side">
      <p style="height:500px">我はサイドバー。</p>
    </div><!-- / #side -->
  </div><!-- / #sideWrap -->
 
</div><!-- / #contents -->
 
<div id="footer">
  <p>ワタスはフッター。</p>
</div><!-- / #footer -->
</body>
</html>

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/06/19 19:31

    親切にすべて記載していただき、ありがとうございます。
    しかし。。。残念ながらスクロールの終わりがヘッダー部分を超えると削除されてしまいました。

    もしかしたら今の構成自体がよくないのかもしれません。。。

    キャンセル

  • 2015/06/19 19:41

    すみません。「スクロールの終わりがヘッダー部分を超える」がどういう状況かよく分からないので、もう少し説明をもらえるとありがたいです。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • JavaScript

    15970questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。