From fc4046a9cf3069ed1424b86c68ac5390cd53b409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olle=20Lauri=20Bostr=C3=B6m?= Date: Sun, 3 Mar 2019 14:40:59 +0100 Subject: [PATCH] refactor: Use IntersectionObserver in Layout component --- src/components/layout.css | 14 +------------- src/components/layout.tsx | 27 ++++++++++++++++++++++++--- src/components/mobile.css | 1 - 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/components/layout.css b/src/components/layout.css index 9b36f3e6ae..91d5018a7c 100644 --- a/src/components/layout.css +++ b/src/components/layout.css @@ -15,8 +15,6 @@ body { padding-top: var(--nav-height); /* Set in JavaScript */ - --magic-hero-number: 365px; - --banner-clip: polygon(0 0, 100% 0, 100% calc(100% - 72px), 0 100%); --banner-gradient: linear-gradient(to right, var(--purple9), var(--blue7)); --nav-height: 6.2rem; @@ -239,22 +237,12 @@ main { } .side-nav__title { - background-attachment: fixed; - -webkit-background-clip: text; - background-clip: text; - background-image: linear-gradient(to top, rgba(0, 0, 0, 1) 49%, rgba(255, 255, 255, 1) 51%); - background-position: 0 calc(-50vh + var(--magic-hero-number)); - background-size: 100% 100vh; - color: white; - /* Force new paint layer in Firefox for rendering bug with background clip position sticky */ - filter: opacity(0.9); + color: #000; font-weight: 200; letter-spacing: 2px; margin: 2.8rem 0 2.4rem; position: sticky; - -webkit-text-fill-color: transparent; top: 2.8rem; - will-change: background-position; z-index: 999; } diff --git a/src/components/layout.tsx b/src/components/layout.tsx index 55173e3c5c..47d7f347b7 100644 --- a/src/components/layout.tsx +++ b/src/components/layout.tsx @@ -16,7 +16,30 @@ type Props = { const Layout = ({ children, title, description, img }: Props) => { const prevOffset = useRef(-1); - // Header hero number CSS varaiable. + useEffect(() => { + if ('IntersectionObserver' in window) { + setupObserver(); + } else { + // Fallback for browsers without IntersectionObserver support + magicHeroNumber(); + } + }); + + const setupObserver = () => { + const root = document.querySelector('.side-nav'); + const options = { root, threshold: 0.5, rootMargin: '-93px 0px 0px 0px' }; + const observer = new IntersectionObserver(onIntersectionChange, options); + const targets = document.querySelectorAll('.side-nav__title'); + targets.forEach((target: Element) => observer.observe(target)); + }; + + const onIntersectionChange = (entries: IntersectionObserverEntry[]) => { + entries.forEach((entry: IntersectionObserverEntry) => { + const element = entry.target as HTMLElement; + element.style.color = entry.isIntersecting ? '#000' : '#fff'; + }); + }; + const magicHeroNumber = () => { if (typeof window === 'undefined') { return; @@ -30,8 +53,6 @@ const Layout = ({ children, title, description, img }: Props) => { window.requestAnimationFrame(magicHeroNumber); }; - useEffect(magicHeroNumber); - return ( <> diff --git a/src/components/mobile.css b/src/components/mobile.css index ca37f4d7ce..380b4f31bd 100644 --- a/src/components/mobile.css +++ b/src/components/mobile.css @@ -148,7 +148,6 @@ padding-left: 3.2rem; margin: 2.4rem 0 3.2rem; top: calc(var(--nav-height) + 12px); - background-position: 0 calc(-50vh + var(--magic-hero-number) - 32px); } .article-reader {