Manipulating DOM Visuals
Once you have a reference to a DOM element (here denoted with the el
variable) you might want to find out it's size, relate it to cursor coordinates or move it. Where possible use CSS classes to manipulate the appearance of elements to simplify your code. Adding a class and using transitions is an easy to make an element move with animation, for example.
If you want to experiment with these, open this JSFiddle. The box on the right shows various position/size properties. Use the drop-down to pick a different element. Observe how the values change when you scroll the page. Try changing the CSS for the different boxes to see how values change.
Getting the position
Get the position an element is actually being shown at, relative to the browser viewport with getBoundingClientRect
:
const rect = el.getBoundingClientRect();
// 'rect' contains left, top, right, bottom, x, y, width and height properties
You can also use offsetLeft
and offsetTop
to get integer-rounded locations. Remember that the values are relative to the viewport (ie. the size of the browser window), and thus might be quite different to how the position was set in CSS.
Viewport-relative units go great with elements that have CSS position: fixed
, because it works on the same principle. For example:
<div id="box">
BOX
</div>
#box {
display: inline-block;
position: fixed;
left: 10px;
}
offsetLeft
works just like we expect, with the same value as in the CSS. If you've used a relative unit (like rem
) it will return a pixel value regardless.
console.log(el.offsetLeft); // 10
CSS positions
At times you might want to work with coordinates in relation to how they are defined in CSS. Unfortunately it's not as simple as it could be.
Take for example this DIV that has '5px' set as its left style:
<div style="left:5px" id="box">
BOX
</div>
You can fetch it by accessing style.left
of the element:
console.log(el.style.left); // "5px"
However it doesn't work if property is not assigned directly on the element, for example:
<div id="box">
BOX
</div>
#box {
left: 5px
}
console.log(el.style.left); // Empty result
It gives an empty result because the style 'left' is not defined on the element, but on class 'box'.
To get around this, use getComputedStyle
and getPropertyValue
instead. This takes into account all the possible influences on the position, and gives you whatever CSS value is in force.
const style = window.getComputedStyle(el);
style.getPropertyValue("left"); // "5px"
For both of these approaches, a string value is returned. To perform computations on it, use parseInt
to convert it to a number.
const left = parseInt(el.style.left, 10); // Convert "5px" into 5
console.log(left); // 5
Setting the position
To set the position of an element, you're really just manipulating it's CSS properties, so everything you know about CSS positioning can be applied here.
Test how to move the element with just CSS - such as live editing the CSS in the developer tools - before trying it in Javascript
For example, to set the left
property to 10 pixels:
el.style.left = "10px";
The easy case for setting the position is when the item has position: fixed
, to stay working in viewport-relative units.
For example, if you want to nudge the element from its current position:
el.style.left = (el.offsetLeft + 10) + "px"
Without fixed positioning, the best approach to perform a relative move is:
const el = document.getElementById('box');
const style = window.getComputedStyle(el);
el.style.left = (parseInt(style.getPropertyValue("left"), 10) + 10) + "px";
Don't forget that the CSS positionining rules still apply. If your element is positioned with position: relative
, setting el.style.left = "-1rem"
will set it negative 1rem, in relation to its parent.
Scrolling
Commonly used to check the overall scrolling of the body (as in the below example) but can also be used for internal scrolling of elements where it is enabled.
const top = document.body.scrollTop;
const left = document.body.scrollLeft;
These values can also be set, eg to scroll to the top-left of the page:
document.body.scrollTop = 0;
document.body.scrollLeft = 0;
Or for example to nudge the scrolling by an amount:
document.body.scrollTop += 50;
Read more
- Measuring Element Dimensions and Location.aspx) MSDN
- getBoundingClientRect
- scrollLeft, scrollTop
- offsetLeft, offsetRight
Dimensions
Relative to viewport:
const rect = el.getBoundingClientRect();
// 'rect' contains left, top, right, bottom, x, y, width and height properties
You can also use offsetHeight
and offsetWidth
properties, which is rounded to an even number. These dimensions are effectively the visible size of the element, but does and thus does not include the margin.
const width = el.offsetWidth;
clientHeight
and clientWidth
is similar, but does not include border or scrollbar dimensions. scrollWidth
and scrollHeight
is size including stuff not visible due to scrolling.
- Determining the dimensions of elements MDN
- Measuring Element Dimensions and Location.aspx) MSDN
- getBoundingClientRect
- offsetWidth, offsetHeight
- clientWidth, clientHeight
- scrollWidth, scrollHeight
Viewport dimensions
You can get the dimensions of the viewport itself - ie the browser window - using the window
object:
window.innerWidth;
window.innerHeight;
Or the user's screen:
window.screen.innerWidth;
window.screen.innerHeight;
Read more
Centre points
Once you have the coordinates and dimensions of an element, you can calculate its centre.
For example, to position an element in the middle of the viewport:
const winHalfWidth = window.innerWidth / 2;
const winHalfHeight = window.innerHeight /2;
const el = document.getElementById('box');
const elRect = el.getBoundingClientRect();
const elHalfWidth = elRect.width / 2;
const elHalfHeight = elRect.height / 2;
el.style.left = (winHalfWidth-elHalfWidth) + "px";
el.style.top = (winHalfHeight-elHalfHeight) +"px";
In most cases though you'll want to set positions using CSS, since it takes care of when the browser resizes and so on.
More
- Get and element's position - A visual guide to the tricks and traps for positions