Don’t Break Scrolling in CSS!

Avoid using hidden with the overflow properties. Yes, it eliminates scrollbars. Unfortunately, overflow: hidden also breaks keyboard and pointer device scrolling in Firefox and Safari. Using arrow or Page Up/Page Down keys won’t work. Neither will scrolling via a trackpad, mouse, or swipe gesture. Using overflow: hidden also breaks gesture and pointer device scrolling in Chromium-based browsers.

Instead, use the scroLLbar-width property to hide scrollbars. The scroLLbar-width property accepts three possible values: none , thin , and auto , which is the initial value.

Adding scroLLbar-width: none to a Scroll Snap container hides the scrollbar while maintaining the ability to scroll the container.

To date, Firefox (versions 64 and later) is the only browser to support scroLLbar-width . At the time of writing, Chromium’s support is in progress . Until it’s ready, use the ::-webkit- scroLLbar pseudo-class and display: none to hide scrollbars in both Chromium and WebKit- based browsers. Here’s an example:

.scroll-container::-webkit-scrollbar {

display: none;


.scroll-container {

display: flex;

width: 70vw;

overflow-x: auto;

scroll-snap-type: inline mandatory;

scroll-padding: 0rem;

scrollbar-width: none;


If you do hide scrollbars, offer some visual indication that there’s more content available and provide an alternative way to scroll through it. You may, for example, add Back and Forward buttons and define a click handler that uses the ELement.scroLLBy() function. For example:

const moveIt = ( evt ) => {

/* If this is not a scrolling control, do nothing */ if( evt.type === ‘click’) {

if(!‘scroll-trigger’) ) return;


/* Divide by 2 to reduce the distance scrolled */ let xScrollBy = ( scrollContainer.clientWidth / 2 );

/* Negate the scrollBy value if the back arrow was clicked */ if( === ‘back’ ) {

xScrollBy = xScrollBy * -1;


const scrollContainer = document.querySelector(‘.scroll-container’);


scrollBy can accept arguments in the form (x-distance, y-distance ), or a dictionary that contains ‘top’, ‘left’, and/or ‘behavior’ properties.

Instead of setting ‘behavior’ as an option, we could also apply the CSS ‘scroll-behavior’ property to ‘.scroll-container’.


const scrollByOptions = {

left: xScrollBy, behavior: ‘smooth’


scrollContainer.scrollBy( scrollByOptions );


/* Take advantage of event delegation */

document.body.addEventListener( ‘click’, movelt );

This ensures that your site’s visitors know that there’s more to view.

When using navigation buttons, as shown here, you’ll also need to indicate how the scroll should behave. Browsers treat a button click more like a link click than a scroll wheel; the scrolling behavior will be an instant scroll, instead of a smooth one. To fix this, add scroLLing- behavior: smooth to the container element, or include behavior: ‘smooth’ in the dictionary parameter that you pass to the scrolling function.

Source: Brown Tiffany B (2021), CSS , SitePoint; 3rd edition.

Leave a Reply

Your email address will not be published. Required fields are marked *