Skip to content

Commit

Permalink
Improve scroll-dependent navbar style
Browse files Browse the repository at this point in the history
The setup before was over complicated, because I tried to use
IntersectionObserver to check if navbar was intersecting with the main
element before styling it with a border etc.

This kind of worked, but it broke testing with Cypress because the
website was rendered inside an iframe, which the IntersectionObserver
API has issues when using implicit root and rootMargin, see
w3c/IntersectionObserver#283 (comment)
for details.

Now, I simplified it to get rid of IntersectionObserver. Now, the border
is applied when we detect that the page scroll is greater than the
navbar height.

Also, the navbar will get hidden every time the user scrolls down,
regardless of where in the page (before this commit, this only happened
after the top of the viewport intersected with the main element).
  • Loading branch information
phelipetls committed Apr 30, 2022
1 parent 991fadb commit 7770079
Showing 1 changed file with 10 additions and 33 deletions.
43 changes: 10 additions & 33 deletions assets/js/nav.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
const main = document.querySelector('main')
const nav = document.querySelector('[data-nav-container]')

nav.querySelector('a.active').scrollIntoView()
Expand All @@ -20,40 +19,9 @@ const navObserver = new IntersectionObserver(

navObserver.observe(nav)

let isMainIntersectingTop = false

const topObserver = new IntersectionObserver(
function (entries) {
const entry = entries[0]

isMainIntersectingTop = entry.isIntersecting

if (isMainIntersectingTop) {
nav.classList.add('border-b', 'border-divider')
} else {
nav.classList.remove('border-b', 'border-divider')

Object.assign(nav.style, {
position: 'fixed',
top: '0px',
})
}
},
{
rootMargin: '0px 0px -100%',
threshold: [0, 1],
}
)

topObserver.observe(main)

let lastScrollPosition = window.scrollY

function hideNav() {
if (!isMainIntersectingTop) {
return
}

if (isNavFullyVisible) {
Object.assign(nav.style, {
position: 'absolute',
Expand Down Expand Up @@ -91,7 +59,7 @@ function setNavPosition() {
const newScrollPosition = window.scrollY
const isScrollingDown = newScrollPosition > lastScrollPosition

const shouldHide = isScrollingDown && isMainIntersectingTop
const shouldHide = isScrollingDown

if (shouldHide) {
hideNav()
Expand All @@ -102,6 +70,14 @@ function setNavPosition() {
lastScrollPosition = Math.max(newScrollPosition, 0)
}

function setNavStyle() {
for (const className of ['border-b', 'border-divider']) {
nav.classList.toggle(className, window.scrollY > nav.offsetHeight)
}
}

setNavStyle()

let timeout

function handleScroll() {
Expand All @@ -111,6 +87,7 @@ function handleScroll() {

timeout = window.requestAnimationFrame(function () {
setNavPosition()
setNavStyle()
})
}

Expand Down

0 comments on commit 7770079

Please sign in to comment.