Skip to content

Commit d56a9d4

Browse files
Make navigation always sticky, remove headroom.js (#1356)
The nav was using headroom.js to hide on scroll-down and reappear on scroll-up. We're switching to a permanently-pinned nav The "scrolled past top" state (used for a subtle drop-shadow under the nav) is now detected with a 1px sentinel element + IntersectionObserver instead of headroom's scroll listener (same visual, no library). Also: - Add `scroll-padding-block-start` so in-page anchor links account for the sticky nav. - Disable the shadow transition under `prefers-reduced-motion`. - Remove now-dead `body:has(.fl-landing-get) .headroom-unpinned` override. - Drop headroom.js dependency.
1 parent c523dc3 commit d56a9d4

6 files changed

Lines changed: 53 additions & 47 deletions

File tree

media/css/cms/components/flare26-navigation.css

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
* and preferred-color-scheme fallback, in case a class isn't provided.
1717
*/
1818

19+
html {
20+
scroll-padding-block-start: var(--fl-navigation-menu-height);
21+
}
22+
1923
.fl-header {
2024
background-color: var(--fl-theme-background);
2125
color: var(--fl-theme-color-text);
@@ -28,6 +32,15 @@
2832
position: static;
2933
}
3034

35+
/* IntersectionObserver target for detecting scroll-past-top — see flare-navigation.es6.js */
36+
.fl-header-sentinel {
37+
block-size: 1px;
38+
inline-size: 1px;
39+
inset-block-start: 0;
40+
pointer-events: none;
41+
position: absolute;
42+
}
43+
3144
.fl-header a {
3245
text-decoration: none;
3346
}
@@ -380,38 +393,34 @@
380393
--fl-navigation-menu-height: 67px;
381394
}
382395

