My solution:
<Popover
...
// mui version 5.14.0
slotProps={{
root: {
sx: {
overflowY: "scroll",
overflowX: "hidden"
}
}
}}
// older mui versions
classes={{
root: {
overflowY: "scroll",
overflowX: "hidden"
}
}}
>
...
</Popover>
Long story long:
Problem code:
<Popover
open={Boolean(anchorEl)}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: "bottom",
horizontal: "left",
}}
>
...
</Popover>
Problem visualized:
Original state of right side of page:
When the Popover
is opened, the vertical scrollbar disappears:
Reason:
This happens because the Popover
is inserted in the DOM as a sibling of the #root
div
, not its child:
This inserted DOM element occupies the exact entire width and height of the page, therefore, it does not need to have scrollbars:
My objective:
Since the suddenly introduced gap by the missing scrollbar looks shabby, I wanted to still have the scrollbar shown on the screen, but not scrollable. This is in line with what MUI
has by default - when a Popover
is open on the screen, the screen does not scroll.
Basically, here's what I wanted:
Solution attempt 1:
I noticed that when the Popover
is open, a padding-right
of 17px
is automatically introduced on the document's body
element:
Tried removing this padding-right
from the body
:
This caused the scrollbar to disappear without leaving a gap when the Popover
is open, and reappear when the Popover
is closed.
The appearance and disappearance of the scrollbar was causing the remaining elements on the screen to reposition themselves whenever the Popover
was toggled:
No-go.
Solution attempt 2:
<Popover
...
disableScrollLock={true} // Added
>
...
</Popover>
This did cause the scrollbar to stay on the screen when the Popover
is open, but, as Viktor has mentioned in his answer, it caused the Popover
to float around when the page was scrolled.
No-go.
A third possible attempt could have been to use <Popper />
with <ClickAwayListener />
as others have mentioned in their answers. But I didn't want to go back and change all instances of Popover
across my app.
Final solution:
mui
version 5.14.0
:
<Popover
...
// mui version 5.14.0
slotProps={{
root: {
sx: {
overflowY: "scroll"
}
}
}}
// older mui versions
classes={{
root: {
overflowY: "scroll"
}
}}
>
...
</Popover>
...
</Popover>
This allows the scrollbar to remain shown on the page while not allowing the user to scroll:
Caveat (and resolution):
For the right-most Button (Button 6), the Popover
was introducing a horizontal scrollbar on the page, with a carry-over of 1px
:
To resolve this, either prevent horizontal scrolling on the Popover
's root
:
<Popover
...
// mui version 5.14.0
slotProps={{
root: {
sx: {
overflowY: "scroll",
overflowX: "hidden" // Added
}
}
}}
// older mui versions
classes={{
root: {
overflowY: "scroll",
overflowX: "hidden" // Added
}
}}
>
...
</Popover>
Or move the Popover
's root
1px
to the left:
<Popover
...
// mui version 5.14.0
slotProps={{
root: {
sx: {
overflowY: "scroll",
left: -1 // Added
}
}
}}
// older mui versions
classes={{
root: {
overflowY: "scroll",
left: -1 // Added
}
}}
>
...
</Popover>