Skip to content

Commit d93e718

Browse files
authored
fix: handle relative html offset clipping rect (#3097)
1 parent dcca804 commit d93e718

4 files changed

+44
-16
lines changed

.changeset/late-humans-decide.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@floating-ui/dom": patch
3+
---
4+
5+
fix: handle relative html offset clipping rect

packages/dom/src/platform/convertOffsetParentRelativeRectToViewportRelativeRect.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111

1212
import {getBoundingClientRect} from '../utils/getBoundingClientRect';
1313
import {getScale} from './getScale';
14+
import {getHTMLOffset} from '../utils/getHTMLOffset';
1415

1516
export function convertOffsetParentRelativeRectToViewportRelativeRect({
1617
elements,
@@ -52,10 +53,16 @@ export function convertOffsetParentRelativeRectToViewportRelativeRect({
5253
}
5354
}
5455

56+
const htmlOffset =
57+
documentElement && !isOffsetParentAnElement && !isFixed
58+
? getHTMLOffset(documentElement, scroll, true)
59+
: createCoords(0);
60+
5561
return {
5662
width: rect.width * scale.x,
5763
height: rect.height * scale.y,
58-
x: rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x,
59-
y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y,
64+
x:
65+
rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x + htmlOffset.x,
66+
y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y + htmlOffset.y,
6067
};
6168
}
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type {NodeScroll} from '../types';
2+
import {getWindowScrollBarX} from './getWindowScrollBarX';
3+
4+
export function getHTMLOffset(
5+
documentElement: HTMLElement,
6+
scroll: NodeScroll,
7+
ignoreScrollbarX = false,
8+
) {
9+
const htmlRect = documentElement.getBoundingClientRect();
10+
const x =
11+
htmlRect.left +
12+
scroll.scrollLeft -
13+
(ignoreScrollbarX
14+
? 0
15+
: // RTL <body> scrollbar.
16+
getWindowScrollBarX(documentElement, htmlRect));
17+
const y = htmlRect.top + scroll.scrollTop;
18+
19+
return {
20+
x,
21+
y,
22+
};
23+
}

packages/dom/src/utils/getRectRelativeToOffsetParent.ts

+7-14
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type {VirtualElement} from '../types';
1111
import {getDocumentElement} from '../platform/getDocumentElement';
1212
import {getBoundingClientRect} from './getBoundingClientRect';
1313
import {getWindowScrollBarX} from './getWindowScrollBarX';
14+
import {getHTMLOffset} from './getHTMLOffset';
1415

1516
export function getRectRelativeToOffsetParent(
1617
element: Element | VirtualElement,
@@ -49,21 +50,13 @@ export function getRectRelativeToOffsetParent(
4950
}
5051
}
5152

52-
let htmlX = 0;
53-
let htmlY = 0;
53+
const htmlOffset =
54+
documentElement && !isOffsetParentAnElement && !isFixed
55+
? getHTMLOffset(documentElement, scroll)
56+
: createCoords(0);
5457

55-
if (documentElement && !isOffsetParentAnElement && !isFixed) {
56-
const htmlRect = documentElement.getBoundingClientRect();
57-
htmlY = htmlRect.top + scroll.scrollTop;
58-
htmlX =
59-
htmlRect.left +
60-
scroll.scrollLeft -
61-
// RTL <body> scrollbar.
62-
getWindowScrollBarX(documentElement, htmlRect);
63-
}
64-
65-
const x = rect.left + scroll.scrollLeft - offsets.x - htmlX;
66-
const y = rect.top + scroll.scrollTop - offsets.y - htmlY;
58+
const x = rect.left + scroll.scrollLeft - offsets.x - htmlOffset.x;
59+
const y = rect.top + scroll.scrollTop - offsets.y - htmlOffset.y;
6760

6861
return {
6962
x,

0 commit comments

Comments
 (0)