Question

Get an HTML Element’s X and Y Position in JavaScript

javascripthtmlcssdomposition

Question

How can I retrieve the X and Y coordinates of HTML elements, such as <img> and <div>, using JavaScript? I need to understand which coordinates are relative to the viewport and how to obtain coordinates relative to the full document.

Short Answer

You will learn how to measure an element’s position with JavaScript, choose between viewport-relative and document-relative coordinates, and avoid common issues caused by scrolling, timing, and CSS layout changes.

Concept

An element can have different X and Y positions depending on the coordinate system you mean.

The most useful browser API is element.getBoundingClientRect(). It returns a DOMRect object describing the element’s visible box relative to the viewport: the currently visible browser area.

const box = document.querySelector(".card").getBoundingClientRect();

console.log(box.left); // X coordinate in the viewport
console.log(box.top);  // Y coordinate in the viewport

If the page scrolls, viewport coordinates change because the element moves closer to or farther from the visible area. To calculate a position relative to the complete document, add the page’s scroll position.

const x = box.left + window.scrollX;
const y = box.top + window.scrollY;

This matters for tasks such as positioning menus, tooltips, drag-and-drop targets, scroll-based animations, click effects, and measuring layout.

Mental Model

Think of a webpage as a long poster and the browser viewport as a small window placed over that poster.

  • Viewport coordinates tell you where an element appears inside the window right now.
  • Document coordinates tell you where the element is printed on the full poster.

When you scroll, the window moves over the poster. The element stays in the same document location, but its location inside the window changes.

Take Quiz

Syntax and Examples

Use getBoundingClientRect() on a DOM element.

const image = document.querySelector("#profile-image");
const rect = image.getBoundingClientRect();

console.log("Viewport X:", rect.left);
console.log("Viewport Y:", rect.top);
console.log("Width:", rect.width);
console.log("Height:", rect.height);

For document-relative coordinates:

const panel = document.querySelector(".panel");
const rect = panel.getBoundingClientRect();

const x = rect.left + window.scrollX;
const y = rect.top + window.scrollY;

console.log("Document X:", x);
console.log("Document Y:", y);

Useful DOMRect properties include:

PropertyMeaning
leftDistance from the viewport’s left edge
topDistance from the viewport’s top edge
rightDistance from the viewport’s left edge to the element’s right edge
bottomDistance from the viewport’s top edge to the element’s bottom edge
widthRendered width of the element
heightRendered height of the element

For a standard div, img, button, or other rendered HTML element, the same method works.

Step by Step Execution

Consider this page structure:

<div style="height: 500px;"></div>
<div id="notice">Important notice</div>
const notice = document.querySelector("#notice");
const rect = notice.getBoundingClientRect();

const viewportX = rect.left;
const viewportY = rect.top;

const documentX = rect.left + window.scrollX;
const documentY = rect.top + window.scrollY;

console.log({ viewportX, viewportY, documentX, documentY });

Step by step:

  1. querySelector("#notice") finds the div element.
  2. getBoundingClientRect() measures its current rendered rectangle.
  3. rect.left and rect.top give the element’s location relative to the visible browser window.
  4. window.scrollX and window.scrollY describe how far the document has been scrolled.
  5. Adding the scroll values produces coordinates relative to the whole document.

If the page is scrolled down by 300 pixels, rect.top may decrease by about 300 pixels, while documentY remains the same unless the page layout itself changes.

Real World Use Cases

  • Tooltips and popovers: Place a help panel beside the button that opened it.
  • Context menus: Position a custom menu near a target element.
  • Drag and drop: Compare an item’s rectangle with a drop zone’s rectangle.
  • Click indicators: Draw a highlight or ripple at a measured location.
  • Scroll effects: Determine whether a section is currently above, inside, or below the viewport.
  • Canvas overlays: Convert an element’s page location into coordinates used for an overlay.
  • Automated UI testing: Verify that an element is visible or appears in an expected area.
Take Quiz

Real Codebase Usage

In production code, developers usually measure elements only when necessary: after rendering, after a resize, after a relevant scroll event, or immediately before positioning another UI component.

A common popover-positioning pattern is:

function positionPopover(anchor, popover) {
  const rect = anchor.getBoundingClientRect();

  popover.style.position = "fixed";
  popover.style.left = `${rect.left}px`;
  popover.style.top = `${rect.bottom + 8}px`;
}

position: fixed works naturally with viewport coordinates because both are relative to the viewport.

For an absolutely positioned overlay inside the document, use document coordinates instead:

