2

I have an browser app that dynamically shows content that can be shorter or longer than the available screen size. On desktop browsers, this causes vertical scrollbar to appear/disappear, which makes the content "jump" left and right.

To avoid this, I add style="overflow-y: scroll" to the body tag, which forces the scrollbar to always display - the scrollbar is just disabled if the content is shorter than the screen.

The problem comes when I use the material-ui SwipeableDrawer component to show a sliding option menu. Viewing the DOM in the browser inspector, it seems material-ui actively removes my overflow-y styling on the body tag when it shows the menu, but then doesn't put it back when it removes the menu.

  • Example app published on Netlify
  • Source code
  • The screen-shot below shows the content is stable at first when the disabled scrollbar is visible, then shows the content jumping left/right after the menu has been displayed.

enter image description here

This only happens on desktop, reproduced with both Chrome and Firefox. It doesn't happen on mobile (iOS, for example) because the scrollbar on mobile devices is displayed "on top" of the content.

I don't want to track what material-ui is doing and add/remove padding - I'm pretty sure material-ui does this behaviour for other components as well (poppers, tooltips, etc.) Tracking all those components and fiddling with padding will be error-prone (not to mention tedious).

Can I somehow make the vertical scrollbar display "on top" of the content like it does in a mobile browser? I'd have to add padding to make sure nothing gets obscured, but at least it'd be static - so once the problem is fixed it'll stay fixed.

Shorn
  • 19,077
  • 15
  • 90
  • 168
  • Could you instead of adding padding make your container less wide? The problem is to know by how much. This [link] https://stackoverflow.com/questions/18548465/prevent-scroll-bar-from-adding-up-to-the-width-of-page-on-chrome has some ideas, but the problem then will be to get it set from the very beginning. – A Haworth Dec 06 '20 at 08:58

2 Answers2

2

One possible workaround is to disable the scroll lock:

<SwipeableDrawer disableScrollLock={true} ... >

A downside of this is that you'll have to remember to do this everywhere you use any material-ui component that has the disableScrolllock functionality - so that means everywhere you use popovers, popups, etc.

But you can override the default props for components. The following worked for SwipableDrawer (because Drawer extends Modal):

export const theme = createMuiTheme({
  props: {
    MuiModal: {
      disableScrollLock: true,
    },
  },
});

Note: the disableScrollLock setting appears to not be needed anymore with mui (i.e. material-ui version 5) - but you do still need to set style="overflow-y: scroll" in your root body element or somewhere similar.

Shorn
  • 19,077
  • 15
  • 90
  • 168
0

One possible workaround is to

make the vertical scrollbar display "on top"

by setting the width of the body to the full view:

  <body style="width: 100vw;">

This means the body element will extend all the way "underneath" the scrollbar (same as how it works on mobile browsers).

A downside of this is that content that appears on the right hand side of the screen may be obstructed by the scrollbar.

Shorn
  • 19,077
  • 15
  • 90
  • 168