# Coordinates
To move elements around we should be familiar with coordinates.
Most JavaScript methods deal with one of two coordinate systems:
1. Relative to the window(or another viewport) top/left.
2. Relative to the document top/left.
It's important to understand the difference and which type is where.
[cut]
## Window coordinates: getBoundingClientRect
Window coordinates start at the left-upper corner of the window.
The method `elem.getBoundingClientRect()` returns window coordinates for `elem` as an object with properties:
- `top` -- Y-coordinate for the top element edge,
- `left` -- X-coordinate for the left element edge,
- `right` -- X-coordinate for the right element edge,
- `bottom` -- Y-coordinate for the bottom element edge.
Like this:

Window coordinates do not take the scrolled out part of the document into account, they are calculated from the window left-upper corner.
In other words, when we scroll the page, the element goes up or down, *its window coordinates change*. That's very important.
```online
Click the button to see its window coordinates:
If you scroll the page, the button position changes, and window coordinates as well.
```
Also:
- Coordinates may be decimal fractions. That's normal, internally browser uses them for calculations. We don't have to round them when setting to `style.position.left/top`, the browser is fine with fractions.
- Coordinates may be negative. For instance, if the page is scrolled down and the `elem` top is now above the window then `elem.getBoundingClientRect().top` is negative.
- Some browsers (like Chrome) also add to the result `getBoundingClientRect` properties `width` and `height`. We can get them also by substraction: `height=bottom-top`, `width=right-left`.
```warn header="Coordinates right/bottom are different from CSS properties"
If we compare window coordinates versus CSS positioning, then there are obvious similarities to `position:fixed` -- also the position relative to the viewport.
But in CSS the `right` property means the distance from the right edge, and the `bottom` -- from the bottom edge.
If we just look at the picture below, we can see that in JavaScript it is not so. All window coordinates are counted from the upper-left corner, including these ones.
```
## elementFromPoint(x, y) [#elementFromPoint]
The call to `document.elementFromPoint(x, y)` returns the most nested element at window coordinates `(x, y)`.
The syntax is:
```js
let elem = document.elementFromPoint(x, y);
```
For instance, the code below highlights and outputs the tag of the element that is now in the middle of the window:
```js run
let centerX = document.documentElement.clientWidth / 2;
let centerY = document.documentElement.clientHeight / 2;
let elem = document.elementFromPoint(centerX, centerY);
elem.style.background = "red";
alert(elem.tagName);
```
As it uses window coordinates, the element may be different depending on the current scroll position.
````warn header="For out-of-window coordinates the `elementFromPoint` returns `null`"
The method `document.elementFromPoint(x,y)` only works if `(x,y)` are inside the visible area.
If any of the coordinates is negative or exceeds the window width/height, then it returns `null`.
In most cases such behavior is not a problem, but we should keep that in mind.
Here's a typical error that may occur if we don't check for it:
```js
let elem = document.elementFromPoint(x, y);
// if the coordinates happen to be out of the window, then elem = null
*!*
elem.style.background = ''; // Error!
*/!*
```
````
## Using for position:fixed
Most of time we need coordinates to position something. In CSS, to position an element relative to the viewport we use `position:fixed` together with `left/top` (or `right/bottom`).
We can use `getBoundingClientRect` to get coordinates of an element, and then to show something near it.
For instance, the function `createMessageUnder(elem, html)` below shows the message under `elem`:
```js
let elem = document.getElementById("coords-show-mark");
function createMessageUnder(elem, html) {
// create message element
let message = document.createElement('div');
// better to use a css class for the style here
message.style.cssText = "position:fixed; color: red";
*!*
// assign coordinates, don't forget "px"!
let coords = elem.getBoundingClientRect();
message.style.left = coords.left + "px";
message.style.top = coords.bottom + "px";
*/!*
message.innerHTML = html;
return message;
}
// Usage:
// add it for 5 seconds in the document
let message = createMessageUnder(elem, 'Hello, world!');
document.body.append(message);
setTimeout(() => message.remove(), 5000);
```
```online
Click the button to run it:
```
The code can be modified to show the message at the left, right, below, apply CSS animations to "fade it in" and so on. That's easy, as we have all the coordinates and sizes of the element.
But note the important detail: when the page is scrolled, the message flows away from the button.
The reason is obvious: the message element relies on `position:fixed`, so it remains at the same place of the window while the page scrolls away.
To change that, we need to use document-based coordinates and `position:absolute`.
## Document coordinates
Document-relative coordinates start from the left-upper corner of the document, not the window.
In CSS, window coordinates correspond to `position:fixed`, while document coordinates are similar to `position:absolute` on top.
We can use `position:absolute` and `top/left` to put something at a certain place of the document, so that it remains there during a page scroll. But we need the right coordinates first.
For clarity we'll call window coordinates `(clientX,clientY)` and document coordinates `(pageX,pageY)`.
When the page is not scrolled, then window coordinate and document coordinates are actually the same. Their zero points match too:

And if we scroll it, then `(clientX,clientY)` change, because they are relative to the window, but `(pageX,pageY)` remain the same.
Here's the same page after the vertical scroll:

- `clientY` of the header `"From today's featured article"` became `0`, because the element is now on window top.
- `clientX` didn't change, as we didn't scroll horizontally.
- `pageX` and `pageY` coordinates of the element are still the same, because they are relative to the document.
## Getting document coordinates [#getCoords]
There's no standard method to get document coordinates of an element. But it's easy to write it.
The two coordinate systems are connected by the formula:
- `pageY` = `clientY` + height of the scrolled-out vertical part of the document.
- `pageX` = `clientX` + width of the scrolled-out horizontal part of the document.
The function `getCoords(elem)` will take window coordinates from `elem.getBoundingClientRect()` and add the current scroll to them:
```js
// get document coordinates of the element
function getCoords(elem) {
let box = elem.getBoundingClientRect();
return {
top: box.top + pageYOffset,
left: box.left + pageXOffset
};
}
```
## Summary
Any point on the page has coordinates:
1. Relative to the window -- `elem.getBoundingClientRect()`.
2. Relative to the document -- `elem.getBoundingClientRect()` plus the current page scroll.
Window coordinates are great to use with `position:fixed`, and document coordinates do well with `position:absolute`.
Both coordinate systems have their "pro" and "contra", there are times we need one or the other one, just like CSS `position` `absolute` and `fixed`.