Browse Source

Add a "Back to top" button on mobile

This button only shows up on mobile (or small screens) and will appear
after the user has scrolled down at least two viewport-heights. The
Intersection Observer API is used to detect this with an invisible
"buffer" div, instead of attaching to scroll events.
merge-requests/61/head
Deimos 6 years ago
parent
commit
630ed4467f
  1. 13
      tildes/scss/_layout.scss
  2. 19
      tildes/scss/modules/_btn.scss
  3. 8
      tildes/scss/themes/_theme_base.scss
  4. 20
      tildes/static/js/behaviors/back-to-top-buffer.js
  5. 3
      tildes/tildes/templates/base.jinja2

13
tildes/scss/_layout.scss

@ -51,6 +51,19 @@ body {
} }
} }
#back-to-top-buffer {
// This is an invisible "buffer" for the "Back to top" button. It uses the
// Intersection Observer API to detect when the entire buffer has been
// scrolled off the screen, and will make the button visible at that point.
// So to have the button show up when the user has scrolled down at least two
// viewport heights, we set its height at 200vh.
height: 200vh;
position: absolute;
top: 0;
right: 0;
width: 1px;
}
#site-header { #site-header {
grid-area: header; grid-area: header;

19
tildes/scss/modules/_btn.scss

@ -68,3 +68,22 @@
border: 1px solid; border: 1px solid;
} }
} }
.btn-back-to-top {
position: fixed;
bottom: 0.4rem;
right: 0.4rem;
font-size: 0.5rem;
opacity: 0;
visibility: hidden;
transition: all 0.5s ease;
&.btn-back-to-top-visible {
@media (max-width: $size-md) {
opacity: 1;
visibility: visible;
}
}
}

8
tildes/scss/themes/_theme_base.scss

@ -111,6 +111,14 @@
} }
} }
.btn-back-to-top {
background-color: map-get($theme, "background-primary");
&:visited {
color: map-get($theme, "link");
}
}
.btn-comment-collapse { .btn-comment-collapse {
color: map-get($theme, "foreground-secondary"); color: map-get($theme, "foreground-secondary");
border-color: map-get($theme, "border"); border-color: map-get($theme, "border");

20
tildes/static/js/behaviors/back-to-top-buffer.js

@ -0,0 +1,20 @@
// Copyright (c) 2019 Tildes contributors <code@tildes.net>
// SPDX-License-Identifier: AGPL-3.0-or-later
$.onmount('[data-js-back-to-top-buffer]', function() {
// Uses the Intersection Observer API to observe when the div with ID
// back-to-top-buffer has been scrolled entirely out of the viewport,
// and adds the btn-back-to-top-visible class to the "Back to top" button
// at that point. If the buffer is scrolled back into the viewport, it
// removes the class, hiding the button again.
var callback = function(entries, observer) {
if (entries[0].isIntersecting) {
$(".btn-back-to-top").removeClass("btn-back-to-top-visible");
} else {
$(".btn-back-to-top").addClass("btn-back-to-top-visible");
}
};
this.intersectionObserver = new IntersectionObserver(callback);
this.intersectionObserver.observe(document.querySelector('#back-to-top-buffer'));
});

3
tildes/tildes/templates/base.jinja2

@ -126,6 +126,9 @@
</ul> </ul>
</footer> </footer>
<div id="back-to-top-buffer" data-js-back-to-top-buffer></div>
<a href="#" class="btn btn-sm btn-back-to-top">Back to top</a>
{% assets "javascript-third-party" -%} {% assets "javascript-third-party" -%}
<script type="text/javascript" src="{{ ASSET_URL }}"></script> <script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %} {% endassets %}

Loading…
Cancel
Save