Tools: How to Get the Correct Y Position of an Element in CHATGPT UI (2026)

Tools: How to Get the Correct Y Position of an Element in CHATGPT UI (2026)

The Problem

Why window.scrollY Is Always 0

Step 1: Target the Element

Step 2: Find the Scroll Container

Step 3: Calculate the Correct Y Position.

How to verify the Y Value is Correct

Test 1: Scroll to it

Test 2: Visual Marker

Test 3: Reverse Check

What Does NOT Work (and Why)

Key Takeaways

Final snippet

When This Pattern Is Useful You try to get the vertical position of an element like this: ...but it always returns 0. Even worse, this common pattern also fails: If you're inspecting the ChatGPT web UI, this can be very confusing. In ChatGPT (and many modern web apps): So "the top of the page" is not the document - it's the scrollable container. This helper walks up the DOM and finds the element that actually scrolls: This gives you the distance from the beginning of the scrollable page: If the value is correct, the element will align perfectly: Draw a horizontal line at the calculated Y: Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to ? It will become hidden in your post, but will still be visible via the comment's permalink. as well , this person and/or

Code Block

Copy

window.scrollY CODE_BLOCK: window.scrollY CODE_BLOCK: window.scrollY CODE_BLOCK: element.getBoundingClientRect().top + window.scrollY CODE_BLOCK: element.getBoundingClientRect().top + window.scrollY CODE_BLOCK: element.getBoundingClientRect().top + window.scrollY CODE_BLOCK: window.scrollY === 0 // always true CODE_BLOCK: window.scrollY === 0 // always true CODE_BLOCK: window.scrollY === 0 // always true CODE_BLOCK: const el = document.querySelector("div.whitespace-pre-wrap"); CODE_BLOCK: const el = document.querySelector("div.whitespace-pre-wrap"); CODE_BLOCK: const el = document.querySelector("div.whitespace-pre-wrap"); CODE_BLOCK: 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); CODE_BLOCK: 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); CODE_BLOCK: 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); CODE_BLOCK: const y = el.getBoundingClientRect().top - container.getBoundingClientRect().top + container.scrollTop; console.log(y); CODE_BLOCK: const y = el.getBoundingClientRect().top - container.getBoundingClientRect().top + container.scrollTop; console.log(y); CODE_BLOCK: const y = el.getBoundingClientRect().top - container.getBoundingClientRect().top + container.scrollTop; console.log(y); CODE_BLOCK: container.scrollTo({ top: y, behavior: "smooth" }); CODE_BLOCK: container.scrollTo({ top: y, behavior: "smooth" }); CODE_BLOCK: container.scrollTo({ top: y, behavior: "smooth" }); CODE_BLOCK: 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); CODE_BLOCK: 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); CODE_BLOCK: 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); CODE_BLOCK: container.scrollTop = y; const diff = el.getBoundingClientRect().top() - container.getBoudningClientRect().top; console.log(diff); CODE_BLOCK: container.scrollTop = y; const diff = el.getBoundingClientRect().top() - container.getBoudningClientRect().top; console.log(diff); CODE_BLOCK: container.scrollTop = y; const diff = el.getBoundingClientRect().top() - container.getBoudningClientRect().top; console.log(diff); CODE_BLOCK: window.scrollY // page doesn't scroll document.body.scrollTop element.offsetTop // breaks with nested layouts CODE_BLOCK: window.scrollY // page doesn't scroll document.body.scrollTop element.offsetTop // breaks with nested layouts CODE_BLOCK: window.scrollY // page doesn't scroll document.body.scrollTop element.offsetTop // breaks with nested layouts CODE_BLOCK: const el = document.querySelector("div.whitespace-pre-wrap"); const container = findScrollParent(el); const y = el.getBoundingClientRect().top - container.getBoundingClientRect().top + container.scrollTop; CODE_BLOCK: const el = document.querySelector("div.whitespace-pre-wrap"); const container = findScrollParent(el); const y = el.getBoundingClientRect().top - container.getBoundingClientRect().top + container.scrollTop; CODE_BLOCK: const el = document.querySelector("div.whitespace-pre-wrap"); const container = findScrollParent(el); const y = el.getBoundingClientRect().top - container.getBoundingClientRect().top + container.scrollTop; - The page itself does not scroll - Scrolling happens inside a nested container - The <body> is fixed-height - 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 - Browser extensions - UI automation (Playwright / Selenium) - Auto-scrolling chat UIs - Virtualized lists - Any SPA where windows.scrollY is useless