Sticky, or fixed, navigation is a popular design choice because it gives users persistent access to navigate the site. On the other hand, it takes up space on the page and sometimes covers content is a way that’s less than appealing.
A possible solution? Smart navigation.
Let’s define “smart navigation” as:
- Visible at the top of the page
- Visible when the user moves up the page (wherever they may have scrolled to)
- Hidden when the user moves down the page
Here’s an example of how that might work:
It‘s all the convenience of sticky positioning, with an added fullscreen benefit. This sort of smart navigation is already commonly (think of the URL bar in many mobile browsers), but is sometimes a hassle to implement without a library or plugin. So, in this article, we’ll discuss how to build one using CSS and vanilla JavaScript.
Side note: People have different definitions of what scrolling down a page means (imagine how some trackpad preferences scroll the page up when you move your fingers down). For the purposes of this article, scrolling down refers to moving towards the bottom of the page.
Let’s look at the code
Here’s some example HTML. Our smart navigation will be the
<nav> <div> Logo </div> <div> <a href="#">Link 1</a> <a href="#">Link 2</a> <a href="#">Link 3</a> <a href="#">Link 4</a> </div> </nav> <main> <!--Place the content of your page here--> </main>
It’s important to note that elements are only sticky relative to their parent container. The parent container of
The CSS for our smart navigation looks like this:
nav { position: sticky; top: 0; display: flex; flex-wrap: wrap; justify-content: space-between; padding: 1.5rem 2rem; background-color: #eaeaea; }
Now we need to detect when our user is scrolling the page and the direction of their scrolling. A user is scrolling down if the value of their last scroll position is less than the value of their current scroll position. Breaking the logic down, we’ll need to:
- Define a variable to store the previous scroll position
- Assign a variable to detect the current scroll position set to the scroll offset of the page
If the current scroll position is greater than the previous scroll position, then the user is scrolling downwards. Let’s call our function isScrollingDown:
let previousScrollPosition = 0; const isScrollingDown = () => { let currentScrolledPosition = window.scrollY || window.pageYOffset; let scrollingDown; if (currentScrolledPosition > previousScrollPosition) { scrollingDown = true; } else { scrollingDown = false; } previousScrollPosition = currentScrolledPosition; return scrollingDown; };
Here’s a visual representation of how this function works:
With this logic, we’re able to detect when the page is scrolling down so we can use this to toggle our nav styling:
const nav = document.querySelector('nav'); const handleNavScroll = () => { if (isScrollingDown()) { nav.classList.add('scroll-down'); nav.classList.remove('scroll-up') } else { nav.classList.add('scroll-up'); nav.classList.remove('scroll-down') } }
If the user is scrolling down, we’ll assign a .scroll-down class that contains our styling method for when the page is moving downward. We can update our
nav { /* default styling */ transition: top 500ms ease-in-out; } nav.scroll-up { top: 0; } nav.scroll-down { top: -100%; }
With this styling, the top property value of
Performance
Whenever we’re working with scroll event listeners, performance is something that should immediately come to mind. Right now, we’re calling our function every time the user scrolls the page, but we don’t need to detect each pixel movement.
For this case, we can implement a throttle function instead. A throttle function is a higher order function that acts as a timer for the function passed into it. If we throttle a scroll event with a timer of 250ms, the event will only be called every 250ms while the user scrolls. It’s a great way to limit the number of times we call the function, helping with the performance of the page.
David Corbacho goes deeper into throttle implementations in this article.
A simple throttle implementation in JavaScript looks like this:
// initialize a throttleWait variable var throttleWait; const throttle = (callback, time) => { // if the variable is true, don't run the function if (throttleWait) return; // set the wait variable to true to pause the function throttleWait = true; // use setTimeout to run the function within the specified time setTimeout(() => { callback(); // set throttleWait to false once the timer is up to restart the throttle function throttleWait = false; }, time); }
Then we can include our handleNavScroll function inside a throttle:
window.addEventListener("scroll", () => { throttle(handleNavScroll, 250) });
With this implementation, the handleNavScroll function is only called once every 250ms.
Accessibility
Whenever implementing a custom feature in JavaScript, we must always take accessibility into concern. One such issue is ensuring that
A way to ensure that
nav.scroll-up, nav:focus-within { top: 0; }
Unfortunately, the focus-within selector isn’t fully supported across all browsers. We can include a JavaScript fallback for it:
const handleNavScroll = () => { if (isScrollingDown() && !nav.contains(document.activeElement))) { nav.classList.add('scroll-down'); nav.classList.remove('scroll-up') } else { nav.classList.add('scroll-up'); nav.classList.remove('scroll-down') } }
In this updated function, we only apply the scroll-down class if the user is scrolling down the page and the
Another aspect of accessibility is the consideration that some users may not want to have any animation on the page. That’s something we can detect and respect with the prefers-reduced-motion CSS media query. We can update this method in JavaScript and prevent our function from running at all if a user prefers reduced motion:
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)"); window.addEventListener("scroll", () => { if (mediaQuery && !mediaQuery.matches) { throttle(handleNavScroll, 250) } });
Wrapping up
So, there we have it: a smart navigation implementation with plain CSS and vanilla JavaScript. Now users have persistent access to navigate the site without losing real estate in a way that blocks content.
Plus, the benefit of a custom implementation like this is that we get a delightful user experience that isn’t over-engineered or sacrifices open performance or accessibility.
The above is the detailed content of Creating a Smart Navbar With Vanilla JavaScript. For more information, please follow other related articles on the PHP Chinese website!

GooFonts is a side project signed by a developer-wife and a designer-husband, both of them big fans of typography. We’ve been tagging Google

Pavithra Kodmad asked people for recommendations on what they thought were some of the most timeless articles about web development that have changed their

Learning how to build GraphQL APIs can be quite challenging. But you can learn how to use GraphQL APIs in 10 minutes! And it so happens I've got the perfect

When a component lives in an environment where the data queries populating it live nearby, there is a pretty direct line between the visual component and the

Here's some legit CSS trickery from yuanchuan. There is this CSS property offset-path. Once upon a time, it was called motion-path and then it was renamed. I

Miriam Suzanne explains in a Mozilla Developer video on the subject.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

SAP NetWeaver Server Adapter for Eclipse
Integrate Eclipse with SAP NetWeaver application server.

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

Dreamweaver Mac version
Visual web development tools

MinGW - Minimalist GNU for Windows
This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.