I've been searching for a "lightbox" type solution that allows this but haven't found one yet (please, suggest if you know of any).
The behavior I'm trying to recreate is just like what you'd see at Pinterest when clicking on an image. The overlay is scrollable (as in the whole overlay moves up like a page on top of a page) but the body behind the overlay is fixed.
I attempted to create this with just CSS (i.e. a div
overlay on top of the whole page and body with overflow: hidden
), but it doesn't prevent div
from being scrollable.
How to keep the body/page from scrolling but keep scrolling inside the fullscreen container?
Best Solution
Theory
Looking at current implementation of the pinterest site (it might change in the future), when you open the overlay a
noscroll
class is applied to thebody
element andoverflow: hidden
is set, thusbody
is no longer scrollable.The overlay (created on-the-fly or already inside the page and made visible via
display: block
, it makes no difference) hasposition : fixed
andoverflow-y: scroll
, withtop
,left
,right
andbottom
properties set to0
: this style makes the overlay fill the whole viewport.The
div
inside the overlay is instead just inposition: static
then the vertical scrollbar you see is related to that element. As a result the content is scrollable but overlay remains fixed.When you close the zoom you hide the overlay (via
display: none
) and then you could also entirely remove it via javascript (or just the content inside, it's up to you how to inject it).As a final step you have to also remove the
noscroll
class to thebody
(so the overflow property returns to its initial value)Code
(it works by changing the
aria-hidden
attribute of the overlay in order to show and hide it and to increase its accessibility).Markup
(open button)
(overlay and close button)
CSS
Javascript (vanilla-JS)
Finally, here's another example in which the overlay opens with a fade-in effect by a CSS
transition
applied to theopacity
property. Also apadding-right
is applied to avoid a reflow on the underlying text when the scrollbar disappears.CSS