383-
.fl-header.headroom {
396+
.fl-header.enable-sticky {
384397
inset-block-start: 0;
385398
position: sticky;
386-
transition:
387-
transform 200ms linear,
388-
box-shadow 200ms linear;
399+
transition: box-shadow 200ms ease-out;
389400
z-index: 100;
390401
}
391402

392-
.fl-header.headroom-pinned {
393-
transform: translateY(0%);
403+
@media (prefers-reduced-motion: reduce) {
404+
.fl-header.enable-sticky {
405+
transition: none;
406+
}
394407
}
395408

396-
.fl-header.headroom-pinned.headroom-not-top {
409+
.fl-header.enable-sticky.is-scrolled {
397410
box-shadow:
398411
0 0 6px 1px rgba(29, 17, 51, 0.04),
399412
0 0 var(--token-spacing-sm) 2px rgba(9, 32, 77, 0.12),
400413
0 0 5px -3px rgba(29, 17, 51, 0.12);
401414
}
402415

403-
.fl-header.headroom-pinned.headroom-not-top .fl-menu-panel {
416+
.fl-header.enable-sticky.is-scrolled .fl-menu-panel {
404417
box-shadow:
405418
0 6px 6px 1px rgba(29, 17, 51, 0.04),
406419
0 var(--token-spacing-sm) var(--token-spacing-sm) 2px
407420
rgba(9, 32, 77, 0.12),
408421
0 5px 5px -3px rgba(29, 17, 51, 0.12);
409422
}
410423

411-
.fl-header.headroom-unpinned {
412-
transform: translateY(-100%);
413-
}
414-
415424
.fl-header.fl-header-no-menu {
416425
padding-block: 9px;
417426
}

media/css/cms/flare-navigation.css

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
--fl-navigation-menu-height: 58px;
1313
}
1414

15+
html {
16+
scroll-padding-top: var(--fl-navigation-menu-height);
17+
}
18+
1519
/* ================================================
1620
Header Base Styles
1721
================================================ */
@@ -27,6 +31,15 @@
2731
position: static;
2832
}
2933

34+
/* IntersectionObserver target for detecting scroll-past-top — see flare-navigation.es6.js */
35+
.fl-header-sentinel {
36+
position: absolute;
37+
top: 0;
38+
width: 1px;
39+
height: 1px;
40+
pointer-events: none;
41+
}
42+
3043
.fl-header a {
3144
text-decoration: none;
3245
}
@@ -364,31 +377,27 @@
364377
padding: 0;
365378
}
366379

367-
.fl-header.headroom {
380+
.fl-header.enable-sticky {
368381
position: sticky;
369382
top: 0;
370383
z-index: 100;
371-
transition: transform 200ms linear, box-shadow 200ms linear;
384+
transition: box-shadow 200ms ease-out;
372385
}
373386

374-
.fl-header.headroom-pinned {
375-
transform: translateY(0%);
376-
387+
@media (prefers-reduced-motion: reduce) {
388+
.fl-header.enable-sticky {
389+
transition: none;
390+
}
377391
}
378392

379-
.fl-header.headroom-pinned.headroom-not-top {
393+
.fl-header.enable-sticky.is-scrolled {
380394
box-shadow: 0 0 6px 1px rgba(29, 17, 51, 0.04), 0 0 8px 2px rgba(9, 32, 77, 0.12), 0 0 5px -3px rgba(29, 17, 51, 0.12);
381395
}
382396

383-
.fl-header.headroom-pinned.headroom-not-top .fl-menu-panel {
397+
.fl-header.enable-sticky.is-scrolled .fl-menu-panel {
384398
box-shadow: 0 6px 6px 1px rgba(29, 17, 51, 0.04), 0 8px 8px 2px rgba(9, 32, 77, 0.12), 0 5px 5px -3px rgba(29, 17, 51, 0.12);
385399
}
386400

387-
388-
.fl-header.headroom-unpinned {
389-
transform: translateY(-100%);
390-
}
391-
392401
.fl-header.fl-header-no-menu {
393402
padding-block: 9px;
394403
}

media/css/cms/pages/flare26-landing-get-page.css

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,6 @@
207207
}
208208

209209
@media (--viewport-md-up) {
210-
/* Keep nav always visible on scroll for this page */
211-
body:has(.fl-landing-get) .fl-header.headroom-unpinned {
212-
transform: translateY(0%);
213-
}
214-
215210
.fl-landing-get .c-intro-download {
216211
align-items: flex-start;
217212
}

media/js/cms/flare-navigation.es6.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,23 @@
66

77
// Sticky header
88
import { createFocusTrap } from 'focus-trap';
9-
import Headroom from 'headroom.js';
109

1110
(function () {
1211
const headerEl = document.querySelector('.fl-header.enable-sticky');
1312

1413
if (headerEl) {
15-
const headroomInstance = new Headroom(headerEl, {
16-
offset: 80,
17-
classes: {
18-
pinned: 'headroom-pinned',
19-
unpinned: 'headroom-unpinned',
20-
notTop: 'headroom-not-top',
21-
notBottom: 'headroom-not-bottom'
22-
}
14+
const sentinel = document.createElement('div');
15+
sentinel.className = 'fl-header-sentinel';
16+
sentinel.setAttribute('aria-hidden', 'true');
17+
headerEl.parentNode.insertBefore(sentinel, headerEl);
18+
19+
const observer = new IntersectionObserver(function (entries) {
20+
headerEl.classList.toggle(
21+
'is-scrolled',
22+
!entries[0].isIntersecting
23+
);
2324
});
24-
headroomInstance.init();
25+
observer.observe(sentinel);
2526
}
2627

2728
// Hamburger menu

package-lock.json

Lines changed: 0 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
"copy-webpack-plugin": "^14.0.0",
1919
"css-loader": "^7.1.4",
2020
"css-minimizer-webpack-plugin": "^8.0.0",
21-
"headroom.js": "^0.12.0",
2221
"mini-css-extract-plugin": "^2.10.2",
2322
"postcss": "^8.5.14",
2423
"postcss-custom-media": "^10.0.2",

0 commit comments

Comments
 (0)