From 2ad96483f2c81cab72dfd361d7a81275e62a5981 Mon Sep 17 00:00:00 2001 From: Jake Howard Date: Tue, 25 Jun 2024 21:18:33 +0100 Subject: [PATCH] Add scroll indicator --- src/hero/index.html | 3 +++ src/hero/index.js | 30 ++++++++++++++++++++++++++++++ src/hero/index.scss | 31 +++++++++++++++++++++++++------ 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/hero/index.html b/src/hero/index.html index c6aba91..091f809 100644 --- a/src/hero/index.html +++ b/src/hero/index.html @@ -10,6 +10,9 @@

Title

Details

+
+
+
diff --git a/src/hero/index.js b/src/hero/index.js index 1af7714..bcba853 100644 --- a/src/hero/index.js +++ b/src/hero/index.js @@ -1,5 +1,29 @@ 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) { const details = hero.querySelector("#details"); const heroIsVisible = @@ -26,4 +50,10 @@ window.addEventListener("load", function () { observer.observe(hero); handleDetailsStick(hero); + + window.addEventListener("resize", handleScrollIndicator); + window.addEventListener("scroll", handleScrollIndicator); + + // Initialize the indicator + handleScrollIndicator(); }); diff --git a/src/hero/index.scss b/src/hero/index.scss index ae4f2f6..2e430ea 100644 --- a/src/hero/index.scss +++ b/src/hero/index.scss @@ -10,6 +10,7 @@ $content-width: 85ch; $content-padding: 16px; $bleed-ratio: 0.2; $details-bg: black; +$details-padding: $content-padding; .hero { height: 50vh; @@ -21,8 +22,8 @@ $details-bg: black; background-color: transparentize($details-bg, 0.6); color: white; line-height: 1; - width: calc(100% - 2rem); - padding: 0 1rem; + width: calc(100% - ($details-padding * 2)); + padding: 0 $details-padding; transition-duration: 0.15s; transition-property: background-color; @@ -55,10 +56,9 @@ $details-bg: black; display: grid; width: 100%; max-width: 100vw; - grid-template-columns: 1fr min( - $content-width, - calc(100% - #{$content-padding} * 2) - ) 1fr; + grid-template-columns: + 1fr min($content-width, calc(100% - #{$content-padding} * 2)) + 1fr; & > * { grid-column: 2; @@ -88,3 +88,22 @@ $details-bg: black; 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; +}