lab004: Unwrapping the Scrolling Web APIs
July 25, 2022
My interest in the scrolling web APIs was piqued by a Stack Overflow question about how to scroll horizontally through icons with a mouse wheel. This question popped the lid open on a chest full of related questions that I had been meaning to find the answers to. On this website, for instance, I ran into issues trying to create a footer that would either be visible in an absolute position at the bottom if the page content was smaller than 100vh, or would come into view when the page content was larger than 100vh and the user scrolled down to the end of the page.
I would also like to learn how to animate on scroll, whether it's parallax or non-parallax animation; how to build an infinite scroll experience; and even just simply how to scroll (rather than jump) to a specific element.
When the button is clicked, the function below is fired:
const handleScroll = () => {
window.scroll({
top: 500,
behavior: 'auto',
})
}
const handleScroll = () => {
window.scroll({
top: 500,
behavior: 'auto',
})
}
We access the global ‘window’ object, drill down into its ‘scroll’ function, then provide it with an options object. top: 500
makes the 500th pixel on the y-axis the new top of the web view. Remember that the the origin of the webpage is at the top left corner of the page, so moving down the y-axis results in an increasing positive value. The behavior: smooth
makes the movement animate smoothly vs. jumping suddenly.
Horizontal Scrolling
Below is a containing div filled with content that overflows its width, resulting in a horizontal scrollbar. Try to scroll left and right with your mouse wheel within the containing div. Pretty cool huh? Outside of the containg div, the mouse wheel acts as normal, scrolling vertically.
The containing div’s attributes include overflow-auto
, which is Tailwind for adding the CSS property overflow: auto
, which hides the overflow and provides a horizontal and/or vertical scrollbar as needed. The @wheel="handleWheel($event)
listens for the mouse scroll wheel to move, then invokes a function and passes the event in as a parameter (the $event
is provided by Vue because the code is in the template where we cannot easily get a reference to the event).
<div
bg-slate-300
dark:bg-slate-500
flex
gap-4
overflow-auto
px-4
py-6
w-full
@wheel="handleWheel($event)"
>
<div
bg-slate-300
dark:bg-slate-500
flex
gap-4
overflow-auto
px-4
py-6
w-full
@wheel="handleWheel($event)"
>
handleWheel
takes in the $event as a parameter, evt
. We then call preventDefault
on the event to prevent the mouse scroll wheel’s default behavior: scrolling vertically. To ignore the items inside the containing div and only target the element that the event listener is attached to, we use currentTarget
rather than target
. We then convert the scroll wheel’s default vertical scrolling into horizontal scrolling by accessing the scrollLeft
property on the currentTarget, which controls the position of the horizontal scroll, and finally add or subtract the vertical change in position, deltaY
to the currentTarget’s scrollLeft
property.
const handleWheel = (evt) => {
evt.preventDefault()
evt.currentTarget.scrollLeft += evt.deltaY
}
const handleWheel = (evt) => {
evt.preventDefault()
evt.currentTarget.scrollLeft += evt.deltaY
}
Discussion
In this lab, I learned that the scroll position (vertical and horizontal) can be controlled using window.scroll
. The (x, y) coordinates of the scrolling web API are simple enough thanks to the resemblance to the Cartesian coordinate system. As a next step, I’d like to experiment with vueUse’s useScroll utility, which provides reactive variables and convenient functions to enhance the web APIs.
Horizontal scrolling, which I thought would much more difficult to implement, was actually a breeze. I use Trello often, and Trello has a wonderful horizontally scrolling UI design; I find that the ability to organize things on a horizontal axis beyond the screen’s boundaries is agreeably intuitive. A couple things Trello does that I’d like to explore is how it scrolls horizontally using the left/right wheel click, and how it scrolls horizontally when pressing “shift” and moving the mouse wheel “normally”, i.e. rolling it forwards and backwards.
Super cool stuff! Onwards, friends! DannyDevs out…