ヘッダーは、ページの上部に配置して表示される部分で、サイトのロゴやメニューをここに置きます。
このヘッダーにはいろんなデザインやレイアウトがありますが、この記事ではよく見る一般的なレイアウトにJavaScriptの .scrollTop
を使って背景色が変わるものを作ってみました。
レスポンシブでスマホにも対応しています。
この記事内のコードを使ったサンプルも上部にあるので、併せてご覧いただきながら参考にし参考にしていただけたら嬉しいです。
.scrollTop
JavaScriptの .scrollTop
は、要素の内容が垂直にスクロールするピクセル数を取得または設定するプロパティです。
document.body.scrollTop > 80
この記事では、body
タグ内でのピクセル数を .scrollTop
で取得して、if の条件分岐でclassの付け替えを行い、ヘッダーの背景色の変化を行います。
スクロールで背景色が加わるヘッダーのサンプル
早速サンプルです。はじめは背景色がない透明のヘッダーが、スクロールするとヘッダーの背景色に白い色が付きます。
PCだとこんな感じで、スマホだと右側にメニューバーが表示されます。
LOGO
実装の手順と方法
コードの解説の前に、実装の手順と方法について解説します。
はじめに、以下のHTMLを記述します。ヘッダーなので、場所は header
タグの中に記述しましょう。
<div id="header">
<div class="headerInner">
<p class="headerLogo">LOGO</p>
<nav>
<ul class="navLinks">
<li><a href="#">MENU1</a></li>
<li><a href="#">MENU2</a></li>
<li><a href="#">MENU3</a></li>
<li><a href="#">MENU4</a></li>
</ul>
<div class="burger">
<div class="line1"></div>
<div class="line2"></div>
<div class="line3"></div>
</div>
</nav>
</div>
</div>
次に、JavaScriptのコードをページに記述します。
コードは <body>〜</body>
で、</body>
の閉じタグ(クロージングタグ)の前に記述しましょう。
// ヘッダーのスクロール制御
const header = document.getElementById("header");
window.addEventListener('scroll', function(){
if (document.body.scrollTop > 80 || document.documentElement.scrollTop > 80) {
header.classList.add('resize');
} else {
header.classList.remove('resize');
}
});
//スマホでメニュー表示・非表示
const navMenu = document.querySelector('.navLinks');
document.querySelector(".burger").addEventListener('click', () => {
navMenu.classList.toggle('active');
},);
最後に、CSSを記述します。
#header {
position: fixed;
top: 0;
width: 100%;
transition: 0.3s ease-in-out;
left: 0;
z-index: 99;
display: flex;
margin: 0;
}
.headerInner {
width: 100%;
max-width: 1130px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
height: 60px;
transition: 0.3s ease-in-out;
position: relative;
}
.headerInner .headerLogo {
margin: 0;
line-height: 60px;
font-size: 1.8rem;
font-weight: 500;
}
.headerInner nav .navLinks {
border: none;
list-style: none;
display: flex;
justify-content: flex-end;
gap: 20px;
margin: 0;
padding: 0;
}
.headerInner nav .navLinks li {
padding: 0;
display: inline-block;
}
.headerInner nav .navLinks li a {
display: block;
height: 60px;
line-height: 60px;
padding: 0 5px;
position: relative;
color: #313131;
}
.headerInner nav .navLinks li a:hover {
text-decoration: none;
}
.headerInner nav .navLinks li a:after {
content: "";
bottom: 0;
width: 0%;
height: 3px;
background: #f0db40;
position: absolute;
left: 0;
transition: all 0.4s;
}
.headerInner nav .navLinks li a:hover:after {
width: 100%;
}
div#header.resize {
background: #FFF;
box-shadow: 0 3px 6px rgb(0 0 0 / 18%);
}
div#header.resize .headerInner {
max-width: 1200px;
}
.burger {
cursor: pointer;
display: none;
}
.burger div {
width: 28px;
height: 3px;
background: #dbdbdb;
}
.active {
display: none;
}
/* スマホUI */
@media screen and (max-width: 767px) {
.headerInner {
justify-content: center;
}
.headerInner .headerLogo {
font-size: 1.6rem;
}
.burger {
display: flex;
flex-direction: column;
gap: 7px;
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
}
.headerInner nav .navLinks {
display: none;
}
ul.navLinks.active {
display: flex;
flex-direction: column;
position: absolute;
top: 99%;
text-align: center;
background: rgb(0,0,0,.9);
width: 100%;
left: 0;
z-index: 0;
gap: 0;
}
.headerInner nav .navLinks li a {
color: #ccc;
}
.headerInner nav .navLinks li a:after {
content: none;
}
}
これで完了です。
ざっくりとしたコードの解説
コードはHTML・JavaScript・CSSの3種です。ざっくりですが、順に解説していきます。
HTML
HTMLは、「header」のid名がつく要素の中にインナーの子要素を作り、その中にロゴやメニューを作っていきます。
<div id="header">
<div class="headerInner">
<p class="headerLogo">LOGO</p>
<nav>
<ul class="navLinks">
<li><a href="#">MENU1</a></li>
<li><a href="#">MENU2</a></li>
<li><a href="#">MENU3</a></li>
<li><a href="#">MENU4</a></li>
</ul>
<div class="burger">
<div class="line1"></div>
<div class="line2"></div>
<div class="line3"></div>
</div>
</nav>
</div>
</div>
「navLinks」のclass名がつく ul
タグがメニューにあたり、ここはCSSのメディアクエリで表示が一番変わる場所です。
JavaScript
JavaScriptは「ヘッダーのスクロールでclassの付け替え」と「スマホでのメニュークリック時のclassトグル」の2種類です。
// ヘッダーのスクロール制御
const header = document.getElementById("header");
window.addEventListener('scroll', function(){
if (document.body.scrollTop > 80 || document.documentElement.scrollTop > 80) {
header.classList.add('resize');
} else {
header.classList.remove('resize');
}
});
//スマホでメニュー表示・非表示
const navMenu = document.querySelector('.navLinks');
document.querySelector(".burger").addEventListener('click', () => {
navMenu.classList.toggle('active');
},);
冒頭の「ヘッダーのスクロール制御」では、.addEventListener
のスクロールイベントで if
の条件分岐を記述して、スクロール量が 80 を境に「resize」のclass名の追加・削除して背景色を変更します。
CSS
CSSは、JavaScriptでclass名を追加・削除する為、コード量は少し多めです。
#header {
position: fixed;
top: 0;
width: 100%;
transition: 0.3s ease-in-out;
left: 0;
z-index: 99;
display: flex;
margin: 0;
}
.headerInner {
width: 100%;
max-width: 1130px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
height: 60px;
transition: 0.3s ease-in-out;
position: relative;
}
.headerInner .headerLogo {
margin: 0;
line-height: 60px;
font-size: 1.8rem;
font-weight: 500;
}
.headerInner nav .navLinks {
border: none;
list-style: none;
display: flex;
justify-content: flex-end;
gap: 20px;
margin: 0;
padding: 0;
}
.headerInner nav .navLinks li {
padding: 0;
display: inline-block;
}
.headerInner nav .navLinks li a {
display: block;
height: 60px;
line-height: 60px;
padding: 0 5px;
position: relative;
color: #313131;
}
.headerInner nav .navLinks li a:hover {
text-decoration: none;
}
.headerInner nav .navLinks li a:after {
content: "";
bottom: 0;
width: 0%;
height: 3px;
background: #f0db40;
position: absolute;
left: 0;
transition: all 0.4s;
}
.headerInner nav .navLinks li a:hover:after {
width: 100%;
}
div#header.resize {
background: #FFF;
box-shadow: 0 3px 6px rgb(0 0 0 / 18%);
}
div#header.resize .headerInner {
max-width: 1200px;
}
.burger {
cursor: pointer;
display: none;
}
.burger div {
width: 28px;
height: 3px;
background: #dbdbdb;
}
.active {
display: none;
}
/* スマホUI */
@media screen and (max-width: 767px) {
.headerInner {
justify-content: center;
}
.headerInner .headerLogo {
font-size: 1.6rem;
}
.burger {
display: flex;
flex-direction: column;
gap: 7px;
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
}
.headerInner nav .navLinks {
display: none;
}
ul.navLinks.active {
display: flex;
flex-direction: column;
position: absolute;
top: 99%;
text-align: center;
background: rgb(0,0,0,.9);
width: 100%;
left: 0;
z-index: 0;
gap: 0;
}
.headerInner nav .navLinks li a {
color: #ccc;
}
.headerInner nav .navLinks li a:after {
content: none;
}
}
「burger」のclass名がつく要素が、スマホで右上に表示されるメニューバーで、ここはJavaScriptじゃなくCSSで表示・非表示をコントロールします。
パソコンで見た場合にこの要素は display: none;
で非表示にして、スマホで見ると display: flex;
になるようメディアクエリで表示されるようにしています。
さいごに
JavaScriptの .scrollTop
は、この記事のように「どれだけスクロールしたか?」などの条件分岐と併せて使うことで、表示を切り替えたりすることができるので是非覚えておきましょう。