Position an element absolutely to another element
Written byPhuoc Nguyen
Category
Level 2 — Intermediate
Created
02 May, 2020
Last updated
07 May, 2021
It's a common requirement that asks for an element to be shown absolutely to a particular element. We can list some cases, such as
- Show a popover when clicking an element
- Show a tooltip when moving the mouse over an element
- Or show a context menu when right-clicking an element
In this post, you'll see three ways to archive that requirement. They are implemented to demonstrate the first use case where we display a popover under a given target.
First of all, assume that the target and popover elements are two simple
`div`
elements as below:<div id="target">...</div>
<div id="popover">...</div>
ResourceThe implementations don't tell you how to add an arrow to the popover. You can take a look at this page to see how it can be done with CSS
#1. Use absolute CSS
This is the easiest way. To position the popover absolutely to the target, we can place the popover in the target
<div id="target" class="target">
...
<div id="popover" class="popover">...</div>
</div>
and apply the simple CSS styles as below:
.target {
position: relative;
}
.popover {
left: 50%;
position: absolute;
top: 100%;
transform: translate(-50%, 0.75rem);
}
This way uses CSS only and doesn't require any position calculation. Anyway, it doesn't work if the target has the
`overflow: hidden`
style.In the demo below, clicking the Toggle overflow:hidden button will make the popover hidden as well.
#2. Append the popover to `body`
This approach comes from the idea of putting the popover to
`body`
:<body>
<div id="target">...</div>
<div id="popover">...</div>
</body>
We still use the absolute style for the popover, but this time we need to calculate the
`top`
and `left`
properties.It's easy to determine them based on the bounding rectangles of the target and popover:
const target = document.getElementById('target');
const popover = document.getElementById('popover');
const targetRect = target.getBoundingClientRect();
const popoverRect = popover.getBoundingClientRect();
const top = targetRect.top + targetRect.height;
const left = targetRect.left + targetRect.width / 2 - popoverRect.width / 2;
We also need space for the arrow at the top, so let's add some offset:
popover.style.top = `${top + 8}px`;
popover.style.left = `${left}px`;
#3. Use an anchor element
This approach is similar to the previous one. The difference is that instead of appending the popover to
`body`
, we add an anchor between the target and popover.<div id="target">...</div>
<div id="anchor" class="anchor"></div>
<div id="popover">...</div>
The anchor is positioned absolutely as following:
.anchor {
left: 0;
position: absolute;
top: 0;
}
The popover's top and left properties have to subtract the top and left values of the anchor from the one we calculate in the previous section:
const target = document.getElementById('target');
const anchor = document.getElementById('anchor');
const popover = document.getElementById('popover');
const targetRect = target.getBoundingClientRect();
const anchorRect = anchor.getBoundingClientRect();
const popoverRect = popover.getBoundingClientRect();
const top = targetRect.top + targetRect.height;
const left = targetRect.left + targetRect.width / 2 - popoverRect.width / 2;
popover.style.top = `${top - anchorRect.top + 8}px`;
popover.style.left = `${left - anchorRect.left}px`;
#Use cases
#See also
Questions? 🙋
Do you have any questions? Not just about this specific post, but about any topic in front-end development that you'd like to learn more about? If so, feel free to send me a message on Twitter or send me an email. You can find them at the bottom of this page.
I have a long list of upcoming posts, but your questions or ideas for the next one will be my top priority. Let's learn together! Sharing knowledge is the best way to grow 🥷.
Recent posts ⚡
innerText vs textContent
02 Oct, 2023
Truncate the content of an element
02 Oct, 2023
Copy the content of an element to your clipboard
01 Oct, 2023
Make a text area fit its content automatically
30 Sep, 2023
Quickly insert alternate characters while typing
30 Sep, 2023
Zebra-like background
30 Sep, 2023
Add autocomplete to your text area
28 Sep, 2023
Linear scale of a number between two ranges
28 Sep, 2023
Highlight the current line in a text area
27 Sep, 2023
Create your own custom cursor in a text area
27 Sep, 2023
Mirror a text area for improving user experience
26 Sep, 2023
Newsletter 🔔
If you're into front-end technologies and you want to see more of the content I'm creating, then you might want to consider subscribing to my newsletter.
By subscribing, you'll be the first to know about new articles, products, and exclusive promotions.
Don't worry, I won't spam you. And if you ever change your mind, you can unsubscribe at any time.
Phước Nguyễn