Skip to content

Commit 1dd8a27

Browse files
crisbetoandrewseguin
authored andcommitted
fix(overlay): incorrect bounding box bottom position when page is scrolled and content is flowing upwards (#10463)
* Fixes the bounding box position and height being calculated incorrectly when the overlay's content is flowing upwards and the page has been scrolled down. * Fixes the "when scrolled" tests not scrolling the page down.
1 parent cdb6e40 commit 1dd8a27

File tree

2 files changed

+36
-6
lines changed

2 files changed

+36
-6
lines changed

src/cdk/overlay/position/flexible-connected-position-strategy.spec.ts

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,17 +159,15 @@ describe('FlexibleConnectedPositionStrategy', () => {
159159
// Scroll the page such that the origin element is roughly in the
160160
// center of the visible viewport (2500 - 1024/2, 2500 - 768/2).
161161
document.body.appendChild(veryLargeElement);
162-
document.body.scrollTop = 2100;
163-
document.body.scrollLeft = 2100;
162+
window.scroll(2100, 2100);
164163

165164
originElement.style.top = `${ORIGIN_TOP}px`;
166165
originElement.style.left = `${ORIGIN_LEFT}px`;
167166
});
168167

169168
afterEach(() => {
169+
window.scroll(0, 0);
170170
document.body.removeChild(veryLargeElement);
171-
document.body.scrollTop = 0;
172-
document.body.scrollLeft = 0;
173171
});
174172

175173
// Preconditions are set, now just run the full set of simple position tests.
@@ -1158,6 +1156,38 @@ describe('FlexibleConnectedPositionStrategy', () => {
11581156
expect(Math.floor(overlayRect.height)).toBe(OVERLAY_HEIGHT);
11591157
});
11601158

1159+
it('should calculate the `bottom` value correctly with upward-flowing content ' +
1160+
'and a scrolled page', () => {
1161+
const veryLargeElement = document.createElement('div');
1162+
1163+
originElement.style.left = '200px';
1164+
originElement.style.top = `200px`;
1165+
1166+
veryLargeElement.style.width = '100%';
1167+
veryLargeElement.style.height = '2000px';
1168+
document.body.appendChild(veryLargeElement);
1169+
window.scroll(0, 50);
1170+
1171+
positionStrategy
1172+
.withFlexibleHeight()
1173+
.withPositions([{
1174+
overlayY: 'bottom',
1175+
overlayX: 'start',
1176+
originY: 'bottom',
1177+
originX: 'start'
1178+
}]);
1179+
1180+
attachOverlay({positionStrategy});
1181+
1182+
const overlayRect = overlayRef.overlayElement.getBoundingClientRect();
1183+
const originRect = originElement.getBoundingClientRect();
1184+
1185+
expect(Math.floor(overlayRect.bottom)).toBe(Math.floor(originRect.bottom));
1186+
1187+
window.scroll(0, 0);
1188+
document.body.removeChild(veryLargeElement);
1189+
});
1190+
11611191
});
11621192

11631193
describe('onPositionChange with scrollable view properties', () => {

src/cdk/overlay/position/flexible-connected-position-strategy.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -564,8 +564,8 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
564564
height = viewport.bottom - origin.y;
565565
} else if (position.overlayY === 'bottom') {
566566
// Overlay is opening "upward" and thus is bound by the top viewport edge.
567-
bottom = viewport.bottom - origin.y + this._viewportMargin;
568-
height = origin.y - viewport.top;
567+
bottom = viewport.height - origin.y + this._viewportMargin;
568+
height = viewport.height - bottom;
569569
} else {
570570
// If neither top nor bottom, it means that the overlay
571571
// is vertically centered on the origin point.

0 commit comments

Comments
 (0)