Richard C.
—How do you find the (x, y) coordinate of an HTML element on your page? You might want to position a popup next to an element, create a fancy animation, or overlay elements seamlessly.
There are two coordinate systems in HTML:
Let’s call these page coordinates and window coordinates. Both of these axes have their origin points (0,0) at the top left of the page or window, with values increasing towards the bottom right.
To get the position of an HTML element in JavaScript relative to the window, use getBoundingClientRect()
:
<!DOCTYPE html> <html lang=""> <body> <div id="myElement" style="position: absolute; left: 50px; top: 100px;"> Hello World </div> <script> globalThis.setInterval(() => { const element = document.getElementById("myElement"); const rect = element.getBoundingClientRect(); console.log("X: " + rect.x + ", Y: " + rect.y); }, 1000); </script> </body> </html>
In this code, we call getBoundingClientRect()
on an element positioned manually at (50,100). This returns a rectangle object, whose properties are the x
and y
coordinates we need. The interval timer will write a new value to the console every second.
The DOMRect
object provides the following properties for your element: left
, top
, right
, bottom
, x
, y
, width
, and height
.
Although you can set negative values in CSS, getBoundingClientRect()
always returns positive width and height values. The left
and x
values are the same, as are the top
and y
values — as long as no CSS transform has been applied to the element (more on that later).
The height and width values include the element’s border and padding, but not its margin value. To calculate the full height of an element you need to access its CSS:
let style = getComputedStyle(element); let marginTop = parseFloat(style.marginTop); let marginBottom = parseFloat(style.marginBottom);
Using getBoundingClientRect()
, the position of the div
will change whenever you scroll on the page. If you want to get the absolute position of the element on the page, not relative to the window, add the number of scrolled pixels to the element’s window location using scrollY
:
console.log("X: " + (rect.x + globalThis.scrollX) + ", Y: " + (rect.y + globalThis.scrollY));
The parentheses around the sums are added for JavaScript to treat them as numbers and not concatenate them as strings.
If you have a complex page layout, such as one with containers with their own scroll windows (div
with overflow: scroll
), or one using CSS transformations, you may need to use other element properties to calculate the x
and y
positions.
First, define what the position of an element means in your layout. Is it relative to the page, the window, or another element on the page? It’s likely you still need only the window position of the element to position another element next to it.
The following properties of an element may be useful to you (all are in pixels):
offsetParent
— The closest positioned ancestor element that is not static
(the default positioning type).offsetLeft
and offsetTop
— The distance from the outer border of the current element (including its margin) to the padding edge of the offsetParent.scrollHeight
— The total height of a scrollable element, including the children not visible in the current view that you have to scroll down to see.scrollTop
— The distance from the top of a scrollable element that the user has scrolled down to. If the scrollbar is still at the top of the element then scrollTop
is 0.clientHeight
— The height of a scrollable element visible on the page.The getBoundingClientRect().height
property of an element is different from its clientHeight
. The clientHeight
property includes the content and its padding but not its border, margin, or horizontal scrollbar. The getBoundingClientRect().height
property includes the height of the content, padding, scrollbar, and borders, but not the margin.
You can loop through every offsetParent
of an element until you return to the HTML body. If you sum all the offsetTop
values along the way, you’ll have the total distance of the element from the start of the page. This will equal rect.y + globalThis.scrollY
from earlier.
A transform is a CSS setting like transform: translate(5px, 6px);
. A transform changes the position of an element visually, but not its original layout position in the document flow.
If an element has been moved with a transform, then getBoundingClientRect()
will return left
and top
values from before the translation, and x
and y
values from after the translation — where the element appears to be visually. So you probably want to use the x
and y
values.
If you need to access the exact values of a transform, you can use getComputedStyle()
:
const transform = window.getComputedStyle(element).getPropertyValue('transform'); if (transform !== 'none') { const matrixValues = transform.match(/matrix.*\((.+)\)/)[1].split(', '); const tx = parseFloat(matrixValues[4]); const ty = parseFloat(matrixValues[5]); console.log('Shifted x by ' + tx); console.log('Shifted y by ' + ty); }
The transform
object will be a string, like matrix(1, 0, 0, 1, 5, 6)
, so we need to extract its values using a regex match. The last two values are the x
and y
translation values. If you are using a 3D transformation with matrix3d
, you need to adjust the regex.
A CSS transform also might involve scaling, rotation, and shearing, which will affect the visual appearance of the element in the window, but not its starting position.
Tasty treats for web developers brought to you by Sentry. Get tips and tricks from Wes Bos and Scott Tolinski.
SEE EPISODESConsidered “not bad” by 4 million developers and more than 100,000 organizations worldwide, Sentry provides code-level observability to many of the world’s best-known companies like Disney, Peloton, Cloudflare, Eventbrite, Slack, Supercell, and Rockstar Games. Each month we process billions of exceptions from the most popular products on the internet.
Here’s a quick look at how Sentry handles your personal information (PII).
×We collect PII about people browsing our website, users of the Sentry service, prospective customers, and people who otherwise interact with us.
What if my PII is included in data sent to Sentry by a Sentry customer (e.g., someone using Sentry to monitor their app)? In this case you have to contact the Sentry customer (e.g., the maker of the app). We do not control the data that is sent to us through the Sentry service for the purposes of application monitoring.
Am I included?We may disclose your PII to the following type of recipients:
You may have the following rights related to your PII:
If you have any questions or concerns about your privacy at Sentry, please email us at compliance@sentry.io.
If you are a California resident, see our Supplemental notice.