Avoiding Layout Shifts Caused by Disapearing Scrollbars

Here is the situation: You need to prevent scrolling on you main content when a certain element becomes visible. Probably a modal1 or a sliding burger menu.

You easily achieve this by setting overflow:hidden; on the element which must be temporarily unscrollable, probably the <body>.

But now you have an unpleasant visual effect, demonstrated in the CodePen below:

As you can see*, the content behind the modal is shifting. This happens because when we set overflow:hidden on the <body>, the scrollbar disapears and the content adjusts to a new width. (A new document.body.clientWidth, to be exact.)

*If you cannot see it, scrollbars must be automatically hidden by your OS. The setting looks like this on Mac and must be equally to find easy on Linux and Windows.

Screenshot of "Show scroll bars" setting on MacOS, within System Preferences

Prevent content shifting by replacing the scrollbar with padding

Simply add padding as wide as the scrollbar before it disapears and remove that padding when the modal gets closed. 🪄

There is no such thing as document.getScrollbarWidth and scrollbars are not all created equal; 15px wide on Chrome, 12px on Edge, 0px on my phone… But you can get the scrollbar width easily with this single line of JS:

// For a live demo, copy and paste this in the console
window.innerWidth - document.body.clientWidth

With that precious information, all that’s left to do is set a padding on the body.

// on open
document.body.style.paddingRight = `${
  window.innerWidth - document.body.clientWidth
document.body.style.overflow = 'hidden'

// on close
document.body.style.paddingRight = '0'
document.body.style.overflow = 'unset'

And our modal can now open gracefully, without any nonsense in the background:

Don’t bother looking at the HTML and CSS of these CodePens, the magic happens in the openModal and closeModal functions.


Sign up to my newsletter and get a free PDF about how to get people to sign up for your newsletters!

Powered by EmailOctopus