

表示位置が可変するページにて、  
スクロールしてナビの位置に来た時にウインドウ上部に固定したいと思い下記のコードを書きました。

<https://jsfiddle.net/aq8j1rLL/9/>

[code]

    $(function() {
    
      $(window).on('load resize', function() {
    
        var navScrollHeight = $('#gnav').offset().top;
    
        $(window).on('scroll', function() {
          if ($(this).scrollTop() > navScrollHeight) {
            $('#gnav').addClass('fixed');
          } else {
            $('#gnav').removeClass('fixed');
          };
        });
    
      });
    
    });
[/code]

[code]

    html,
    body {
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 0;
    }
    
    #container {
      width: 100%;
      height: 2000px;
      background-color: grey;
    }
    
    header {
      position: relative;
    }
    
    h1 {
      width: 100%;
      height: 300px;
      background-color: white;
      margin: 0;
    }
    
    #gnav {
      width: 100%;
      height: 70px;
      background-color: black;
      z-index: 1000;
    }
    
    .fixed {
      position: fixed;
      top: 0;
      left: 0;
    }
[/code]

[code]

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <div id='container'>
      <header>
        <h1></h1>
        <nav id="gnav"></nav>
      </header>
    </div>
[/code]

ナビが固定される前にウインドウの大きさを変えるとナビの位置でちゃんと固定されるのですが、  
固定された後にウインドウの大きさを変えると、いきなりナビが消えたり、別の位置で固定されたり不安定になります。

当方初心者で色々試したのですがさっぱりわかりません。

何卒ご教授の方よろしくお願いいたします。


CC BY-SA 4.0
2017-02-05T16:49:34.637
32409
2022-02-27T09:07:00.760
2019-09-15T05:45:05.750
32986
20135
question
jquery
jQueryでの可変の表示位置の取得


コメント拝見しました。元のコードを編集したものを回答として差し替えさせていただきます：

<https://jsfiddle.net/uztqeoe8/3/>

[code]

    $(function() {
      // このイベントは不要と思われます
      //$(window).on('load resize', function() {
    
      // 動的に変化しないjQueryオブジェクトはキャッシュ（変数に入れて保管）しましょう
      var $window = $(window);
      var $gnav = $('#gnav');
      var $socialLink = $('#social-link');
    
      var navScrollHeight = $gnav.offset().top;
    
      $window.on('scroll', function() {
        if ($window.scrollTop() > navScrollHeight) {
    
          $gnav.addClass('fixed');
    
          // CSS変更はなるべくJavaScriptではなくCSSで設定しましょう
    
          // こちらについては意図がよくわからなかったのでそのままにしました。同様にCSSで対応可能ならそちらをおすすめします
          // アイコンマージン追加
          $socialLink.css({
            'margin-top': '106px'
          });
        } else {
    
          $gnav.removeClass('fixed');
    
          // アイコンマージン解除
          $socialLink.css({
            'margin-top': 0
          });
        };
      });
      //});
    });
[/code]

[code]

    html,
    body {
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 0;
    }
    
    body {
      font: 12px "游ゴシック", sans-serif;
      color: black;
      position: relative;
    }
    
    div#container {
      position: relative;
      width: 100%;
      height: 100%;
    }
    
    header {
      position: relative;
      width: 100%;
      height: 100%;
      text-align: center;
      background-color: grey;
    }
    
    header.img-fixed {
      background: url("../images/photo.jpg") no-repeat;
      background-size: cover;
      background-position: center center;
      background-attachment: fixed;
    }
    
    header section {
      position: absolute;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      margin: auto;
      width: 100%;
      height: 50%;
    }
    
    header section h1 {
      width: 300px;
      height: 221px;
      text-indent: 100%;
      white-space: nowrap;
      overflow: hidden;
      background-color: black;
      background-size: 100% 100%;
      margin: 0 auto 21px;
    }
    
    #gnav {
      width: 100%;
      height: 70px;
      margin-bottom: 15px;
      z-index: 1000;
      background-color: rgba(255, 0, 100, 0);
      transition: 0.3s ease-in-out;
    }
    
    #gnav.fixed {
      position: fixed;
      top: 0;
      left: 0;
      background-color: rgba(255, 0, 100, 0.5);
    }
    
    #gnav ul {
      margin: 0;
      padding: 26px 0 0;
      display: flex;
      justify-content: center;
    }
    
    li {
      list-style-type: none;
    }
    
    #gnav ul li a {
      position: relative;
      margin: 0 20px;
      font: 18px/25.5px sans-serif;
      display: block;
      text-decoration: none;
    }
    
    #social-link {
      text-align: center;
      margin-left: -2.5px;
    }
    
    #social-link ul li {
      display: inline-block;
    }
    
    #social-link ul li a {
      width: 35px;
      height: 35px;
      display: block;
      background-color: black;
    }
    
    main {
      width: 100%;
      height: 2000px;
      background-color: white;
    }
[/code]

[code]

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <div id='container'>
    
      <header class="img-fixed">
        <section>
          <h1>mydesign</h1>
          <nav id="gnav">
            <ul>
              <li><a href="#view-concept">CONCEPT<span></span></a></li>
              <li><a href="#view-menu">MENU<span></span></a></li>
              <li><a href="#view-about">ABOUT<span></span></a></li>
              <li><a href="#view-reserve">RESERVE<span></span></a></li>
            </ul>
          </nav>
          <aside id="social-link">
            <ul>
              <li>
                <a href="https://www.facebook.com/" target="_blank"></a>
              </li>
              <li>
                <a href="https://www.instagram.com/" target="_blank"></a>
              </li>
            </ul>
          </aside>
        </section>
      </header>
      <main></main>
    </div>
