そもそも上へ戻るボタンの必要性について懐疑的ですが、こういうデザインをよくもらうので書いてみました。
サンプル
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);