function positionDocumentOverlay(anchor, overlay) {
  const rect = anchor.getBoundingClientRect();

  overlay.style.position = "absolute";
  overlay.style.left = `${rect.left + window.scrollX}px`;
  overlay.style.top = `${rect.bottom + window.scrollY + 8}px`;
}

Real projects also remeasure when layout can change. Examples include image loading, viewport resizing, font loading, content expanding, and responsive CSS changes. For observing element-size changes, ResizeObserver can be useful; for checking viewport visibility, IntersectionObserver is often a better fit than continuously measuring during every scroll event.

Common Mistakes

Treating viewport coordinates as document coordinates

This code is valid, but its values change when the user scrolls:

const rect = element.getBoundingClientRect();
console.log(rect.top);

If you need a stable position on the full page, add window.scrollY and window.scrollX.

const documentY = rect.top + window.scrollY;

Reading style.left and style.top

console.log(element.style.left); // Often an empty string

element.style.left only reads an inline style="left: ..." value. It does not reliably report where an element was rendered by normal layout, flexbox, grid, margins, or stylesheets. Use getBoundingClientRect() for rendered coordinates.

Measuring before the element exists

const card = document.querySelector(".card");
card.getBoundingClientRect(); // Fails if card is null

Run the code after the relevant HTML has been created, such as by placing the script after the element or waiting for DOMContentLoaded.

document.addEventListener("DOMContentLoaded", () => {
  const card = document.querySelector(".card");
  console.log(card.getBoundingClientRect());
});

Assuming coordinates never change

An element’s measured position can change after scrolling, resizing, content updates, image loading, or CSS changes. Measure again when the value is needed.

Using offsetTop as a page position

offsetTop is relative to the element’s offsetParent, not necessarily the document. It can be useful for some layout tasks, but it does not answer all page-coordinate questions.

Comparisons

ApproachCoordinates are relative toBest useImportant limitation
getBoundingClientRect()ViewportVisibility checks and fixed-position UIChanges as the page scrolls
rect.left + scrollX, rect.top + scrollYDocumentAbsolute overlays and page-relative measurementsMust account for scroll values
offsetLeft, offsetTopoffsetParentSimple positioning within a layout parentNot a reliable full-document position
element.style.left, element.style.topInline CSS valuesReading values your code explicitly set inlineDoes not measure normal rendered layout

Use getBoundingClientRect() as the default choice when you need the actual position of a rendered element.

Take Quiz

Cheat Sheet

const element = document.querySelector("#target");
const rect = element.getBoundingClientRect();

// Relative to the visible browser viewport
const viewportX = rect.left;
const viewportY = rect.top;

// Relative to the full document
const documentX = rect.left + window.scrollX;
const documentY = rect.top + window.scrollY;
  • left and top are the element’s upper-left corner.
  • right and bottom describe the opposite edges.
  • Viewport coordinates change after scrolling.
  • Document coordinates normally stay stable while scrolling.
  • Remeasure after layout changes or resize events.
  • Match coordinate systems: use viewport coordinates with position: fixed; use document coordinates with many document-level absolute overlays.
  • Check that querySelector found an element before measuring it.

FAQ

How do I get the X and Y position of a div in JavaScript?

Select the div and call getBoundingClientRect(). Use rect.left for X and rect.top for Y relative to the viewport.

Does getBoundingClientRect() work for images?

Yes. It works for rendered elements including img, div, buttons, inputs, and SVG elements.

Why does rect.top change when I scroll?

It is measured relative to the viewport. Scrolling moves the visible viewport over the document, so the element’s viewport location changes.

How do I get an element’s position relative to the document?

Add the current scroll offsets: rect.left + window.scrollX and rect.top + window.scrollY.

What is the difference between offsetTop and getBoundingClientRect().top?

offsetTop is relative to an offsetParent. getBoundingClientRect().top is relative to the viewport and represents the rendered box’s current position.

Can the returned coordinates be decimals?

Yes. Browser layout can use fractional pixel values, especially with zooming, transforms, or responsive layouts.

When should I measure an element?

Measure after the element has been rendered and whenever you need an up-to-date value. Remeasure after relevant layout or viewport changes.

Take Quiz

Mini Project

Description

Build a small element inspector that displays the current viewport and document coordinates of a target card. It demonstrates how scrolling changes viewport values while document values remain tied to the page layout.

Goal

Display an element’s X and Y position and update the displayed values when the page scrolls or the window is resized.

Requirements

Use getBoundingClientRect() to measure a target element.

Show both viewport-relative and document-relative X and Y values.

Update the values when the user scrolls.

Update the values when the browser window is resized.

Take Quiz

Keep learning

Related questions

View more