Published on

How to Get the Correct Y Position of an Element in CHATGPT UI

Authors
  • avatar
    Name
    Loc Truong
    Twitter

The Problem

You try to get the vertical position of an element like this:

window.scrollY

...but it always returns 0.

Even worse, this common pattern also fails:

element.getBoundingClientRect().top + window.scrollY

If you're inspecting the ChatGPT web UI, this can be very confusing.

Why window.scrollY Is Always 0

In ChatGPT (and many modern web apps):

  • The page itself does not scroll
  • Scrolling happens inside a nested container
  • The <body> is fixed-height

That means:

window.scrollY === 0 // always true

So "the top of the page" is not the document - it's the scrollable container.


Step 1: Target the Element

const el = document.querySelector("div.whitespace-pre-wrap");

Step 2: Find the Scroll Container

This helper walks up the DOM and finds the element that actually scrolls:

function findScrollParent(element) {
  let parent = element.parentElement;

  while (parent) {
    const style = getComputedStyle(parent);
    if (/(auto|scroll)/.test(style.overflowY)) {
      return parent;
    }
    parent = parent.parentElement;
  }

  return document.documentElement;
}

const container = findScrollParent(el);

Step 3: Calculate the Correct Y Position.

This gives you the distance from the beginning of the scrollable page:

const y =
  el.getBoundingClientRect().top -
  container.getBoundingClientRect().top +
  container.scrollTop;

console.log(y);
```js
This works even when `windows.scrollY === 0`.

How to verify the Y Value is Correct

Test 1: Scroll to it

If the value is correct, the element will align perfectly:

container.scrollTo({
  top: y,
  behavior: "smooth"
});

Test 2: Visual Marker

Draw a horizontal line at the calculated Y:

const marker = document.createElement("div");
marker.style.position = "absolute";
marker.style.left = "0";
marker.style.right = "0";
marker.style.background = "red";
marker.style.height = "2px";
marker.style.top = y + "px";
document.body.appendChild(marker);

Test 3: Reverse Check

container.scrollTop = y;
const diff = 
  el.getBoundingClientRect().top() - 
  container.getBoudningClientRect().top;
console.log(diff);

What Does NOT Work (and Why)

window.scrollY // page doesn't scroll
document.body.scrollTop
element.offsetTop // breaks with nested layouts

Key Takeaways

  • window.scrollY only works when the document scrolls
  • ChatGPT uses an internal scroll container
  • Always compute positions relative to the scroll container
  • Use getBoundingClientRect + scrollTop for reliable results

Final snippet

const el = document.querySelector("div.whitespace-pre-wrap");
const container = findScrollParent(el);

const y = 
  el.getBoundingClientRect().top -
  container.getBoundingClientRect().top +
  container.scrollTop;

When This Pattern Is Useful

  • Browser extensions
  • UI automation (Playwright / Selenium)
  • Auto-scrolling chat UIs
  • Virtualized lists
  • Any SPA where windows.scrollY is useless