@ PHP

Onepage scroll:ワンページスクロール

ワンページスクロールは、シングルページ(1ページ完結型のページ)を作成する場合に使われるフリップ型のページナビゲーションの一つで、メニューをクリックすると縦方向にスムーズスクロールして、コンテンツを閲覧できる仕組みです。

onepage_scroll.html

<!DOCTYPE html>
<html lang="ja">

<head>
<meta charset="utf-8">
<title>sample</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.header {
  position: fixed;
  z-index: 200;
  top: 0;
  width: 100%;
  background: rgba(255, 255, 255, .9);
}
.header {
  text-align: center;
}
.header nav ul li {
  display: inline-block;
}
.header nav ul li a {
  font-weight: bold;
  display: block;
  padding: 9px 20px;
  text-decoration: none;
  color: black;
}
#fashion,
#travel,
#art,
#food {
  position: relative;
  width: 100%;
  height: 400px;
  border-bottom: solid 1px black;
}
#fashion .section-title,
#travel .section-title,
#food .section-title {
  font-size: 4rem;
  line-height: 1;
  position: absolute;
  bottom: 5px;
  left: 40px;
  margin: 0;
  padding: 0;
  letter-spacing: .1rem;
}
#art .section-title {
  font-size: 4rem;
  line-height: 1;
  position: absolute;
  right: 100px;
  bottom: 5px;
  margin: 0;
  padding: 0;
  transform: rotate(90deg);
  transform-origin: right bottom;
  letter-spacing: .1rem;
}
footer {
  height: 100px;
  margin: 0;
  padding: 0;
  background: #fff;
}
footer small {
  font-size: 0.8rem;
  padding-left: 20px;
}
</style>
</head>

<body>
<header>
  <div class="header" id="top-head">
    <nav>
      <ul>
        <li><a href="#fashion" class="nav-link">Fashion</a></li>
        <li><a href="#travel" class="nav-link">Travel</a></li>
        <li><a href="#art" class="nav-link">Art</a></li>
        <li><a href="#food" class="nav-link">Food</a></li>
      </ul>
    </nav>
  </div>
</header>
<div class="container">
  <!-- Fashion -->
  <div id="fashion">
    <section>
      <h1 class="section-title">Fashion</h1>
    </section>
  </div>
  <!-- Travel -->
  <div id="travel">
    <section>
      <h1 class="section-title">Travel</h1>
    </section>
  </div>
  <!-- Art -->
  <div id="art">
    <section>
      <h1 class="section-title">Art</h1>
    </section>
  </div>
  <!-- Food -->
  <div id="food">
    <section>
      <h1 class="section-title">Food</h1>
    </section>
  </div>
</div>
<!-- /.container -->
<footer>
  <small>Copyright © noID All Rights Reserved.</small>
</footer>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
$(function() {

  // #で始まるアンカーをクリックした場合の処理
  $('a[href^=#]').click(function() {

    // スクロールの速度
    var speed = 400; // ミリ秒

    // アンカーの値取得
    var href = $(this).attr("href");

    // 移動先を取得
    var target = $(href == "#" || href == "" ? 'html' : href);

    // 移動先を数値で取得
    var position = target.offset().top;

    // スムーススクロール
    $('body,html').animate({
      scrollTop: position
    }, speed, 'swing');

    return false;
  });

});
</script>
</body>

</html>

demo

次のソースコードは、

var target = $(href == "#" || href == "" ? 'html' : href);

以下のように記述することもできます。

if(href == "#" || href == "") {
  var target = $('html')
} else {
  var target = $(href)
};

下記ソースコードは、WebKit では body、それ以外のブラウザでは html のように両方を指定してスクロールイベントを設定しています。

$('body,html').animate({
  scrollTop: position
}, speed, 'swing');

ですが、両方指定するとコールバック関数を指定している場合、コールバック関数が2回呼ばれることになります。

そこで、スクロールイベントで使うのはbodyなのかhtmlなのかをブラウザで判別して、分岐処理を行う必要が生じます。

var isHtmlScroll = (function() {
  var html = $('html'),
  top = html.scrollTop();
  var el = $('<div/>').height(10000).prependTo('body');
  html.scrollTop(10000);
  var rs = !!html.scrollTop();
  html.scrollTop(top);
  el.remove();
  return rs;
})();

$(isHtmlScroll ? 'html' : 'body').animate({
  scrollTop: position
}, speed, 'swing');

「iPhoneで従来のブラウザ判定ではスクロールが上手く動作しない」場合には、以下のようにして分岐処理をすることができます。

var scrollTag = ( window.chrome || 'WebkitAppearance' in document.documentElement.style )? 'body' : 'html';

$(scrollTag).animate({
  scrollTop: position
}, speed, 'swing');