1- import { getComputedStyle , isIos , setStyleProperty , setStyle } from "@zag-js/dom-query"
1+ import { getComputedStyle , isIos , isOverflowElement , setStyleProperty , setStyle } from "@zag-js/dom-query"
22
33const LOCK_CLASSNAME = "data-scroll-lock"
44
@@ -22,9 +22,17 @@ function hasStableScrollbarGutter(element: HTMLElement): boolean {
2222 return scrollbarGutter === "stable" || scrollbarGutter ?. startsWith ( "stable " ) === true
2323}
2424
25+ // html scrolls when it overflows, body otherwise (e.g. app-shell layouts where body is
26+ // permanently hidden and an inner region scrolls instead).
27+ function getScrollContainer ( doc : Document ) : HTMLElement {
28+ const { documentElement, body } = doc
29+ return isOverflowElement ( documentElement ) ? documentElement : body
30+ }
31+
2532function applyLock ( doc : Document ) : VoidFunction {
2633 const win = doc . defaultView ?? window
2734 const { documentElement, body } = doc
35+ const scroller = getScrollContainer ( doc )
2836
2937 // Check if scrollbar-gutter: stable is set on html or body
3038 // If so, the browser already reserves space for the scrollbar
@@ -37,7 +45,7 @@ function applyLock(doc: Document): VoidFunction {
3745 const setScrollbarWidthProperty = ( ) => setStyleProperty ( documentElement , "--scrollbar-width" , `${ scrollbarWidth } px` )
3846 const paddingProperty = getPaddingProperty ( documentElement )
3947
40- const setBodyStyle = ( ) => {
48+ const setScrollerStyle = ( ) => {
4149 // Only add padding if scrollbar-gutter: stable is not set
4250 const styles : Record < string , string > = {
4351 overflow : "hidden" ,
@@ -47,7 +55,7 @@ function applyLock(doc: Document): VoidFunction {
4755 styles [ paddingProperty ] = `${ scrollbarWidth } px`
4856 }
4957
50- return setStyle ( body , styles )
58+ return setStyle ( scroller , styles )
5159 }
5260
5361 // Only iOS doesn't respect `overflow: hidden` on document.body
@@ -79,7 +87,7 @@ function applyLock(doc: Document): VoidFunction {
7987 }
8088 }
8189
82- const cleanups = [ setScrollbarWidthProperty ( ) , isIos ( ) ? setBodyStyleIOS ( ) : setBodyStyle ( ) ]
90+ const cleanups = [ setScrollbarWidthProperty ( ) , isIos ( ) ? setBodyStyleIOS ( ) : setScrollerStyle ( ) ]
8391
8492 return ( ) => {
8593 cleanups . forEach ( ( fn ) => fn ?.( ) )
0 commit comments