スクロールしても固定表示されるヘッダーは珍しくありませんが、その方法はいくつかあります。今回は5つのパターンでサンプルを作成してみました。
Contents
最初から固定表示
基本なので言わずもがなですが一応。単なる固定表示ならCSSの「position: fixed;」だけです。簡単ですね。
HTML
<header class="site-header">
<h1 class="site-logo"><img src="images/logo.png" alt="WEBDESIGNDAY"></h1>
<nav class="gnav">
<ul class="gnav__menu">
<li class="gnav__menu__item"><a href="">About</a></li>
<li class="gnav__menu__item"><a href="">Works</a></li>
<li class="gnav__menu__item"><a href="">Recruit</a></li>
<li class="gnav__menu__item"><a href="">News</a></li>
<li class="gnav__menu__item"><a href="">Contact</a></li>
</ul>
</nav>
</header>
<div class="hero"><img src="images/hero.jpg" alt="hero"></div>
<div class="content">
<!--省略-->
</div>
<footer class="site-footer">
<p class="copyright">@2017 WEBDESIGNDAY</p>
</footer>
CSS
body{
background: #81bcd8;
}
.site-header{
background: #fff;
display: flex;
padding: 60px 20px;
position: fixed;
justify-content: space-between;
width: 100%;
}
.site-logo img{
height: 20px;
width: auto;
}
.gnav__menu{
display: flex;
}
.gnav__menu__item{
margin-left: 20px;
}
.gnav__menu__item a{
color: #333;
text-decoration: none;
}
.hero{
max-height: 500px;
overflow: hidden;
}
.hero img{
height: auto;
width: 100%;
}
.content{
line-height: 1.6;
margin: 0 auto;
padding-top: 100px;
width: 800px;
}
.content p{
margin-bottom: 40px;
}
.site-footer{
background: #333;
padding: 80px 0;
}
.copyright{
color: #fff;
font-size: 12px;
text-align: center;
}
最初から固定表示、特定位置までスクロールでサイズ・色を変える
windowのスクロールイベントを受け取り、特定の位置までスクロースしたらヘッダーにクラスをつけてCSSを変更します。
HTML
HTMLは変更なしです。
CSS
.site-header{
background: rgba(255,255,255,0.5);
display: flex;
padding: 60px 20px;
position: fixed;
justify-content: space-between;
transition: .5s;
width: 100%;
}
.site-header.transform{
background: rgba(255,255,255,0.9);
padding: 20px;
}
2行目
変更後の違いをわかりやすくするためと、メインの画像の邪魔をしないように背景色を透過させています。
11行目
特定位置までスクロールするとjQueryで「transform」クラスをつけますので、スタイルを変えています。
jQuery
var _window = $(window),
_header = $('.site-header'),
heroBottom;
_window.on('scroll',function(){
heroBottom = $('.hero').height();
if(_window.scrollTop() > heroBottom){
_header.addClass('transform');
}
else{
_header.removeClass('transform');
}
});
_window.trigger('scroll');
6行目
変数「heroBottom」にメイン画像エリアの高さを入れています。画像ですので、jQueryが読み込まれてすぐに変数に高さを入れようとすると正常な高さが取得できません。
ですので、スクロール時に高さを変数に入れています。
7行目
今回は、「メイン画像エリアの「.hero」の下までスクロールしたら」というのを条件判定にクラスをつけていきます。
途中から固定表示
HTML
<div class="hero"><img src="images/hero.jpg" width="1600" height="1200" alt="hero"></div>
<header class="site-header">
<h1 class="site-logo"><img src="images/logo.png" alt="WEBDESIGNDAY"></h1>
<nav class="gnav">
<ul class="gnav__menu">
<li class="gnav__menu__item"><a href="">About</a></li>
<li class="gnav__menu__item"><a href="">Works</a></li>
<li class="gnav__menu__item"><a href="">Recruit</a></li>
<li class="gnav__menu__item"><a href="">News</a></li>
<li class="gnav__menu__item"><a href="">Contact</a></li>
</ul>
</nav>
</header>
<div class="content">
<!--省略-->
</div>
<footer class="site-footer">
<p class="copyright">@2017 WEBDESIGNDAY</p>
</footer>
メイン画像とヘッダーの順番を入れ変えました。
CSS
.site-header{
background: #fff;
display: flex;
padding: 20px;
position: absolute;
justify-content: space-between;
width: 100%;
}
.site-header.fixed{
position: fixed;
top: 0;
}
5行目
「position: absolute;」にしておくのがポイントです。こうしておかないと固定表示にした途端、下のコンテンツがヘッダーの高さ分上にカクっとずれてしまいます。
10,11行目
jQueryで「.fixed」クラスをつけますので固定表示にします。
jQuery
var _window = $(window),
_header = $('.site-header'),
heroBottom;
_window.on('scroll',function(){
heroBottom = $('.hero').height();
if(_window.scrollTop() > heroBottom){
_header.addClass('fixed');
}
else{
_header.removeClass('fixed');
}
});
_window.trigger('scroll');
15行目
スクロールをきっかけにしているので、途中までスクロールしている状態でリロードされた場合、スクロールイベントが発生しません。
ですので、「_window.trigger(‘scroll’);」でロード時に「スクロールしたよ」と通知しています。
あとは先ほどのサンプルとほとんど何も変わりません。つけるクラス名が「fixed」になっただけです。
途中からヘッダーを入れ替える
HTML
<div class="hero"><img src="images/hero.jpg" width="1600" height="1200" alt="hero"></div>
<header class="site-header">
<h1 class="site-logo"><img src="images/logo.png" alt="WEBDESIGNDAY"></h1>
<nav class="gnav">
<ul class="gnav__menu">
<li class="gnav__menu__item"><a href="">About</a></li>
<li class="gnav__menu__item"><a href="">Works</a></li>
<li class="gnav__menu__item"><a href="">Recruit</a></li>
<li class="gnav__menu__item"><a href="">News</a></li>
<li class="gnav__menu__item"><a href="">Contact</a></li>
</ul>
</nav>
</header>
<div class="content">
<!--省略-->
</div>
<footer class="site-footer">
<p class="copyright">@2017 WEBDESIGNDAY</p>
</footer>
<div class="header-change">
<h1 class="site-logo"><img src="images/logo-w.png" alt="WEBDESIGNDAY"></h1>
<nav class="gnav">
<ul class="gnav__menu">
<li class="gnav__menu__item"><a href="">About</a></li>
<li class="gnav__menu__item"><a href="">Works</a></li>
<li class="gnav__menu__item"><a href="">Recruit</a></li>
<li class="gnav__menu__item"><a href="">News</a></li>
<li class="gnav__menu__item"><a href="">Contact</a></li>
</ul>
</nav>
</div>
20行目
フッターの後に入れ替え用のヘッダー「header-change」を追加しました。
CSS
.site-header{
background: #fff;
display: flex;
justify-content: space-between;
padding: 20px;
position: absolute;
width: 100%;
}
.header-change{
background: #333;
display: flex;
justify-content: space-between;
padding: 20px;
position: fixed;
top: -63px;
transition: .5s;
width: 100%;
}
.header-change.show{
top: 0;
}
.header-change .gnav__menu__item a{
color: #fff;
text-decoration: none;
}
「header-change」のスタイルを追加しています。
15行目
ヘッダー高さだけ上に移動して隠しています。
jQuery
var _window = $(window),
_header = $('.site-header'),
headerChange = $('.header-change'),
heroBottom;
_window.on('scroll',function(){
heroBottom = $('.hero').height();
if(_window.scrollTop() > heroBottom){
headerChange.addClass('show');
}
else{
headerChange.removeClass('show');
}
});
_window.trigger('scroll');
9行目
クラスをつけるのが入れ替え用のヘッダーに変更になっただけであとは同じです。
下にスクロールで消えて上にスクロールで固定表示
HTML
HTMLはサンプル3と同じです。
CSS
.site-header{
background: #fff;
display: flex;
justify-content: space-between;
padding: 20px;
position: fixed;
top: 0;
transition: .5s;
width: 100%;
}
.site-header.hide{
top: -63px;
}
12行目
こちらはクラスがついたら上に移動して隠します。
jQuery
var _window = $(window),
_header = $('.site-header'),
heroBottom,
startPos,
winScrollTop;
_window.on('scroll',function(){
winScrollTop = $(this).scrollTop();
heroBottom = $('.hero').height();
if (winScrollTop >= startPos) {
if(winScrollTop >= heroBottom){
_header.addClass('hide');
}
} else {
_header.removeClass('hide');
}
startPos = winScrollTop;
});
_window.trigger('scroll');
10・17行目
直前までのスクロール位置を「startPos」に入れて、それに対してスクロールが増えていれば下スクロール。そうでなければ上スクロールになります。
11行目
それだけだと下にスクロールし始めるとすぐに消えてしまうので今まで同様、メイン画像の下までスクロールしたら消えるように条件判定を追加しています。