Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit a693167

Browse files
ollelauribostromsagirk
authored andcommitted
refactor: Use IntersectionObserver in Layout component (#168)
This might need a bit of tweaking so consider it a WIP. The idea is that instead of calculating the hero offset in each animation frame - we can use the IntersectionObserver API. We are notified each time the intersection changes and when a `.side-nav__title` intersects with the hero banner, we apply some white color. Should offer some performance benefits and might also help solve #86. Seems like the [browser support is pretty good](https://caniuse.com/#feat=intersectionobserver), so this should work out of the box in most browsers. What are your thoughts on this?
1 parent 3a82dab commit a693167

File tree

3 files changed

+25
-17
lines changed

3 files changed

+25
-17
lines changed

src/components/layout.css

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ body {
1515
padding-top: var(--nav-height);
1616

1717
/* Set in JavaScript */
18-
--magic-hero-number: 365px;
19-
2018
--banner-clip: polygon(0 0, 100% 0, 100% calc(100% - 72px), 0 100%);
2119
--banner-gradient: linear-gradient(to right, var(--purple9), var(--blue7));
2220
--nav-height: 6.2rem;
@@ -239,22 +237,12 @@ main {
239237
}
240238

241239
.side-nav__title {
242-
background-attachment: fixed;
243-
-webkit-background-clip: text;
244-
background-clip: text;
245-
background-image: linear-gradient(to top, rgba(0, 0, 0, 1) 49%, rgba(255, 255, 255, 1) 51%);
246-
background-position: 0 calc(-50vh + var(--magic-hero-number));
247-
background-size: 100% 100vh;
248-
color: white;
249-
/* Force new paint layer in Firefox for rendering bug with background clip position sticky */
250-
filter: opacity(0.9);
240+
color: #000;
251241
font-weight: 200;
252242
letter-spacing: 2px;
253243
margin: 2.8rem 0 2.4rem;
254244
position: sticky;
255-
-webkit-text-fill-color: transparent;
256245
top: 2.8rem;
257-
will-change: background-position;
258246
z-index: 999;
259247
}
260248

src/components/layout.tsx

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,30 @@ type Props = {
1616
const Layout = ({ children, title, description, img }: Props) => {
1717
const prevOffset = useRef(-1);
1818

19-
// Header hero number CSS varaiable.
19+
useEffect(() => {
20+
if ('IntersectionObserver' in window) {
21+
setupObserver();
22+
} else {
23+
// Fallback for browsers without IntersectionObserver support
24+
magicHeroNumber();
25+
}
26+
});
27+
28+
const setupObserver = () => {
29+
const root = document.querySelector('.side-nav');
30+
const options = { root, threshold: 0.5, rootMargin: '-93px 0px 0px 0px' };
31+
const observer = new IntersectionObserver(onIntersectionChange, options);
32+
const targets = document.querySelectorAll('.side-nav__title');
33+
targets.forEach((target: Element) => observer.observe(target));
34+
};
35+
36+
const onIntersectionChange = (entries: IntersectionObserverEntry[]) => {
37+
entries.forEach((entry: IntersectionObserverEntry) => {
38+
const element = entry.target as HTMLElement;
39+
element.style.color = entry.isIntersecting ? '#000' : '#fff';
40+
});
41+
};
42+
2043
const magicHeroNumber = () => {
2144
if (typeof window === 'undefined') {
2245
return;
@@ -30,8 +53,6 @@ const Layout = ({ children, title, description, img }: Props) => {
3053
window.requestAnimationFrame(magicHeroNumber);
3154
};
3255

33-
useEffect(magicHeroNumber);
34-
3556
return (
3657
<>
3758
<SEO title={title} description={description} img={img} />

src/components/mobile.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@
148148
padding-left: 3.2rem;
149149
margin: 2.4rem 0 3.2rem;
150150
top: calc(var(--nav-height) + 12px);
151-
background-position: 0 calc(-50vh + var(--magic-hero-number) - 32px);
152151
}
153152

154153
.article-reader {

0 commit comments

Comments
 (0)