Skip to content

Commit f5dd24a

Browse files
crisbetovivian-hu-zz
authored andcommitted
fix(overlay): incorrectly calculating centered position on a scrolled page with pushing (#13185)
Fixes a centered flexible overlay with pushing, on a scrolled page, not calculating the position properly. There were a couple of issues: * We were using the `top` viewport offset to calculate along the X axis, as well as `left` to calculate along Y. * We weren't accounting correctly for the scroll position. Fixes #11868.
1 parent 38e7dd2 commit f5dd24a

File tree

2 files changed

+45
-6
lines changed

2 files changed

+45
-6
lines changed

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,6 +1744,40 @@ describe('FlexibleConnectedPositionStrategy', () => {
17441744
expect(Math.floor(overlayRect.top)).toBe(viewportMargin);
17451745
});
17461746

1747+
it('should center flexible overlay with push on a scrolled page', () => {
1748+
const veryLargeElement = document.createElement('div');
1749+
1750+
originElement.style.left = '200px';
1751+
originElement.style.top = '200px';
1752+
1753+
veryLargeElement.style.width = '100%';
1754+
veryLargeElement.style.height = '2000px';
1755+
document.body.appendChild(veryLargeElement);
1756+
window.scroll(0, 250);
1757+
1758+
positionStrategy
1759+
.withFlexibleDimensions()
1760+
.withPush(true)
1761+
.withPositions([{
1762+
overlayY: 'top',
1763+
overlayX: 'center',
1764+
originY: 'bottom',
1765+
originX: 'center'
1766+
}]);
1767+
1768+
attachOverlay({positionStrategy});
1769+
1770+
const overlayRect = overlayRef.overlayElement.getBoundingClientRect();
1771+
const originRect = originElement.getBoundingClientRect();
1772+
1773+
expect(Math.floor(overlayRect.left - overlayRect.width / 2))
1774+
.toBe(Math.floor(originRect.left - originRect.width / 2));
1775+
1776+
window.scroll(0, 0);
1777+
document.body.removeChild(veryLargeElement);
1778+
});
1779+
1780+
17471781
});
17481782

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

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

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -718,10 +718,13 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
718718
bottom = viewport.height - origin.y + this._viewportMargin * 2;
719719
height = viewport.height - bottom + this._viewportMargin;
720720
} else {
721-
// If neither top nor bottom, it means that the overlay
722-
// is vertically centered on the origin point.
721+
// If neither top nor bottom, it means that the overlay is vertically centered on the
722+
// origin point. Note that we want the position relative to the viewport, rather than
723+
// the page, which is why we don't use something like `viewport.bottom - origin.y` and
724+
// `origin.y - viewport.top`.
723725
const smallestDistanceToViewportEdge =
724-
Math.min(viewport.bottom - origin.y, origin.y - viewport.left);
726+
Math.min(viewport.bottom - origin.y + viewport.top, origin.y);
727+
725728
const previousHeight = this._lastBoundingBoxSize.height;
726729

727730
height = smallestDistanceToViewportEdge * 2;
@@ -751,10 +754,12 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
751754
left = origin.x;
752755
width = viewport.right - origin.x;
753756
} else {
754-
// If neither start nor end, it means that the overlay
755-
// is horizontally centered on the origin point.
757+
// If neither start nor end, it means that the overlay is horizontally centered on the
758+
// origin point. Note that we want the position relative to the viewport, rather than
759+
// the page, which is why we don't use something like `viewport.right - origin.x` and
760+
// `origin.x - viewport.left`.
756761
const smallestDistanceToViewportEdge =
757-
Math.min(viewport.right - origin.x, origin.x - viewport.top);
762+
Math.min(viewport.right - origin.x + viewport.left, origin.x);
758763
const previousWidth = this._lastBoundingBoxSize.width;
759764

760765
width = smallestDistanceToViewportEdge * 2;

0 commit comments

Comments
 (0)