[/code]

コードを拝見したところ、不要な部分が多いように思われました。

  * DOMのオフセット座標はウィンドウのリサイズでは（たぶん）変化しないので、DOM構成が動的に変化するわけでなければ、ロードされた時点で確定していいかとおもいます。
  * 今回の原因と思われるのが、load/resizeイベント内でscrollイベントハンドラを設定している点です。このイベントが発火するたびにscrollイベントハンドラが追加で登録さてています。これは不要なだけでなく処理の衝突、パフォーマンスの悪化をもたらしますので、取り除かれるべきです。

以上を踏まえて書き直してみました。

* * *

追記

このように更新してみました。<https://jsfiddle.net/s5d6yhh3/>

[code]

    $(function() {
      // このイベントは不要と思われます
      //$(window).on('load resize', function() {
    
      // 動的に変化しないjQueryオブジェクトはキャッシュ（変数に入れて保管）しましょう
      var $window = $(window);
      var $gnav = $('#gnav');
      var $socialLink = $('#social-link');
    
      var fixedClassName = 'fixed';
      var navScrollHeight = $gnav.offset().top;
    
      $window.on('resize', function() {
        if ($gnav.hasClass(fixedClassName)) {
          $gnav.removeClass(fixedClassName);
          navScrollHeight = $gnav.offset().top;
          $gnav.addClass(fixedClassName);
        } else {
          navScrollHeight = $gnav.offset().top;
        }
      });
    
      $window.on('scroll', function() {
        if ($window.scrollTop() > navScrollHeight) {
          $gnav.addClass(fixedClassName);
          // CSS変更はなるべくJavaScriptではなくCSSで設定しましょう
        } else {
          $gnav.removeClass(fixedClassName);
        };
      });
      //});
    });
[/code]

[code]

    html,
    body {
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 0;
    }
    
    body {
      font: 12px "游ゴシック", sans-serif;
      color: black;
      position: relative;
    }
    
    div#container {
      position: relative;
      width: 100%;
      height: 100%;
    }
    
    header {
      position: relative;
      width: 100%;
      height: 100%;
      text-align: center;
      background-color: grey;
    }
    
    header.img-fixed {
      background: url("../images/photo.jpg") no-repeat;
      background-size: cover;
      background-position: center center;
      background-attachment: fixed;
    }
    
    header section {
      position: absolute;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      margin: auto;
      width: 100%;
      height: 50%;
    }
    
    header section h1 {
      width: 300px;
      height: 221px;
      text-indent: 100%;
      white-space: nowrap;
      overflow: hidden;
      background-color: black;
      background-size: 100% 100%;
      margin: 0 auto 21px;
    }
    
    #gnav {
      width: 100%;
      height: 70px;
      margin-bottom: 15px;
      z-index: 1000;
      background-color: rgba(255, 0, 100, 0);
      transition: 0.3s ease-in-out;
    }
    
    #gnav.fixed {
      position: fixed;
      top: 0;
      left: 0;
      background-color: rgba(255, 0, 100, 0.5);
    }
    
    #gnav ul {
      margin: 0;
      padding: 26px 0 0;
      display: flex;
      justify-content: center;
    }
    
    li {
      list-style-type: none;
    }
    
    #gnav ul li a {
      position: relative;
      margin: 0 20px;
      font: 18px/25.5px sans-serif;
      display: block;
      text-decoration: none;
    }
    
    #gnav.fixed+#social-link {
      margin-top: 106px;
    }
    
    #social-link {
      text-align: center;
      margin-left: -2.5px;
    }
    
    #social-link ul li {
      display: inline-block;
    }
    
    #social-link ul li a {
      width: 35px;
      height: 35px;
      display: block;
      background-color: black;
    }
    
    main {
      width: 100%;
      height: 2000px;
      background-color: white;
    }
[/code]

[code]

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <div id='container'>
    
      <header class="img-fixed">
        <section>
          <h1>mydesign</h1>
          <nav id="gnav">
            <ul>
              <li><a href="#view-concept">CONCEPT<span></span></a></li>
              <li><a href="#view-menu">MENU<span></span></a></li>
              <li><a href="#view-about">ABOUT<span></span></a></li>
              <li><a href="#view-reserve">RESERVE<span></span></a></li>
            </ul>
          </nav>
          <aside id="social-link">
            <ul>
              <li>
                <a href="https://www.facebook.com/" target="_blank"></a>
              </li>
              <li>
                <a href="https://www.instagram.com/" target="_blank"></a>
              </li>
            </ul>
          </aside>
        </section>
      </header>
      <main></main>
    </div>
[/code]

  * 当方では再現しなかったのですが、リサイズ時になんらかの処理をしたいということであれば、ここで改めてscrollイベントハンドラを追加するのではなく、適切なスコープに配置した変数を更新するような形で対応すればいいと思います。
  * 今回の場合は`#social-link`のCSS変更をスタイルシートでも実装可能です。例として書いておいたので参考までにご確認ください。
  * jQueryオブジェクトをキャッシュすべきかどうかについては様々意見がありますし、コードの規模が小さければほとんど誤差の範囲ですので、神経質になってすべて変数に入れるというのはやりすぎかもしれません。ただし個人的な見解を述べれば、単純に何度も`$('selector')`と書くのが面倒なので、十分おすすめするに値すると思います（変数としておけば補完などでも対応してくれる場合が増えます）。

なお内容があれもこれもになってきましたので、加えてご質問があればあらたな投稿として質問していただくほうが、いろいろなかたの意見が聞けるかと思います。


CC BY-SA 4.0
2017-02-05T17:36:39.250
32411
2019-09-15T05:44:36.373
2019-09-15T05:44:36.373
32986
32409
answer