CATEGORIES:CSS JAVA JQUERY
スクロールしたらページ上段へ戻るボタンを作る#02

SAMPLE PAGE

この枠の中を、下へスクロールしてみる。

少し下がると、右下に円が出る。円を押すと、先頭へ戻る。

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

↓

いちばん下。円を押してみる。

円が大小に動き、外へ広がる輪が消えていくボタンで、スクロールすると右下に出て、押すと先頭へゆっくり戻る方法。大きさ・色・速さは数字の変更だけで調整できる。

前回は、文字のボタンをフェードインで出していたのだが、これを円の動きに変え、戻るときの動きもゆっくり始まってゆっくり止まるようにする。

今回は、円のボタンと、ゆっくり戻る動きの組み込み編。

RELATED スクロールしたらページ上段へ戻るボタンを表示

動きは次のとおり。

  • 200px より下へスクロールすると、右下にボタンがフェードインする。先頭に戻ると消える
  • 円は1.2秒で大小に1往復し、外へ広がる輪(2重)が消えていく
  • 押すと、先頭へスクロールする。ゆっくり始まってゆっくり止まる
  • 戻る時間は距離に合わせて変わる(1.2〜2.5秒)
  • 戻っている途中にホイール・タッチ・キー操作をしたら、その場で止まる

jQuery を使う。WordPress 以外のサイトでもそのまま使える。

HTML

</body> の直前(WordPress なら footer.php)に配置。

<!-- ページ上段へ戻るボタン:スクロールすると右下に円が出る → 押すと先頭へゆっくり戻る -->
<p id="page-top"><a href="#" aria-label="ページの先頭へ戻る"><span class="page-top-dot"><i class="page-top-ring"></i></span></a></p>

※ href="#" なので、JavaScript が動かない環境でも、押せば先頭へ移動する

CSS

<style> の中、または CSS ファイルに配置。

/* ===== ここから CSS ===== */

/* ボタン全体:画面の右下に固定 */
#page-top {
  --pt-size: 14px;      /* ★ 円の大きさ(小さいときの直径) */
  --pt-scale: 1.5;      /* ★ 円が大きくなるときの倍率 */
  --pt-ring: 2.6;       /* ★ 広がる輪(残像)の倍率。大きいほど遠くまで広がる */
  --pt-ring-alpha: .45; /* ★ 輪の最初の濃さ(0〜1) */
  --pt-speed: 1.2s;     /* ★ 円が大小1往復する時間。小さいほど速い */
  --pt-color: #A6A6A6;  /* ★ 円の色 */
  --pt-hover: #59443C;  /* ★ マウスを乗せたときの円の色 */
  --pt-right: 40px;     /* ★ 画面の右端から円までの距離 */
  --pt-bottom: 90px;    /* ★ 画面の下端から円までの距離 */
  --pt-pad: 12px;       /* 押せる範囲を広げる余白(円の周り) */
  position: fixed;
  right: calc(var(--pt-right) - var(--pt-pad));
  bottom: calc(var(--pt-bottom) - var(--pt-pad));
  z-index: 100;
  margin: 0;
}

/* 円は小さいので、押せる範囲を円の周りに広げる */
#page-top a {
  display: block;
  padding: var(--pt-pad);
}

/* 円の入れ物(大きさは動かさない)。::before = 本体の円、::after と .page-top-ring = 広がる輪 */
.page-top-dot {
  position: relative;
  display: block;
  width: var(--pt-size);
  height: var(--pt-size);
}

.page-top-dot::before,
.page-top-dot::after,
.page-top-ring {
  content: "";
  position: absolute;
  inset: 0;
  display: block;
  border-radius: 50%;
  background: var(--pt-color);
  pointer-events: none;
  transition: background-color .3s;
}

/* 本体の円:大小に動く */
.page-top-dot::before {
  animation: pt-core var(--pt-speed) ease-in-out infinite;
}

/* 輪:広がりながら消える。2つを半周期ずらして、残像を2重にする */
.page-top-dot::after,
.page-top-ring {
  opacity: 0;
  animation: pt-ring var(--pt-speed) ease-out infinite;
}

.page-top-ring {
  animation-delay: calc(var(--pt-speed) / -2);
}

/* マウスを乗せたとき */
#page-top a:hover .page-top-dot::before,
#page-top a:hover .page-top-dot::after,
#page-top a:hover .page-top-ring {
  background: var(--pt-hover);
}

@keyframes pt-core {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(var(--pt-scale)); }
}

@keyframes pt-ring {
  0%   { transform: scale(1); opacity: var(--pt-ring-alpha); }
  100% { transform: scale(var(--pt-ring)); opacity: 0; }
}

