Introduction
One of the powerful features of modern HTML and Cascading Style Sheets (CSS) for web development is that you can almost completely separate the markup of your page in HTML from the rendering details specified in your CSS. An HTML page using a small selection of tags and some CSS styling can look like… well, just about anything you like. And you can change how it looks by simply changing the CSS.
A basic - but often misunderstood - feature of CSS styling is something called the box model. The box model simply defines the rectangular space around an element and is defined by three properties:
The widths you assign to these CSS properties add up to the space between the associated HTML element and its neighboring elements. Here’s an example showing all three:
The border represents the effective outer limit of the element itself. The border can be either visible or invisible, and has properties for line type, color, and width.
Padding specifies the spacing between the border and any content within the HTML element. If there’s no visible border, then the extent of the padding is effectively the extent of the element. Any background CSS properties associated with the element are displayed within the area defined by the border and padding properties.
The margin represents the distance between the outer edge of the border and any neighboring elements. This is often a source of confusion as it’s easy to think of the margin as a kind of “padding” between elements. Better to think of it like the margin of a page: it represents the outer edge of the object. The margin is effectively transparent and will not reflect any of the background properties specified for the element.
CSS Syntax
Let’s construct a simple example so you can see the CSS syntax. Here’s the HTML for a simple container div
containing a single line of text:
<div id="container">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
</div>
For visual clarity, we first set up the styling of the body and the “container” div:
body {background: black;}
#container {
background: gray;
width: 600px;
margin: 0px auto;
border: 1px solid black;}
The important thing to note here is that the page background is black and the container div is gray. Now we can format the p
element within the container:
p { background: white;
border: 20px solid red;
margin-top: 20px;
margin-right: 20px;
margin-bottom: 20px;
margin-left: 20px;
padding-top: 20px;
padding-right: 20px;
padding-bottom: 20px;
padding-left: 20px; }
So anything within the border of the p
element should be white - and we’ll have a good, thick, red border so you can’t miss it. Here’s what it looks like:
Note that we specify the top, bottom, left, and right margin and padding values separately in this example. This is one way to specify these values, and similar border-top (and so on) settings are available for the border. This allows you to clearly set any or all border, margin, and padding settings that you need. For example, this is completely acceptable if you only want to specify the top and right margins:
margin-top: 30px;
margin-right: 8px;
However, you can also use CSS shorthand syntax to set these values. This is, in fact, what we’ve done with the border setting so far:
border: 20px solid red;
For the margin and padding, you can set all four values at once using this shorthand:
margin: 0 0 0 0;
padding: 0 0 0 0;
The values are given separated by spaces in clockwise order from the top. In other words:
margin: [top] [right] [bottom] [left]
You have to give all four values, using 0 to indicate no margin or padding in that direction. Any legal CSS unit can be used, though these properties are typically set in %, px, or em values.
Neighboring and Nested Elements
Configuration of the border, margins, and padding for elements in the page markup gives you great flexibility in the design of your site. As with other CSS properties, you can assign styles to elements, element states (hover, for example), IDs, and classes. And a little scripting with JavaScript or jQuery enables you to do some pretty fancy styling on the fly as well.
You need to be aware of combined margin and padding effects of adjacent elements. It’s not always obvious how settings will combine - particularly when style changes affect the placement of elements on the rendered page. And there are some tricks you need to be aware of as well.
First, let’s take a look at a variety of different border, margin, and padding configurations here:
The HTML for this code is pretty straightforward and is just an extension of the previous examples. Each line of text is contained in a separate div
, and each div
has a unique ID.
<div id="container">
<div id="none">Lorem ipsum dolor sit amet....</div>
<div id="margin">Ut enim ad minim veniam....</div>
<div id="padding">Duis aute irure dolor....</div>
...
</div>
Here’s the associated CSS:
#none {
border: 1px solid red;
margin: 0 0 0 0;
padding: 0 0 0 0;}
#margin {
border: 1px solid red;
margin: 20px 20px 20px 20px;
padding: 0 0 0 0;}
#padding {
border: none;
margin: 0 0 0 0;
padding: 20px 20px 20px 20px;}
#marginpadding {
border: none;
margin: 20px 20px 20px 20px;
padding: 20px 20px 20px 20px;}
#marginborderpadding {
border: 20px solid red;
margin: 20px 20px 20px 20px;
padding: 20px 20px 20px 20px;}
Note that the margin and padding are additive, and you’ll need to keep that in mind. 5px here and 10px there can add up to some unexpected placement of elements.
However, there are some exceptions, the most important of which is…
Collapsing Margins
In many cases, when two adjacent elements both have top or bottom margins that touch, the margins combine regardless of your CSS properties for the individual elements. This is called a collapsed margin. Here’s an example:
The four div
s here are all using the same 20px margins and padding all the way around.
#marginpadding {
margin: 20px 20px 20px 20px;
padding: 20px 20px 20px 20px;}
But notice that, while there’s equal padding all the way around each element, the top and bottom margins between elements are clearly less than 20px + 20px = 40px. In this case, it turns out to be OK, and we get appropriate margins all the way around. But it pays to be aware that this behavior is by design. In addition, empty elements will typically collapse completely regardless of margin values, and there are other rules as well. To learn more, read the Collapsing margins section of the W3C CSS Recommendation, which goes into great detail about how and when margins collapse.
Another collapsing margin case is a bit more tricky. Remember that, in the original HTML example, the container has a border. If we take that away…
#container {background: gray; width: 600px; margin: 0px auto;}
…presto, the top and bottom margins collapse completely.
A straightforward remedy is what we had in the first place: a small border that blends in with the background or using the transparent color value. However, in more complicated layouts, you may end up resorting to using dummy elements that negate the collapsing behavior. A close reading of the CSS Recommendation should help you avoid these situations, however.
Negative Margins
So far all of the examples have shown zero or positive margin values. With the CSS2 specification, negative margin values are perfectly legal CSS, too. In a nutshell, negative top and left values let you pull the element up and over, while negative bottom and right values pull adjacent elements into and over the target element. Combine negative margins with z-index and you can create some pretty slick layouts with just a few lines of code.
For example, this CSS turns our previous linear example into a collection of overlapping boxes:
#marginpadding {
margin: 20px 40px 20px 20px;
padding: 20px 20px 20px 20px;
z-index: 1;
position: relative;}
#negativemargin {
background: orange;
margin: -30px 20px -30px 40px;
padding: 20px 20px 20px 20px;
z-index: 2;
position: relative;}
Here’s what it looks like:
There are a lot of great effects you can achieve with negative margins, including multi-column lists, textual drop shadows… the list goes on.
By now you should have a pretty good handle on the box model. Put this together with some knowledge of CSS positioning - see Fluid, multi-column, vertically ordered list using CSS and Relatively Simple 3 Equal-Height Columns CSS Liquid Layout - and you can do quite a bit with not a lot of code.
Happy coding!