What we’ll be making
Screen real estate is a precious commodity, especially on small displays such as mobile devices. One strategy to maximize content display is to dynamically control the display of the primary navigation depending on whether or not the user is scrolling up or scrolling down. It’s quite simple: scroll down on the page and the navigation recedes; scroll up on the page and the navigation reappears.
HTML Scaffolding and Basic Styles
We’ll start by creating our basic HTML elements and styling them. We’ll select a few colors as variables and set a variable for our nav-bar height. These steps could easily be accomplished without SCSS, but I prefer using Sass when possible.
Our HTML will consist of a primary
<main> container and a full-width, fixed-position
<nav> element at the very top of the page.
We’ll apply a fixed height,
300vh to the
<body> of our page for demonstration purposes (this will allow us to scroll as if our page were full of content).
We’ll pin our
<nav> element to the top of the browser window with
position: fixed and
top: 0. We’ll also make it the full width of the parent element with
width: 100% and key in our
$navBar-height variable for the
Animating Expand & Collapse
We’re going to jump ahead just a little bit with this next step. We know that we want to alternately hide and reveal the
<nav> element upon scrolling, and the simplest way to achieve this is by adding/removing a class that animates these changes in state.
For this, we’ll create two classes,
.open, each with a corresponding animation,
open. Note the
animation property of
forwards, which will keep the animation from reverting to its initial state upon finishing.
When we scroll down the page, we’d like our
<nav> element to fade and collapse upward simultaneously, and do the opposite when we scroll up. To achieve the fade, the animations for each class will alternately set the
opacity of the
<nav> element to fully transparent or opaque. To achieve the collapse and expand effect, we’ll set the position of the
<nav> element to either
top: 0 for
top: -$navBar-height for
In the collapsed position, the
<nav> element will be position absolutely above the browser window, rendering it effectively invisible. The
opacity animation will help make this a smooth transition, but is optional. In fact, this method could be used in conjunction with scroll events to animate any number of elements in all sorts of interesting ways.
Scroll Events & Animations
In order to toggle our expand/collapse classes, we’ll need to make them available to our script. We’ll do this by querying the
<nav> element by ID and set a variable,
navClasses with the native
.classList. This will now give us access to the current classes associated with our
To assign and remove these classes, we’ll define two functions that we’ll call either when scrolling down (collapse) or scrolling up (open).
These functions will make use of the native
.remove() methods to append or remove strings to the class list of its associated
Detecting Scroll Position
Now that we have our structure, styles, and animations in place, we’ll need a way to detect scroll position and call our class addition/removal functions.
We’ll start by creating a function that returns the position of the browser window along the Y-axis. When called, this function will return the value, in pixels, of the uppermost portion of the window (the point at which content is clipped on scroll).
scrollY is a native property of the browser window object2.
We’ll also need to keep track of our scroll position in order to check the current scroll value with the previous scroll value.
Calling Scroll Detect Functions
Next we’ll need to determine if a user has scrolled up or down on the page, and depending upon the case, call the respective function. We’ll do this by defining a function, which takes three functions as parameters, a home action (default state), down action, and up action.
A conditional statement will check if the current scroll position is lower or higher than the previous scroll position. If the current scroll position is greater than the previous, the user has scrolled down and we invoke the
down() function. If the current scroll position is less than the previous scroll position, the user has scrolled up and we invoke the
up() function. Lastly, we update the current scroll position.
Putting it All Together
The last step in our example is to create an event listener on the browser window, which invokes our
scrollDetect() function on scrolling events.
We’ll pass in our previously defined functions as arguments and voila! we have an interactive top-level navigation menu that expands and collapses on scroll events.
The expanding and collapsing navbar we’ve built is a practical example of listening to scroll events on the browser window. With this navigation menu, we can save precious screen real estate and remove interface distractions, which can be especially useful when consuming content on mobile devices.
Not only is this a useful interface component, it exposes the power of listening to native scroll events. With these methods, we have another tool with which we can call all sorts of interactive events.
Have feedback? Let me know; I’d be happy to hear it. [email protected]