/* OSで「視差効果を減らす」設定のときは、円を動かさない(円だけ表示) */
@media (prefers-reduced-motion: reduce) {
  .page-top-dot::before,
  .page-top-dot::after,
  .page-top-ring { animation: none; }
}

/* ===== ここまで CSS ===== */

JavaScript

HTML の後ろ(</body> の直前、HTML の下)に配置。jQuery をすでに読み込んでいる場合は、1行目の読み込みは不要。

<!-- jQuery(アニメーションを使うため slim 版ではなく通常版)。すでに読み込んでいる場合は不要 -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

<script>
/* ===== JavaScript =====
   ・200px より下へスクロールしたら、ボタンがフェードインする。上へ戻るとフェードアウト
   ・ボタンを押すと、先頭へスクロール。ゆっくり始まってゆっくり止まる
   ・戻る時間は距離に合わせて変わる(最短 MIN_TIME、最長 MAX_TIME)
   ・戻っている途中にホイール・タッチ・キー操作をしたら、すぐ止める */
$(function () {
  var SHOW_AT = 200;    /* ★ ボタンを出すスクロール量(px) */
  var MIN_TIME = 1200;  /* ★ 戻る時間の最短(ミリ秒) */
  var MAX_TIME = 2500;  /* ★ 戻る時間の最長(ミリ秒) */
  var SPEED = 0.8;      /* ★ 距離1pxあたりの時間(ミリ秒)。大きいほどゆっくり */

  var $btn = $('#page-top');
  $btn.hide();

  /* ゆっくり始まってゆっくり止まる動き(jQuery には標準で入っていないので自分で足す) */
  $.easing.easeInOutQuint = function (p) {
    return p < 0.5 ? 16 * p * p * p * p * p : 1 - Math.pow(-2 * p + 2, 5) / 2;
  };

  /* 表示・非表示は、状態が変わったときだけ切り替える */
  var visible = false;
  $(window).on('scroll', function () {
    var show = $(this).scrollTop() > SHOW_AT;
    if (show === visible) { return; }
    visible = show;
    if (show) {
      $btn.stop(true, true).fadeIn();
    } else {
      $btn.stop(true, true).fadeOut();
    }
  });

  /* 押したら先頭へ。距離に合わせて時間を変える */
  $btn.on('click', function () {
    var y = $(window).scrollTop();
    var time = Math.min(MAX_TIME, Math.max(MIN_TIME, y * SPEED));
    $('html, body').stop(true).animate({ scrollTop: 0 }, time, 'easeInOutQuint');
    return false;
  });

  /* 戻っている途中に操作が入ったら、すぐ止める */
  $(window).on('wheel touchstart keydown', function () {
    $('html, body').stop(true);
  });
});
</script>

※ jQuery は slim 版ではなく通常版を使うこと(slim 版には animate と fadeIn が入っていない) ※ $.easing.easeInOutQuint は、jQuery に標準で入っていないので、自分で足している。jQuery 1.8 以降なら、そのまま動く

調整するときの変更箇所

調整するときの変更箇所は次のとおり。

変えたいもの変更する場所
円の大きさCSS の --pt-size
円が大きくなる倍率CSS の --pt-scale
輪の広がり・濃さCSS の --pt-ring(広がり)、--pt-ring-alpha(濃さ)
円の速さCSS の --pt-speed(小さいほど速い)
円の色・マウスを乗せたときの色CSS の --pt-color、--pt-hover
画面の右・下からの位置CSS の --pt-right、--pt-bottom
ボタンを出すスクロール量JavaScript の SHOW_AT
戻る時間JavaScript の MIN_TIME、MAX_TIME、SPEED
戻る動き(ゆっくり始まる強さ)JavaScript の $.easing.easeInOutQuint の式

※ 戻る時間は、SPEED(距離1pxあたりの時間)をかけて決める。そのうえで MIN_TIME より短くならず、MAX_TIME より長くならない。たとえば 1000px 戻るなら、0.8ms × 1000 = 800ms だが、最短の 1200ms になる ※ OS で「視差効果を減らす」を選んでいる環境では、円は動かず、止まって表示される

前回の、文字のボタン(#page-top)がすでに入っている場合は、HTML・CSS・JavaScript の古い設定を先に削除すること。同じ #page-top を使っているので、残すと CSS が重なって崩れ、JavaScript が2重に動く。

表示環境によって動きの見え方が異なる場合があるため、本番に反映する前に確認してね。

NOTICES

  • 記事内容は実装させたものがほとんどですが自己責任で参考にしてください。

TO HEADER