Skip to content

Instantly share code, notes, and snippets.

@rolandtoth
Created April 19, 2018 15:33
Show Gist options
  • Save rolandtoth/0e9ab01e2723eada2890cfe41c8312be to your computer and use it in GitHub Desktop.
Save rolandtoth/0e9ab01e2723eada2890cfe41c8312be to your computer and use it in GitHub Desktop.
Pure CSS scroll-to-top
<div class="container" id="top">
<h1>Pure CSS scroll-to-top</h1>
<div class="intro">
<p>
A CSS-only solution to reveal a scroll-to-top link on scrolling down the page + animated scroll back to top.
</p>
<p>Browser requirements</p>
<ul>
<li>
<em><a href="https://caniuse.com/#search=position%3Asticky" target="_blank">position: sticky</a></em> for reveal</li>
<li>
<em><a href="https://caniuse.com/#search=scroll-behavior" target="_blank">scroll-behavior</a></em> for animated scroll
</li>
</ul>
<p>
Uses <em>position: fixed</em> fallback (scroll-to-top link always shows).
</p>
</div>
<input type="checkbox" id="dummy-content-toggle">
<label for="dummy-content-toggle">Toggle page height</label> &nbsp;
<input type="checkbox" id="fallback-toggle" onchange="this.checked ? document.documentElement.style.scrollBehavior = 'auto' : document.documentElement.removeAttribute('style');">
<label for="fallback-toggle">Simulate unsupported browser</label>
<div id="dummy-content">
<h3>Scroll down &#8595;</h3>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
<h3>No JavaScript...</h3>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
<h3>...less CPU burden.</h3>
<p>
Consectetur non proident adipisicing elit, sed non proident do eiusmod tempor incididunt ut labore sdfsdsd sdf et dolore magna aliqua. Duis aute irure dolor in reprehenderit in sdsdfsdf voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
<p>
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident.
Lorem ipsum dolor sit amet, consectetur non proident adipisicing elit, sed non proident do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
</div>
<div class="scrolltop-wrap">
<a href="#top">
<svg height="48" viewBox="0 0 48 48" width="48" xmlns="http://www.w3.org/2000/svg"><path id="scrolltop-bg" d="M0 0h48v48h-48z"/><path id="scrolltop-arrow" d="M14.83 30.83l9.17-9.17 9.17 9.17 2.83-2.83-12-12-12 12z"/></svg>
</a>
</div>
</div>

Pure CSS scroll-to-top

A CSS-only solution to reveal a scroll-to-top link only on scrolling down the page + animated scroll back to top.

Requires position: sticky and scroll-behavior: smooth browser support.

A Pen by rolandtoth on CodePen.

License.

html {
scroll-behavior: smooth;
}
body {
position: relative;
}
.scrolltop-wrap {
$size: 3rem;
$offsetBottom: 2rem;
$offsetRight: 3rem;
$scrollToRevealDistance: 25vh; // scroll offset to reveal scroll-to-top link
$color: #007bff;
box-sizing: border-box;
position: absolute;
top: $scrollToRevealDistance;
right: $offsetRight;
bottom: 0;
pointer-events: none;
// prevent extra page height if content is smaller than viewport
// Firefox only
@-moz-document url-prefix() {
clip: rect(0, $size, auto, 0);
}
a {
$offset: - ($size + $offsetBottom); // pull up + add a small bottom space
position: fixed; // fallback
position: sticky;
top: $offset;
width: $size;
height: $size;
margin-bottom: $offset;
transform: translateY(100vh); // push to bottom from top (when stuck)
backface-visibility: hidden;
display: inline-block;
text-decoration: none;
user-select: none;
pointer-events: all;
overflow: hidden;
svg {
display: block;
border-radius: 50%;
width: 100%;
height: 100%;
path {
transition: all 0.1s;
}
#scrolltop-bg {
fill: lighten($color, 10%);
}
#scrolltop-arrow {
fill: white;
transform: scale(0.66);
transform-origin: center;
}
}
&:hover {
#scrolltop-bg {
fill: $color;
}
}
}
}
// presentation styles
html {
overflow-y: scroll;
&::before {
content: "";
display: block;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: url("https://images.pexels.com/photos/62693/pexels-photo-62693.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260")
center center no-repeat;
background-size: cover;
filter: brightness(1.13) blur(2px);
}
}
body {
font-family: 'Raleway', sans-serif;
max-width: 40rem;
margin: 0 auto;
line-height: 2;
background: transparent;
}
.container {
position: relative;
padding: 2rem 2rem 6rem;
}
h1,
h2,
h3,
p {
margin-top: 2rem;
margin-bottom: 2rem;
}
.intro {
font-size: 1.16rem;
}
.intro a:hover {
text-decoration: underline;
}
#dummy-content p {
display: inline;
background: rgba(#b2b7bb, 0.5);
color: transparent;
user-select: none;
border-radius: 2px;
box-decoration-break: clone;
+ p {
&:before {
visibility: hidden;
content: ".";
display: block;
}
}
}
label {
display: inline-block;
line-height: 1;
padding: 0.7rem 0.84rem;
border: 1px solid rgba(#b2b7bb, 0.99);
border-radius: 2px;
cursor: pointer;
user-select: none;
transition: all 0.1s;
&:hover {
color: #1e8aff;
border-color: darken(#b2b7bb, 6%);
}
}
input[type="checkbox"] {
display: none;
}
input#dummy-content-toggle {
&:checked {
~ #dummy-content {
display: none;
}
~ label[for="dummy-content-toggle"] {
background: #1e8aff;
border-color: #1e8aff;
color: white;
}
}
}
input#fallback-toggle {
&:checked {
~ .scrolltop-wrap a {
position: fixed;
}
~ label[for="fallback-toggle"] {
background: #1e8aff;
border-color: #1e8aff;
color: white;
}
}
}
a {
color: #1e8aff;
}
ul {
margin-top: -1rem;
}
@media screen and (max-width: 721px) {
html {
font-size: 84%;
&::before {
background: #eff0f2;
}
}
.container {
padding: 1rem 1.5rem 2rem;
}
h1 {
font-size: 2.2rem;
}
h3 {
font-size: 1.5rem;
}
h1,
h2,
h3,
p {
margin-top: 1rem;
margin-bottom: 1rem;
}
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/css/bootstrap.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Raleway:300" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment