After I accidentally stumbled upon the solution to “preventing body scrolling when overlay is on” by trying too many different things again and again, I wasn’t able to explain exactly why this works.
Almost 2 years later, after another week-long painful bug with scrolling problems, and trying too many things all over again, I finally came up with the gist of all “prevent some div from scrolling” problems.
- don’t allow body to be taller than window, and
- have the scrolled-div and don’t-let-me-scroll-div as siblings instead of parent and child, so that no propagation of scrolls can happen
To achieve limited body height, we can either go:
- The natural way:
- html/body: height: 100%; which renders body exactly at window height
- at the same time, set a 100% height and overflow: auto; on all direct child elements of body
- the reason 100% height alone doesn’t work is that: the default option for overflow is visible. Even though content after an overflow-visible element won’t be pushed down by the overflow, parent element’s height will be stretched all the same.
- The forceful way:
- set all too-tall child elements of body to be:
- position: absolute/fixed; top: 0; bottom: 0;
- basically making sure none of them can put their toes across the boundary (border of window), therefore ensuring that nothing can sneakily stretch up body height
- and of course, overflow: auto; on them too, because otherwise body is still stretched.
Example 1: This Demo
- scrolling on overlay won’t scroll content layer
- height of html/body is 100%
- nothing inside body has a height taller than window
- overlay div and content page are siblings.
Example 2: Kendo-ui’s auto-complete demo page.
- scrolling inside the autocomplete dropdown won’t scroll the page, yet
- scrolling outside of dropdown scrolls the page which triggers dropdown close.
- dropdown div and #main content div are siblings.
May this issue never haunt any of us ever again.