Leo's dev blog

Prevent layout shift when toggling scrollbar on Window

Macbook pro on brown wooden table
Published on
/3 mins read/---

When will the scrollbar toggle? For example:

  • Open a Modal, Popup, or Drawer with a lot of content and prevent the user from scrolling the Window.
  • Toggle an Accordion or a Tab which expands the document height that leads to shows up the scrollbar.
  • ...

On Window devices, these cases will cause the layout shift. This is because the scrollbar is added to the Window which makes the Window's width smaller. This experience is not good for the user.

So let's prevent this layout shift with CSS.

The classic fix

CSS3global.css
html {
  overflow-y: scroll;
}

The classic fix is to add the overflow-y: scroll to the html element. This will always show the scrollbar on the Window (even if the content's height is smaller than the viewport's height).

The scrollbar in this case will always be visible. And its background turns to gray (if the Window isn't scrollable).

And of course, I don't recommend this solution cause I think it looks bad as the original problem.

Using view width

A better solution is to add an invisible margin-left to the html element with the same width as the scrollbar. This margin-left will be visible when the scrollbar is added to the Window and invisible when the scrollbar is removed from the Window.

But how to get the scrollbar's width ?

The answer is to use the vw unit.

If you don't know yet, vw or view width is a CSS unit just like px, %, or rem but it's relative to the viewport's width. 100vw is equivalent to 100% of the viewport's width (including the scrollbar), and 100% width (for the html element) is equivalent to 100% of the viewport's width (without the scrollbar)

So, we can calculate the width of the scrollbar by subtracting the 100% width from the 100vw width with the CSS's calc() function like this:

CSS3global.css
html {
  margin-left: calc(100vw - 100%);
}

The margin-left value will equal 0 when the Window isn't scrollable and equal to the scrollbar's width when the Window is scrollable.

NOTE

If you use this way to prevent layout shift and your application has a fixed's element (like a Popup or a Modal) which prevents Window scroll with the overflow-y: hidden style when it's open, then you should also add the margin-left to the fixed element as well.

For example:

CSS3global.css
html,
.popup-overlay,
.modal-overlay {
  margin-left: calc(100vw - 100%);
}

Another solution is to set the width of the html element to 100vw and prevent horizontal scroll:

CSS3global.css
html {
  width: 100vw;
  overflow-x: hidden;
}

This solution only makes sense if your application doesn't have to scroll horizontally (like a blog or a documentation website). And I'm using this in my blog, you can open the devtool and check the html styles to see it .

The no-code way

There are 2 ways to prevent layout shift without writing any CSS code:

  • The first one is to tell your users not to use Window device and to use a Mac or a Linux device instead

  • The second one is to just... leave it as it is, sometimes it's not a big deal, and your user doesn't actually care about that

If you have any other solutions, please let me know in the comments below.

Happy styling