DEV Community

Cover image for Preventing the Layout Shift Caused by Scrollbars
Rashid Shamloo
Rashid Shamloo

Posted on

Preventing the Layout Shift Caused by Scrollbars

The Problem

When content overflows the page and the scrollbar shows up, the content is pushed/shifted to the left and vice versa, when the scrollbar disappears, the content is pushed/shifted to the right:

This annoying layout shift can be prevented in multiple ways. In this article, I will go over them one by one:

1. Always showing the scrollbars

This is the easiest and ugliest solution.

body {
  overflow-y: scroll;
}
Enter fullscreen mode Exit fullscreen mode

2. The scrollbar-gutter property

The scrollbar-gutter property has been made for this exact purpose. setting it to stable will preserve the space for the scrollbar and prevent the layout shift.

html {
  scrollbar-gutter: stable;
}
Enter fullscreen mode Exit fullscreen mode

BUT... it doesn't work in Safari and the scrollbar track will always be visible on your page which is not desirable.

*. A little note about 100vw and 100%

Before continuing to the next points, it is necessary to understand the difference between 100vw and 100%:

  • 100vw : Full width including the scrollbar.
  • 100% : Full width excluding the scrollbar.

3. Shifting the content to the right

When the scrollbar is not showing, 100vw and 100% are equal, and when the scrollbar is showing, the difference between them is equal to the width of the scrollbar.

So if we shift the content to the right by the difference of 100vw and 100%, we can prevent the layout shift. To achieve it we can use padding-left on the parent/container element:

.container {
  padding-left: calc(100vw - 100%);
}
Enter fullscreen mode Exit fullscreen mode

Source

4. Positioning inside a 100vw width parent

Since scrollbars don't affect the vw unit, we can fix the problem by setting the width of the parent/container in the vw unit and centering/positioning our elements inside of it:

.container {
  width: 100vw;
  /* elements inside won't be affected by scrollbars */
  display: flex;
  align-items: center;
  justify-content: center;
}
Enter fullscreen mode Exit fullscreen mode

Source


The result after applying the 4th method:

Top comments (6)

Collapse
 
mrmg profile image
Michael Geil

In a few cases, display: flex; can destroy the entire layout.
padding-left can be ineffective if the white space on the left side is too large.
I tried this rule:

.container {
   position: relative;
   left: calc((100vw - 100%) / 2);
}
Enter fullscreen mode Exit fullscreen mode

The result was as desired. A stable layout with or without scrollbar.

Collapse
 
ltdat26 profile image
ltdat26

Thank you so much, I've tried it and this is truly magic.

Collapse
 
fruntend profile image
fruntend

Сongratulations 🥳! Your article hit the top posts for the week - dev.to/fruntend/top-10-posts-for-f...
Keep it up 👍

Collapse
 
rashidshamloo profile image
Rashid Shamloo

Thanks for featuring my article :)

Collapse
 
mobeigi profile image
Mo Beigi • Edited

Great share! Thanks for this, I was missing using 100vw instead of 100%.

Keep in mind things like padding-left: calc(100vw - 100%); are not a good solution because a browser can display the toolbar on the left side instead of right due to preferences or for users that use languages that go right to left etc.

After a lot of tinkering with this I'm not sure if its worth implementing at all. My CSS and HTML structure plus logic was getting quite complicated for something this trivial. My use case was I have a nav header and footer that should be styled all the way to the edge of the screen but I wanted to prevent layout shift as users navigated around the website.

However, styling to the edge and using scrollbar-gutter seems to be quite the challenge. I kept running into the issue that the preserved scrollbar space would be styled differently, then I used 100vw to try and address this but then it introduced a new horizontal scrollbar I would have to hide with overflow-x hidden. Then this would cause issues as the window was resized (made smaller) in responsive theme where the scrollbar would overlap with the edge of the text before continuing to resize. Lots of headaches!

From what I can tell almost all major / huge websites don't bother implementing this and just allow the minor layout shift due to resizing window or navigating to another page. Some sites (like dev.to) opt to always show the scrollbar. This is for the main page / body scrollbar of course, I'd try to avoid layout shift when interacting with the same page of course.

Collapse
 
oahmada profile image
Adam Hao

It seems impossible to prevent content shifting and horizontal scrollbar appearing at the same time.