少しスクロールしたら出てきて、特定の箇所までスクロールするとその場所で留まる上へ戻るボタン

  • 5
    Like
  • 1
    Comment

そもそも上へ戻るボタンの必要性について懐疑的ですが、こういうデザインをよくもらうので書いてみました。

サンプル

上へ戻るボタンサンプル

HTML

index.html
<footer>
    <a id="btn_pagetop" href="javascript:void(0);">^</a>
    <p>フッタ</p>
</footer>

Sass

ここの #btn_pagetop の素は留まっている状態、.hide が付くとボタンが隠れている状態、.fixed が付くと固定されている状態、それぞれの位置を指定します。

pagetop.sass
footer
    position: relative
#btn_pagetop
    width: 60px
    height: 60px
    margin-bottom: 20px
    display: block
    position: absolute
    top: 0
    bottom: auto
    right: 20px
    z-index: 1

    &.hide, &.fixed
        top: auto
        bottom: 0
        +transition-property(transform)
        +transition-duration(.3s)
        +transition-delay(0s)
        +transition-timing-function(ease)
    &.hide
        position: fixed
        +transform(translateY(150px))
    &.fixed
        position: fixed

CoffeeScript

bottom に留めたい場所を指定します。今回はフッタの高さ - ボタンの高さ - ボタンの margin-bottom としています。
body の高さ - スクロール位置 - ウィンドウの高さが、留めたい場所よりも少ない場合に .hide.fixed を解き放って素の状態とし、スクロール位置がウィンドウの高さ / 2 を超えた場合に .fixed を付けて固定し、それ以外は .hide を付けて隠します。

pagetop.coffee
pagetop =
    init: ->
        @$window = $(window)
        @$document = $(document)
        @$body = $('body')
        @$btn = $('#btn_pagetop')
        @bottom = $('footer').innerHeight() - @$btn.innerHeight() - parseInt(@$btn.css('margin-bottom'))
        @$btn.on 'click', ->
            $('html, body').animate({scrollTop: 0}, 1000)
            return
        @$window.scroll ->
            pagetop.fire()
            return
        @fire()
        return

    fire: ->
        scroll = @$document.scrollTop()
        window_height = @$window.innerHeight()
        if @$body.innerHeight() - scroll - window_height < @bottom
            @$btn.removeClass('hide fixed')
        else if scroll > window_height / 2
            @$btn.removeClass('hide').addClass('fixed')
        else
            @$btn.removeClass('fixed').addClass('hide')
        return
$ ->
    pagetop.init()
    return

生成された JavaScript も置いておきます。

pagetop.js
(function() {
  var pagetop;

  pagetop = {
    init: function() {
      this.$window = $(window);
      this.$document = $(document);
      this.$body = $('body');
      this.$btn = $('#btn_pagetop');
      this.bottom = $('footer').innerHeight() - this.$btn.innerHeight() - parseInt(this.$btn.css('margin-bottom'));
      this.$btn.on('click', function() {
        $('html, body').animate({
          scrollTop: 0
        }, 1000);
      });
      this.$window.scroll(function() {
        pagetop.fire();
      });
      pagetop.fire();
    },
    fire: function() {
      var scroll, window_height;
      scroll = this.$document.scrollTop();
      window_height = this.$window.innerHeight();
      if (this.$body.innerHeight() - scroll - window_height < this.bottom) {
        this.$btn.removeClass('hide fixed');
      } else if (scroll > window_height / 2) {
        this.$btn.removeClass('hide').addClass('fixed');
      } else {
        this.$btn.removeClass('fixed').addClass('hide');
      }
    }
  };

  $(function() {
    pagetop.init();
  });

}).call(this);