【jQuery】スクロールして対象の要素が見えた時にメニューの色を変える

2014.8.9 jQuery

LP(ランディングページ)とかによくある、対象の要素が見えた時に色が変わるメニューをjQueryで簡単に実装!

LP(ランディングページ)などでよく使われている、ある特定のエリアに差し掛かった時にパッと色が変わるナビゲーションの実装をしていきます。

今回は、セクションが画面に登場する度に、それに応じたid指定のサイドメニューの色が変わる効果を例にあげますが、そうでない場合にも応用が効くと思います。

 

HTML

<main>
	<section id="to_section1">1</section>
	<section id="to_section2">2</section>
	<section id="to_section3">3</section>
	<section id="to_section4">4</section>
	<section id="to_section5">5</section>
	<section id="to_section6">6</section>
</main>
<aside class="sidebar">
	<ul>
		<li><a href="#to_section1">section1</a></li>
		<li><a href="#to_section2">section2</a></li>
		<li><a href="#to_section3">section3</a></li>
		<li><a href="#to_section4">section4</a></li>
		<li><a href="#to_section5">section5</a></li>
		<li><a href="#to_section6">section6</a></li>
	</ul>
</aside>

メインカラムとサイドカラムです。

メインカラムにはidを指定します。
そこにページ内リンクを設定する要領で、サイドメニューの<a>にもメインカラムのidへリンクを指定します。

サイドカラムの<a hreF=””>に指定した、対応したidをもつメインカラムの<section>スクロールによって現れた時に、サイドカラムの各<a>に効果を当てていきます。

CSS

	<style>
	body , html{
		margin: 0;
		padding: 0;
		font-family: century gothic;
	}
		main{
			width: 70%;
			float: left;
		}
		aside{
			width: 30%;
			float: right;
		}

		li{list-style:none;}

		section{
			height: 500px;
			padding: 250px 0;
			text-align: center;
			font-size: 200px;
			color: #fff;
			}
		section:nth-child(odd){
			background-color: #cfc;
		}
		section:nth-child(even){
			background-color: #ccf;
		}
		.sidebar{
			position: fixed;
			right: 0;
		}
		.sidebar li a{
			padding: 10px 30px;
			margin-bottom: 10px;
			background-color: #ccc;
			font-size: 30px;
			display: block;
			-webkit-transition: all .3s;
			-o-transition: all .3s;
			transition: all .3s;
		}

		.sidebar li a.now{
			background-color: #fcc;
		}

わかりやすく、sectionを色分けして高さをつけています。

サイドメニューは画面上部に固定しています。

jQuery

$(function(){
	$(window).on('scroll' , function(){
		$('.sidebar li a').each(function() {
			//変数の作成
			var $window = $(window);
			var $this = $(this);

			var linkTo =  $this.attr('href'); //href=""取得
			var $target = $(linkTo);

			var topLimit= $target.offset().top;
			var bottomLimit = $target.offset().top + $target.outerHeight();

			if(topLimit <= $window.scrollTop() && $window.scrollTop() <= bottomLimit){
				$this.addClass('now');
			}else{
				$this.removeClass('now');
			}


		});
	});

});

$(window).on(‘scroll’ ,function(){~で、スクロールにより発生するイベントとして書いていきます!

3行目の$(‘.sidebar li a’)が、変化を起こすターゲットです。クラスとかidを指定している場合はそれを書いたほうがいいでしょう。
で、イベント発生ごとに各要素をターゲットとするため、.eachで処理します。

eachは感覚で使ってしまっているので、しっかり勉強せねば…

つぎに、後に使う変数を定義します。

  • $window…開いてるウィンドウに対して~するため
  • $this…いまターゲットとしている.sidebar li aに対して~するため
  • linkTo…$thisを使って、いまターゲットとしている.slidebar li aのhref=””値
  • $target…変数linkToをjQueryオブジェクト化$(linkTo)と書いて代入する

最後の項目はハマってしまいました。linkToをそのまま使いまわすと「TypeError: linkTo.offset is not a function」などとコンソールでエラーが出ます。

以上の変数をベースに、具体的な数値を計算する変数を書きます。このへんです。

var topLimit= $target.offset().top;
var bottomLimit = $target.offset().top + $target.outerHeight();
  • topLimit…先ほどの$target(a href=””値、つまりはサイドメニューと対をなすセクション要素)の上端の、HTMLの一番上から$targetの上端の距離
    .offset() | jQuery 1.9 日本語リファレンス | js STUDIO
  • bottomLimit…$targetの上端の、ページの一番上からの距離 + $targetの高さ = HTMLの一番上から$targetの下端の距離

次のif条件分岐で勝負が決まります…!

if(topLimit <= $window.scrollTop() && $window.scrollTop() <= bottomLimit){
	$this.addClass('now');
}else{
	$this.removeClass('now');
}

最初のifは何を言っているかというと、

「ページ上端からスクロールした距離px($window.scrollTop())」が、「ターゲットが対象とするsectionの、ページの上からの位置(topLimit)」よりも大きくて、「ページ上端から、ターゲットのsectionの下端までの距離(bottomLimit)」より小さい
場合に、ターゲットにclass=”now”を付加し、そうでない場合(対象のsectionを通り過ぎた場合)にclass=”now”を外すということです。

で、今回はCSSで

		.sidebar li a.now{
			background-color: #fcc;
		}

と指定しているので、画面上にhref=””と同じidのsectionが現れた場合、サイドメニューの一部分が赤く背景色が変わる仕様になっています。

デモはこちら。

スクロールして対象要素が現れた時、サイドメニューの色が変わるデモ

あとはCSSの指定で色々アレしてみてください!
今回は.sidebar liにtransitionプロパティを使用しているので、フワッと背景色が変わる感じになってて、ちょっとやわらかくて落ち着いた感じになっていますねー。

この「ある要素が現れたとき、エフェクトを与える」というのは、応用を利かせることにより、非常にクリエイティブな表現ができると思います。
ちょっと違う方法ですが、その応用をしているwebサイトをご紹介します!

jquery.inviewで更にリッチに実装!

jQuery.inviewも似たようなエフェクトを実装できます。
前述の応用を実装するためにはjquery.inviewがお手軽でしょう。

詳しい使い方はこのへんが語ってくださっています。ご参考ください!

スクロールにより、対象のセクションに差し掛かるとこんな感じになるんです。かっこいい!抱かれたい!

BESHOW

BEASHOW (ビショウ) -サロンが開発 本物のサロン品質-

 

いかがでしたでしょうか。

サイドメニューの色が変わるだけでも、かなりユーザーは迷いにくくなると思います。
今回は「setion1,2…」でしたが、各セクションの見出しを書くことで、より必要な情報を選んで観てもらうことが出来ますね。

意外と単純なコーディングなので是非試してみてくださいー!

 

でわ!

プロフィール

東京でWebデザイナー・コーダーとして、フロントエンド的なことからグラフィックデザイン的なことをして、ごにょごにょと小さく活動中。Webクリエイターでは珍しい(?) HIPHOP, R&B好き。休日はよくカフェや漫画喫茶に出向いたりパン屋に行ったり、主に散歩しています。だいたいラーメンを食べて帰ってくる、そんな過ごし方です(都内のオススメ散歩コース募集中!)。デザインのトレンドやデザイン思考、HTML、CSSからSASS、Javascript、Wordpress構築などコーディングのTIPSなどをブログにアップしていきます。その他のことはtwitter( @satohmsys )まで。