The box model

The browser rendering engine takes every single HTML element to be bounded by a box. In other words, rendering content on the web is based on a box model.

The box encapsulates all the content, padding and borders of a given element. It is a grouped unit which browsers use to layout content on a webpage, wrap text, set scrollbars and much more. It is also utilised in calculating an element's offsets, its width and height.

Let's see how this box looks for an HTML element.

Border-box
Padding box
Content box

The bounding box essentially comprises of the following three components:

  1. At its core lies the content box where all the actual content dwells
  2. The padding box holds the padding of the element, given by padding.
  3. Finally the border box holds the borders of the element defined by border.

When the element has only padding and content in it, its padding box equals the bounding box; when it has only borders and content in it the border box equals the bounding box; when it has all three again its border box equals its bounding box; and when it has none of these its content box equals the bounding box.

A method to help

In JavaScript, we can use the getBoundingClientRect() method on an element node to get the various dimensions of its bounding box i.e its width, height and so on. The method returns a DOMRect object with a number of properties accounting for different aspects of the bounding box.

Suppose we have the following CSS for an element p:

p {
    width: 200px;
    height: 100px;
    padding: 50px;
    border: 25px solid black;
}

What can you tell about the width of the bounding box of this element?

Determine the width of the bounding box of the p element shown above.

  • 200px
  • 275px
  • 300px
  • 350px

From the code above we can deduce it should be 350px (200px for the width of the content box, 50 + 50 = 100px for the padding on both sides and, 25 + 25 = 50px for the borders on both sides).

Let's see what the method getBoundingClientRect() gives us in its width property:

// Suppose that ele = document.getElementsByTagName("p")[0];
ele.getBoundingClientRect().width; // 350

So as you can see it matches the width we calculated above i.e total width of the bounding box by summing the content box's width and the padding and border values.

Apart from the width, let's explore what else does this method offers us with for an element's dimensions.

ele.getBoundingClientRect(); // DOMRect {x: 0, y: 0, width: 350, height: 250, top: 0, left: 0, bottom: 0, right: 0}

The object it returns contains the properties:

  1. x: same as left
  2. y: same as top
  3. width: width of the element's bounding box
  4. height: height of the element's bounding box
  5. left: distance of the left edge of the element from the left of the viewport
  6. top: distance of the top edge the element from the top of the viewport
  7. right: distance of the element's right edge from the left of the viewport
  8. bottom: distance of the bottom edge of the element from the top of the viewport
Some browsers might not support properties x and y, therefore it is best to stick with left and top respectively.
On Internet Explorer and Edge, this method returns a ClientRect object instead of DOMRect, without the properties x and y.

The properties width and height are clear in their meaning and you can infer right away what they would return, right?

What might be new for you are the rest of the properties also known as offsets of an element. Offsets are distances of an element's edges from the viewport, commonly used when scroll events are needed to be attached to a document. We'll see them in more detail in the next chapters but for now let's just take a simple look at the properties left and top.

First for top:

A div of height 100px

A paragraph of 50px height.

var ele = document.getElementById("p1");
var rect = ele.getBoundingClientRect();
console.log(rect.top); // 124

Now for left:

A paragraph with 50px left margin.

var ele = document.getElementById("p1");
var rect = ele.getBoundingClientRect();
console.log(rect.left); // 58

In both these cases we get values greater than the expected ones due to preset margins on HTML elements p and body. Try removing them using CSS and then again log the offset values above and you'll get 100 and 50 respectively. It's all about thinking and understanding!