jQuery | スクロールで上からにゅるっと出てくるメニューバー

プログラミング勉強

このように、最初ヘッダートップにあってスクロールすると消えるけど、再び上からにゅるっと出てくるメニューバー。

メニューバーはいつもなんか適当に作ってたので、この機会にちゃんとまとめてみます。

まずはHTML

<ul class="header-nav js-header-nav">
 <li><a href="#">Main</a></li>
 <li><a href="#News">News</a></li>
 <li><a href="#price">Price</a></li>
 <li><a href="#access">Access</a></li>
 <li><a href="#contact">Contact</a></li>
</ul>
 つるんとしたシンプルなやつです。
ul タグにクラスを2つ当ててるのは、あとでjQueryで使うためです。

CSS

 
.header-nav {
  /* liアイテムを横並び */
  display: flex;
  /* ul全体の幅・高さ */
  width: 100%;
  height: 100px;
  background: pink;
}
.header-nav li {
  /* メニュー名を左右中央寄せ */
  text-align: center;
  /* li box の高さをulに合わせる */
  line-height: 100px;
  width: calc(100% / 5);
}
.header-nav li a{
  /* リンクをブロックいっぱいに */
  display: block;
  color: #000;
}

CSSもシンプルなんですが、

li の高さをul に合わせて、かつ垂直に中央にしようとすると、

heightを100%に指定したりline-height/heightを同値で指定したりすると

望むようになってくれなくて困りました。。

 

とりあえず上記のCSSで各li の幅いっぱいにリンクが押せるメニューバーが出来上がりです。

jQuery

  $(function() {
    let headNav = $('.js-header-nav');
    //scrollしたとき
    $(window).on('scroll', function () {
    //現在の位置が200pxより大きいかつ、クラスfixedが付与されていない(false)時
    if($(this).scrollTop() > 200 && headNav.hasClass('fixed') == false) {
    //headerの高さ分上に設定(上から降りてくるようにするため)
    headNav.css({top: '-100px'});
    //クラスfixedを付与
    headNav.addClass('fixed');
    //位置を0に設定。1秒かけてアニメーションでにゅるっと降りてくる
    headNav.animate({top: 0},1000);
  }

    //現在の位置が200px以下かつ、クラスfixedが付与されている時にfixedを外す
    else if($(this).scrollTop() <= 200 && headNav.hasClass('fixed') == true){
    headNav.removeClass('fixed');
  }

  //場合によってフロートナビゲーションの残像が残ることがあったので追記。後で少し説明します。
     else if($(this).scrollTop() <= 200) { 
       headNav.removeClass("fixed");
    }
  });
});

ちょっと長いですが、最初のブロックでは一定までスクロールしたときの

「にゅるっと出てくる」アニメーションの位置・動きを指定しています。

いぬ

jQueryで「fixedクラス」を付与し、top:0の指定もできましたが、後ほどcssへも「.fixed」のスタイルを追記します

そして後ろのブロックでは、スクロールが一定まで満たない状態の指定をしています。

今回のアニメーション指定はtopだけですが、
通常ハイフンでつなぐようなプロパティをanimate関数へ指定する時は、
キャメルケースで書くそうです。
fontSize backgroundColor …等

.fixed へスタイル指定

.fixed{
position: fixed;
/* top: 0; ←はjQeryで指定済み*/
}

positionを指定しないとtop:0 だけでは思うようにならないので、

cssでposition:fixed を指定します。

とりあえずこれで上からにゅるっと降りてくるメニューバーが完成です!

上から降りてきたらCSSを変えたい

こういう感じで、上からスライドダウンしてきた時に見た目を変えたい!

というわがまま要望があった場合も追記するだけでいけます。

 /* ヘッダーナビがスクロールでダウンしてきたとき */
.fixed{
position: fixed;
}
.header-nav.fixed {
background: rgba(255, 99, 71, .7);
}
.fixed .changeColor {
background: yellow;
}

