1
Fork 0

Add scroll indicator

This commit is contained in:
Jake Howard 2024-06-25 21:18:33 +01:00
parent fe7347f647
commit 2ad96483f2
Signed by: jake
GPG key ID: 57AFB45680EDD477
3 changed files with 58 additions and 6 deletions

View file

@ -10,6 +10,9 @@
<h1>Title</h1> <h1>Title</h1>
<p>Details</p> <p>Details</p>
</div> </div>
<div id="scroll-indicator-container">
<div id="scroll-indicator"></div>
</div>
</div> </div>
</div> </div>
<div class="content-wrapper"> <div class="content-wrapper">

View file

@ -1,5 +1,29 @@
import _ from "underscore"; import _ from "underscore";
const SCROLL_INDICATOR = document.getElementById("scroll-indicator");
const CONTENT = document.querySelector(".content-wrapper");
function handleScrollIndicator() {
// How far down the page does the content start?
const initialScroll = CONTENT.getBoundingClientRect().top + window.scrollY;
const contentHeight = CONTENT.getBoundingClientRect().height;
// How far down the page do we consider the content "read"?
const scrollTarget = window.innerHeight * 0.75;
const scrolled =
(window.scrollY - initialScroll + scrollTarget) / contentHeight;
const scrolledPercentage = clamp(scrolled * 100, 0, 100);
SCROLL_INDICATOR.style.width = `${scrolledPercentage.toFixed(2)}%`;
}
function clamp(n, min, max) {
return Math.min(Math.max(n, min), max);
}
function handleDetailsStick(hero) { function handleDetailsStick(hero) {
const details = hero.querySelector("#details"); const details = hero.querySelector("#details");
const heroIsVisible = const heroIsVisible =
@ -26,4 +50,10 @@ window.addEventListener("load", function () {
observer.observe(hero); observer.observe(hero);
handleDetailsStick(hero); handleDetailsStick(hero);
window.addEventListener("resize", handleScrollIndicator);
window.addEventListener("scroll", handleScrollIndicator);
// Initialize the indicator
handleScrollIndicator();
}); });

View file

@ -10,6 +10,7 @@ $content-width: 85ch;
$content-padding: 16px; $content-padding: 16px;
$bleed-ratio: 0.2; $bleed-ratio: 0.2;
$details-bg: black; $details-bg: black;
$details-padding: $content-padding;
.hero { .hero {
height: 50vh; height: 50vh;
@ -21,8 +22,8 @@ $details-bg: black;
background-color: transparentize($details-bg, 0.6); background-color: transparentize($details-bg, 0.6);
color: white; color: white;
line-height: 1; line-height: 1;
width: calc(100% - 2rem); width: calc(100% - ($details-padding * 2));
padding: 0 1rem; padding: 0 $details-padding;
transition-duration: 0.15s; transition-duration: 0.15s;
transition-property: background-color; transition-property: background-color;
@ -55,10 +56,9 @@ $details-bg: black;
display: grid; display: grid;
width: 100%; width: 100%;
max-width: 100vw; max-width: 100vw;
grid-template-columns: 1fr min( grid-template-columns:
$content-width, 1fr min($content-width, calc(100% - #{$content-padding} * 2))
calc(100% - #{$content-padding} * 2) 1fr;
) 1fr;
& > * { & > * {
grid-column: 2; grid-column: 2;
@ -88,3 +88,22 @@ $details-bg: black;
max-width: calc(#{$content-width} + (100vw - #{$content-width}) * 0.5); max-width: calc(#{$content-width} + (100vw - #{$content-width}) * 0.5);
} }
} }
#scroll-indicator-container {
height: 5px;
width: 100%;
visibility: hidden;
position: relative;
top: 5px;
left: -$content-padding;
#scroll-indicator {
background-color: green;
height: 100%;
padding: 0 $content-padding;
}
}
.stuck #scroll-indicator-container {
visibility: visible;
}