Skip to content

Commit a140781

Browse files
authored
fix(scroll): prevent scroll on document to keep sticky elements (#997)
2 parents 2ead23f + f1a3158 commit a140781

1 file changed

Lines changed: 16 additions & 16 deletions

File tree

packages/scroll/src/preventScroll.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ export type CreatePreventScrollProps = {
2121
element?: MaybeAccessor<HTMLElement | undefined>;
2222
/** Whether scroll prevention is active. *Default = `true`* */
2323
enabled?: MaybeAccessor<boolean>;
24-
/** Hide the `<body>` scrollbar while active. *Default = `true`* */
24+
/** Hide the document scrollbar while active. *Default = `true`* */
2525
hideScrollbar?: MaybeAccessor<boolean>;
26-
/** Add padding/margin to `<body>` to compensate for the hidden scrollbar. *Default = `true`* */
26+
/** Add padding/margin to document element to compensate for the hidden scrollbar. *Default = `true`* */
2727
preventScrollbarShift?: MaybeAccessor<boolean>;
2828
/** Whether to use `padding` or `margin` for the scrollbar shift compensation. *Default = `"padding"`* */
2929
preventScrollbarShiftMode?: MaybeAccessor<"padding" | "margin">;
30-
/** Restore `<body>` scroll position via `window.scrollTo` when disabled to avoid layout shift. *Default = `true`* */
30+
/** Restore scroll position via `window.scrollTo` when disabled to avoid layout shift. *Default = `true`* */
3131
restoreScrollPosition?: MaybeAccessor<boolean>;
3232
/** Allow two-finger pinch-zoom gestures. *Default = `false`* */
3333
allowPinchZoom?: MaybeAccessor<boolean>;
@@ -47,15 +47,15 @@ type ActiveStyle = {
4747

4848
type PreventScrollRegistry = {
4949
stack: Signal<string[]>;
50-
activeBodyStyles: Map<string, ActiveStyle>;
50+
activeDocumentStyles: Map<string, ActiveStyle>;
5151
/** Shared across duplicate package copies so instance ids never collide on the shared stack. */
5252
nextId: number;
5353
};
5454

5555
const getRegistry = (): PreventScrollRegistry =>
5656
globalRegistry<PreventScrollRegistry>("@solid-primitives/scroll:prevent-scroll", () => ({
5757
stack: createSignal<string[]>([], { ownedWrite: true }),
58-
activeBodyStyles: new Map(),
58+
activeDocumentStyles: new Map(),
5959
nextId: 0,
6060
}));
6161

@@ -64,24 +64,24 @@ const isActive = (id: string): boolean => {
6464
return stack.length > 0 && stack[stack.length - 1] === id;
6565
};
6666

67-
function applyBodyStyle(
67+
function applyDocumentStyle(
6868
key: string,
6969
element: HTMLElement,
7070
style: Partial<CSSStyleDeclaration>,
7171
properties: { key: string; value: string }[],
7272
): () => void {
73-
const activeBodyStyles = getRegistry().activeBodyStyles;
73+
const activeDocumentStyles = getRegistry().activeDocumentStyles;
7474

7575
const originalStyles: Partial<CSSStyleDeclaration> = {};
7676
for (const k in style) {
7777
originalStyles[k] = element.style[k as keyof CSSStyleDeclaration] as string;
7878
}
7979

80-
const existing = activeBodyStyles.get(key);
80+
const existing = activeDocumentStyles.get(key);
8181
if (existing) {
8282
existing.activeCount++;
8383
} else {
84-
activeBodyStyles.set(key, {
84+
activeDocumentStyles.set(key, {
8585
activeCount: 1,
8686
originalStyles,
8787
properties: properties.map(p => p.key),
@@ -94,13 +94,13 @@ function applyBodyStyle(
9494
}
9595

9696
return () => {
97-
const active = activeBodyStyles.get(key);
97+
const active = activeDocumentStyles.get(key);
9898
if (!active) return;
9999
if (active.activeCount !== 1) {
100100
active.activeCount--;
101101
return;
102102
}
103-
activeBodyStyles.delete(key);
103+
activeDocumentStyles.delete(key);
104104

105105
for (const [k, v] of Object.entries(active.originalStyles)) {
106106
(element.style as any)[k] = v;
@@ -226,8 +226,8 @@ export const createPreventScroll = (props: CreatePreventScrollProps = {}): void
226226
}) => {
227227
if (!enabled || !hideScrollbar) return;
228228

229-
const { body } = document;
230-
const scrollbarWidth = window.innerWidth - body.offsetWidth;
229+
const { documentElement } = document;
230+
const scrollbarWidth = window.innerWidth - documentElement.clientWidth;
231231
const offsetTop = window.scrollY;
232232
const offsetLeft = window.scrollX;
233233

@@ -236,14 +236,14 @@ export const createPreventScroll = (props: CreatePreventScrollProps = {}): void
236236

237237
if (preventScrollbarShift && scrollbarWidth > 0) {
238238
if (preventScrollbarShiftMode === "padding") {
239-
style.paddingRight = `calc(${window.getComputedStyle(body).paddingRight} + ${scrollbarWidth}px)`;
239+
style.paddingRight = `calc(${window.getComputedStyle(documentElement).paddingRight} + ${scrollbarWidth}px)`;
240240
} else {
241-
style.marginRight = `calc(${window.getComputedStyle(body).marginRight} + ${scrollbarWidth}px)`;
241+
style.marginRight = `calc(${window.getComputedStyle(documentElement).marginRight} + ${scrollbarWidth}px)`;
242242
}
243243
properties.push({ key: "--scrollbar-width", value: `${scrollbarWidth}px` });
244244
}
245245

246-
const restoreStyle = applyBodyStyle("prevent-scroll", body, style, properties);
246+
const restoreStyle = applyDocumentStyle("prevent-scroll", documentElement, style, properties);
247247

248248
return () => {
249249
restoreStyle();

0 commit comments

Comments
 (0)