ナビゲーションを固定するtipsはよく見かけますが、
開閉するコンテンツが含まれる場合、documentの高さをどうやって再取得したら良いんだろう、、、
と少しハマってしまったので、メモメモ。
sample.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>header固定+ドロップダウン</title>
<link href="sample.css" rel="stylesheet">
</head>
<body>
<header><h1>header固定+ドロップダウンのサンプル</h1></header>
<nav>
<ul>
<li>リスト1</li>
<li>リスト2</li>
<li>リスト3</li>
<li>リスト4</li>
</ul>
</nav>
<main>
<section>
<h2>ココをクリックすると内容が開きます。</h2>
<p>これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。</p>
</section>
<section>
<h2>ココをクリックすると内容が開きます。</h2>
<p>これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。</p>
</section>
<section>
<h2>ココをクリックすると内容が開きます。</h2>
<p>これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。</p>
</section>
<section>
<h2>ココをクリックすると内容が開きます。</h2>
<p>これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。</p>
</section>
<section>
<h2>ココをクリックすると内容が開きます。</h2>
<p>これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。</p>
</section>
</main>
<footer></footer>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="sample.js"></script>
</html>
sample.css
@charset "UTF-8" ;
*{
margin: 0;
padding: 0;
box-sizing: border-box;
text-align: center;
}
header{
height: 200px;
background: #baa7c5;
color: #fff;
}
header h1{
line-height: 6;
}
nav{
background: #2e889c;
transition: .3s;
}
nav ul{
display: flex;
list-style: none;
justify-content: center;
}
nav ul li{
padding: 10px 20px;
}
main{ padding-top: 50px;}
main section{
max-width: 960px;
margin: 0 auto 50px;
background: #f0f0f0;
padding: 20px;
}
main section h2{ margin-bottom: 10px;}
main section h2 + p{
display: none;
background: #888;
color: #eee;
margin-top: 10px;
padding: 10px;
}
.is-fixed {
position: fixed;
bottom: 0;
left: 0;
z-index: 2;
width: 100%;
}
.is-hide {
transform: translateY(100%);
}
footer{
height: 200px;
background: #2c3e50;
color: #fff;
}
sample.js
$(function() {
//開閉
$("h2").on("click", function() {
$(this).next("p").slideToggle().toggleClass("open");
if ($(this).next("p").hasClass("open")) {
$(this).text("ココをクリックすると内容が閉じます。");
}
else {
$(this).text("ココをクリックすると内容が開きます。");
}
});
//nav固定
var $win = $(window),
$main = $('main'),
$nav = $('nav'),
navHeight = $nav.outerHeight(),
footerHeight = $('footer').outerHeight(),
docmentHeight = $(document).height(),
navPos = $nav.offset().top,
fixedClass = 'is-fixed',
hideClass = 'is-hide';
/* スクロールした時 */
$win.on('load scroll', function() {
var value = $(this).scrollTop(),
scrollPos = $win.height() + value;
if ( value > navPos ) {
if ( docmentHeight - scrollPos <= footerHeight ) {
$nav.addClass(hideClass);
} else {
$nav.removeClass(hideClass);
}
$nav.addClass(fixedClass);
} else {
$nav.removeClass(fixedClass);
}
});
/* 開閉してdocumentの高さが変わった時 */
$("h2").on('click', function(){
$win.on('load scroll', function() {
var value02 = $(this).scrollTop(),
docmentHeight02 = $(document).height(),
scrollPos02 = $win.height() + value02;
$nav.removeClass('is-hide');
if ( value02 > navPos ) {
if ( docmentHeight02 - scrollPos02 <= footerHeight ) {
$nav.addClass(hideClass);
} else {
$nav.removeClass(hideClass);
}
$nav.addClass(fixedClass);
} else {
$nav.removeClass(fixedClass);
}
});
});
});
スクロールした時とクリックした時を一緒に処理しようとしていたために、
ややこしく感じてしまいました。
結果、分けて書けば特に難しいことはなかったです。
(もっとスマートな書き方があれば教えてください。)
参考
ナビゲーションの固定に関しては、こちらの記事の5番目を参考にしました。
大変わかりやすい記事でありがたいです。
jQuery:スクロールしたらヘッダーやナビゲーションを固定・変化させる動きを実装するサンプルコード 5/NxWorld