先ほどの.fixedはそのままにして、

.fixedがついてる場合の.header-nav(ul全体)の背景色を指定。

CSSを上書きしてあげます。

おまけとして、.fixedがついてるときの1つめのliアイテムにも変化をつけてあげました。

そのためにあらかじめ1つめのliにclass=”changeColor”を追記してあります。

ナビメニューの下側にシャドウをつけたい場合は

いぬ
box-shadow: 0 10px 10px rgba(0,0,0,0.1);
と指定すると下側10pxにぼかし10pxのうっすらシャドウがつきます

フロートナビゲーションの残像が・・・?

さきほど、後で説明しますと書いたjQueryの最後のコードですが、

トップ固定ナビゲーションとフロートナビゲーションの位置が違うページを作っていて、

たとえば、トップ固定ナビはヘッダーの上から100pxの位置。フロートナビはfixedのtop:0;だったとします。

パッと見の挙動は大丈夫なのですが、フロートナビがちょうど出現するくらいのぎりぎりのところでヘッダーにスクロールして戻ったりすると

フロートナビの残像がtop:0;の位置に謎に残っていたことがありまして。

とりあえず最後のコードを追記したら解決しました。

無くても動く場合も多いと思いますので、環境によって修正ください。

 

今思うと、if 、else ifの条件が甘いんですかね・・・?ifとelseだけでもいいような気がしてきましたが、それはまた今度考えます。。

最終的なコード

html

<ul class="js-header-nav header-nav">
 <li><a class="changeColor"href="#">Main</a></li>
 <li><a href="#">News</a></li>
 <li><a href="#price">Price</a></li>
 <li><a href="#access">Access</a></li>
 <li><a href="#contact">Contact</a></li>
</ul>

css

.header-nav {
  /* liアイテムを横並び */
  display: flex;
  /* ul全体の幅・高さ */
  width: 100%;
  height: 100px;
  background: pink;
}
.header-nav li {
  /* メニュー名を左右中央寄せ */
  text-align: center;
  /* li box の高さをulに合わせる */
  line-height: 100px;
  width: calc(100% / 5);
}
.header-nav li a{
 /* リンクをブロックいっぱいに */
  display: block;
  color: #000;
}

/* ヘッダーナビがスクロールでダウンしてきたとき */
.fixed{
  position: fixed;
}
.header-nav.fixed {
  background: rgba(255, 99, 71, .7);
}
.fixed .changeColor {
  background: yellow;
}

jquery

これは先ほどと全く同じですが、一応

  $(function() {
    let headNav = $('.js-header-nav');
    //scrollしたとき
    $(window).on('scroll', function () {
    //現在の位置が200px以上かつ、クラスfixedが付与されていない(false)時
    if($(this).scrollTop() > 200 && headNav.hasClass('fixed') == false) {
    //headerの高さ分上に設定(上から降りてくるようにするため)
    headNav.css({top: '-100px'});
    //クラスfixedを付与
    headNav.addClass('fixed');
    //位置を0に設定。1秒かけてアニメーションでにゅるっと降りてくる
    headNav.animate({top: 0},1000);
  }

    //現在の位置が200px以下かつ、クラスfixedが付与されている時にfixedを外す
   //(スクロールアップでも消えるように)
    else if($(this).scrollTop() < 200 && headNav.hasClass('fixed') == true){
    headNav.removeClass('fixed');
  }

   //必要に応じてつける
   else if($(this).scrollTop() <= 200) { 
   headNav.removeClass("fixed");
   }
  });
});

こんな感じでできました!

お疲れ様です〜

☆参考サイト OKULOG様

 

CodePenも使ってみました!!

※スライドダウン時のbackground透過とboxshadowも加えているので、

上記のコードとは微妙に異なります。

See the Pen
上からにゅるっとメニューバー
by hiro (@hiro555)
on CodePen.

タイトルとURLをコピーしました