I am setting the position of the arrow seen in the screenshot using the calculation in the typescript, however, the position is getting based from the top of the black popup instead of the top of the screen.
- top of screen to middle of button = 250px
- top of popup to arrow = 250px
So the offset is correct but it is using the top of the popup for 0px
instead of the top of the screen. What can I do to place the arrow using the top of the screen or fix my formula to account for the positioning?
When I use relative positioning:
When I use absolute positioning:
Here is how the css looks (I tried setting relative
to absolute
which doesn't work:
.menu-popup {
--arrow-left-offset: 50%;
--arrow-top-offset: 50%;
padding: var(--spacing-s) 0;
margin: 10px;
position: relative;
&::after {
content: ' ';
position: absolute;
}
// The placement of the arrow
&.menu-popup-right.standard-variant::after {
top: var(--arrow-top-offset);
right: 100%; /* To the left of the menu-popup */
margin-top: -5px;
}
}
I am then updatinging the css variable like this:
// Changes the placement of the arrow:
private changeArrowPlacement() {
if (typeof this.menu === 'undefined') return;
// The button
const tRect = this.triggerRef.nativeElement.getBoundingClientRect();
// The menu
const mRect = this.menu.nativeElement.getBoundingClientRect();
if (typeof this.position === 'string' && ['left', 'right'].includes(this.position)) {
const top = tRect.height / 2 tRect.top 'px';
this.setArrowOffset('top', top);
}
}
// Sets the the css property:
private setArrowOffset(position: 'left' | 'top', value: string) {
if (typeof this.menu === 'undefined') return;
this.menu.nativeElement.style.setProperty('--arrow-left-offset', '0%');
this.menu.nativeElement.style.setProperty('--arrow-top-offset', '0%');
this.menu.nativeElement.style.setProperty(`--arrow-${position}-offset`, value);
}
The popup is generated via Angular CDK, which creates a div element.
Here is a simple mockup of the html
<!-- Created by me -->
<div id="application">
<button (click)="openPopup()">Open Popup</button>
</div>
<!-- Created by Angular CDK -->
<div >
<div >
<div >
</div>
</div>
</div>
Here is what angular generates for the popup:
/* Overlay element */
.overlay {
top: 0px;
left: 0px;
height: 100%;
width: 100%;
position: absolute;
}
/* Overlay Pane */
.pane {
top: 144.5px;
left: 573.844px;
}
CodePudding user response:
absolute
is positioned relative to the parent relative
container. So, just remove position: relative
from parent container, and you're good to go - your absolute
will be then relative to the page body itself (if there's no other containers with position
set in between).
Also, if you have no control over parent container, you can try using fixed
for your arrow. Note though, it's position will be fixed even if you scroll the page - it will stay in its place on screen.
Finally, you could just place your absolutely positioned arrow by experimentally finding the right coordinates for it. Note, you could use not only px
as units, but also %
. Or even transform: translate(X, Y);
where X
and Y
could also be either pixels or percentiles.
CodePudding user response:
So it looks like the calculation that I needed was this as it takes into account relative positioning:
const top = tRect.top - mRect.top tRect.height / 2 'px';
- Get the top of the button
- Get the top of the menu
- Subtract the two to get the difference (arrow is now placed at the top of the button)
- Add half the height of the button (arrow is now placed at half the height of the button)
This works if the button is at the top, bottom, left, right, or center of the page.