CSS3 Tutorial – CSS Box Model

css3_logoEvery element in web design is a rectangular box. IN a previous post, Positioning & Inline, you learned about where the box is displayed. But that is only part of the story. The other part is about padding, border, and margin and how they affect where the box is displayed.

When you type in F12 in your favorite debugger, you will find tools that help you figure out the values in your style sheets for the size and location of the box.

Internet Explorer Chrome Firefox
image image image

But what happens when you do not declare your widths? What happens then?

This post relies on Chris Coyier’s excellent post The CSS Box Model.

The browsers will let you edit the values there too, so you can try out changes. Click F12 to bring up the developer tools, and you can find the style box rendering.

And most browsers let you edit the values. You can double click on the value in the box frame and change the value to see its affect on your page temporarily.

image

Width and Margins

First of all, the margin is a special case. Margin is unique in that it doesn’t affect the size of the box itself per se, but it affects other content interacting with the box, and thus an important part of the CSS box model.

So what about the default values inside “the box”? The size of the box inside the border is calculated like this:

Width
width + padding-left + padding-right + border-left + border-right

Height
height + padding-top + padding-bottom + border-top + border-bottom

But that begs the question, what are the defaults in each situation? Well, its can be confusing.

Default Width of Block Level Boxes

But what if the values are not declared?

  • If padding or borders are undeclared, they are either zero (likely if you are using a css reset) or the browser default value (probably not zero especially on form elements that are commonly not reset).
  • If the width of a box is undeclared (and the box is a block level element), things get a little weirder. Let’s start with that, and then move on to some other good-to-know stuff about the box model.

Let’s look at an example.


<div style="width: 300px; background-color: azure; border: 1px solid blue">
<div style="padding: 20px; background-color: lightgoldenrodyellow">This box has a padding of 20 pixels. Now is the time for all good men to come to the aid of their country. The quick fox jumped over the road.</div>
<div></div>
<div style="padding: 20px; width: 100%; background-color: lightcoral">This box has a padding of 20 pixels and a width of 100%. Now is the time for all good men to come to the aid of their country. The quick fox jumped over the road.</div>
</div>

image

If you don’t declare a width, and the box has static or relative positioning, the width will remain 100% in width, but the padding and border will push inwards instead of outward, as shown on the top div. 

But if you explicitly set the width of the box to be 100%, the padding will push the box outward as normal.

The lesson here being that the default width of a box isn’t really 100% but a less tangible “whatever is left”. This is particularly valuable to know, since there are lots of circumstances where it is immensely useful to either set or not set a width.

This concept applies directly to textarea element, where the width is in the cols attribute. You may need a text area set to 100%, yet have padding too. But the padding does not work as you expect.

Absolute Boxes

Absolutely positioned boxes that have no width set on them behave a bit strangely. Their width is only as wide as it needs to be to hold the content. So if the box contains a single word, the box is only as wide as that word renders. If it grows to two words, it’ll grow that wide.


<div style="width: 300px; border: 1px solid blue">
<div style="position: absolute;
background-color: powderblue;">hello</div>
</div>
<div style="position: relative;">&nbsp;</div>
<div style="width: 300px; border: 1px solid red">
<div style="position: absolute;
background-color: lightgoldenrodyellow">hello there</div>
</div>
<div style="position: relative;">&nbsp;</div>
<div style="width: 300px; border: 1px solid green">
<div style="position: absolute;
background-color: lightgreen">Now is the time for all good men to come to the aid of their country. The quick fox jumped over the lazy dog.</div>
</div>
<div style="position: relative;">&nbsp;</div>
<div style="border: 1px solid green">
<div style="position: absolute; width: 300px;
background-color: lightgreen">Now is the time for all good men to come to the aid of their country. The quick fox jumped over the lazy dog.</div>
</div>

image

This should continue until the box is 100% of the parent’s width (the nearest parent with relative positioning, or browser window) and then begin to wrap.

There are plenty of quirks in how different browsers handle this, not to mention just the fact that text renders differently across platforms. (IE 7, 8 and 9 look different than IE 10 in the preceding example.)

Floating Box With No Width

The same exact behavior is seen with floated elements with no widths. The box is only as wide as it needs to be to accommodate the content, up to as wide as its parent element (doesn’t need to be relatively positioned though). Because of the fragile nature of these width-less boxes, the lesson to take away here is to not rely on them in mission-critical scenarios, like in overall page layout. If you float a column to use as a sidebar and count on some element inside (like an image) to be responsible for holding its width, you are asking for trouble.

Inline Boxes

You can think of them as really really long and skinny rectangles, that just so happen to wrap at every line. They are able to have margin, padding, borders just like any other box.


<div style="border: 1px solid orange">
<span style="width: 300px; margin-left: 100px; padding: 3px 3px 3px 3px;
background-color: lightgreen">Now is the time for all good men to come to the aid of their country. The quick fox jumped over the lazy dog.</span>
<span style="width: 300px; margin-left: 100px; padding: 3px 3px 3px 3px;
background-color: lightgreen">Now is the time for all good men to come to the aid of their country. The quick fox jumped over the lazy dog.</span>
</div>

image

The wrapping is what makes it confusing. A left margin as shown above pushes the box to the right as you would suspect, but only the first line, as that is the beginning of the box. Padding is applied above and below the text like it should be, and when it wraps it ignores the line above its padding and begins where the line-height dictates it should begin. The background was applied with transparency to see how it works more clearly.

See It On Your Page

To see every single “box” that makes up a page? Try putting this in the style sheet temporarily:


* {
border: 1px solid red !important;
}

References

The CSS Box Model