Today while building a modal I experimented with a different layout that solves a few issues with the scrollbar, in a simple way. Jump to the final version, or read on.
Basic Modal
The most basic modal is 2 <div>
elements:
- an overlay
position: fixed;
in the<body>
- and the content, nested in the overlay
Scrollbar
There's an issue with this simple modal: the vertical scrollbar of the main content persists when the modal is opened.
Opening a modal should fully switch context away from the underlying content to the modal. Scrolling presentation and interaction need to follow this context switch.
A common solution is to add overflow: hidden
on <html>
or <body>
, removing the scrollbar entirely. This also works if the modal content is scrollable.
Content Shift
Removing the scrollbar fixes one problem, but introduces another: the underlying content shifts position.
When the scrollbar is removed, the content takes up that extra width, leading to text and content reflowing, and backgrounds repositioning.
In the past I've solved this in two ways: adding padding
/margin
on <html>
, or setting the width
of <html>
.
These values have to be recalculated and updated when the window
is resized, or as content is added/removed.
Modal Over Everything
So today as I was building a modal I got to this stage and thought about why the modal exists within the scrollable content. It should be fully separate, and on top of the scrollbar. This is possible by restructuring the document.
The modal has to be outside the scrollable content; it's added to the <body>
and can't be any higher up the DOM, so the scrollable content will need to be a child of <body>
.
What I like about this:
- no code to remove/add scrollbars
- no code to set width/margin to account for the scrollbar
- no recalculations when resized
It just works.
Lastly
One drawback with this setup is that it's atypical. Any other code expecting overflow
to be on <html>
or <body>
will need to be refactored. This and other issues likely wouldn't be hard to resolve.
I plan to test this solution further for browser and device compatibility, and hopefully it proves out.
Top comments (1)
Thank you!