Element sizes and positions

While developing real JavaScript applications, you'll often encounter the need to know the positions and dimensions/sizes of HTML elements i.e their width, their height, their position from top of the viewport or the page and so on.

Just for an example, if you were to write a library for lazy loading images then you would've to calculate the offsets of images from the top of the document to determine exactly when to load them up.

We have a whole course dedicated to teaching lazy loading, in fine detail, at Learn Lazy Loading.

And this is just one example - there are many such simple and complex features in JavaScript that need to know HTML element dimensions. How we get these is what this unit is all about.

We will see what are bounding boxes and computed styles. We will see how to get the width and height of an element in addition to how to get the distance of the its top and bottom edges from the top of the viewport and that of its left and right edges from the left of the viewport. In short there is much to cover in this unit all of which is highly useful as a JavaScript developer to know!

Let's start by going over the limitations we have in getting an element's dimensions using the style property before moving on to explore solutions to it, in the next chapters.

The problem with style

Can we use the style property on DOM elements to get their absolute widths?

In the HTML DOM style property chapter we saw how the style property can be used to set inline styles for a given element; and get the ones that have already been set.

There we also stated that the property can ONLY return an element's inline styles; NOT the ones in a <style> tag or an external stylesheet. If you didn't quite get the idea of what we said let's consider an example.

Suppose we have the following HTML element and want to get its actual width in pixels. We can't at least rely on style to get this job done:

<p>A paragraph</p>
var ele = document.getElementsByTagName("p")[0];
console.log(ele.style.width) // ""

The property returns nothing useful to us; just an empty string. Even if we had specified a custom CSS width for the element anywhere else, except for the style attribute, then also we would get an empty string returned.

It's only in some cases, that we can get some useful output from style as shown below:

<p style="width: 100px;">A paragraph</p>
ele.style.width; // "100px"

Here we've given the element a custom CSS width inside its style attribute, which is then extracted using the expression ele.style.width. However, the value still isn't directly useful - we have to parse a number out of this returned string using the parseInt() method.

To add to this discussion, even just having a value won't necessarily solve the width problem - what if we had a percentage width:

<p style="width: 10%;">A paragraph</p>
ele.style.width; // "10%"

As you can see here, we get the same "10%" value returned by ele.style.width which is of no use to us, at least in this case. We wanted an absolute pixel width but the style property limited us by returning whatever we wrote, as it is.

But this doesn't stop here - exploring the other side of the mirror, what if we wanted to get an element's distance from the top of an HTML document? It turns out that this doesn't only depend on the margins and positions of the element itself, but also on these properties of all its parents.

Consider the following example where the <p> element has a distance of 140px from the top of the document:

<body style="padding: 100px;margin-top: 20px">
    <div style="margin-top: 20px;">
        <p>A paragraph</p>

This value comes about after considering the margins and padding of <div> as well as those of the <body> element.

In real scenarios, however, we need to consider much more than just these two properties - we need to look into border, box-sizing, position, relative dimensions and way more.

Therefore it turns out that style doesn't offer us any reliable result to get the dimensions or positional co-ordiantes of HTML elements on a document. We definitely need better alternatives, that work efficiently and effectively in solving this problem.

Let's discover those....