Looking for the previous guiStuff?

It's still here, the content didn't go anywhere. You may want to check out this new guiStuff though -- It's rather informative.

References/Tutorials:


Intro Documents:


guiStuff:






::Stuff for the multi-spec coder;

Coding, formats, standards, and other practical things.

 Home  //  CSS Articles  //  The CSS Box Model 

<!-- CSS Articles

The Box Model


Practical usage of CSS requires some understanding of how a page is 'rendered' by a browser. That is to say, how styles are attached to elements, and these elements turned into pixels on the browser viewing pane. CSS and HTML/XHTML are rather intermingled when it comes to rendering by the browser, since most HTML/XHTML tags have inherent style elements that are attached to them, regardless of whether or not they're specifically styled. In fact, many HTML/XHTML tags could be replaced by a properly crafted class that was simply attached to a SPAN element. We know, of course, that there's a reason for the different tags, and that semantic web coding makes for better-structured sites, but if visuals were the only thing that concerned us, then CSS could replace almost any inherent HTML/XHTML tag property we could think of. This is exactly how web browsers "think". They don't see an H1 tag and look up the spec for rendering an H1 element in HTML, they know that, even with no CSS around, an H1 element is simply text with the properties of display: block, margin-top: 1.Xem, margin-bottom:1.Xem, font-size: 2.Xem, approximately. Within the browser, there's complete separation between structure and style.

CSS treats visual elements as rectangles that flow along the document. Although CSS is a broad specification that applies to many devices, this text will focus on how these elements are rendered in web browsers.

To understand how a page is rendered, the box model must first be explained. Visually, it's actually rather simple:

Box Model Diagram

All visual elements within a page are considered to be rectangular boxes, each with its own padding, border, and margin properties. The background-color of an element will effect its content area and its padding, but not the border or margin. The border type can be set to different styles, but its color defaults to the 'foreground' color, which also effects the text within the element. The margin is always transparent, and can be considered the space with which the element distances itself ('pushes' itself away) from adjacent elements (this analogy helps in some cases, but hinders in others).

Width (size) for padding, border, and margin default to 0 if not set explicitly. Margins are the only properties that may be negative. When referring to a box's width and height, the abstract definition refers to that box's entire contents, including padding, border, and margin. Otherwise, the content area box may be referred to specifically, which means that only the width and height of the content area are considered. In practice, the box's width and height differs from one browser implementation to the other -- this will be discussed below.

Block elements and Inline elements

There are two types of boxes -- block, and inline. In CSS, the display property can set an element to either inline or block. Inline elements are elements that do not form their own content block. Text, images, and span areas are all inline elements. Their contents is distributed in lines, normally flowing left-to-right, top-to-bottom. Some elements appear to break the normal flow of content, and create a division when they are placed within a document -- for example: DIV, P, Hx, and TABLE elements. These are all inherently block elements and create their own content blocks. They have the properties of block elements without the need to explicitly set their display property to block. You may still turn any inline element into a block element by setting its display property to block. The other way around, however (turning inherently block elements into inline elements via the display property), is not fully supported and is not recommended.

The Document Tree

Not to be confused with the more complex 'Document Object Model', the Document Tree is a relationship set that XML, HTML, and XHTML adhere to. Technically, non-strict HTML can stray from this set of relationships and still be rendered by a browser, but this is only because the browser "guesses" the author's intentions and fixes the errors on-the-fly.
Basically, elements within an HTML/XHTML page form a "document tree". This means that every element within the document has exactly one parent, except for the HTML element, which is the root element, and thus has none. That is the first 'relationship' of the document tree (the Parent-Child relationship), but there are other relationships between elements that will determine how they will be displayed. The two most basic types of relationships are the preceding element, and the following element. Both of these elements are optional, since the element may be the only 'Child'. Let's take a look at an example:

<html> <head> <title>Page Title</title> </head> <body> <h1>Welcome!</h1> <p>This is some <em>example</em> text.</p> <p>This is the second paragraph on this page.</p> </body> </html>

If you were to break down the above document into its relational tree, you'd notice quite a few relationship definitions. Since this is not a discussion about data structures, we'll focus on the ones that actually effect how elements are displayed on a page. The first relationship actually doesn't effect much, apart from being present: the HTML element is the root element, and has no parent elements. Let's skip to the BODY of the page. There's an H1 element, which we know to be a Block-level element, followed by two P elements (also Block-level elements), the first of which contains an EM element. The BODY is the parent of H1, and the two P's, but not the EM. Technically, the BODY element is an an Ancestor of the EM element, since it is a parent of the EM's parent (the ansector relationship cascades indefinately, so the HTML element is actually the ancestor of all of the document's elements). Finally, let's reach the two basic relationships mentioned above: preceding and following. The H1 has no preceding elements, as it's the first child of the BODY. It does, however, have a following element -- the first P (the one that contains the EM element). The first P (again, the one with the EM element) has both a preceding element, the H1, and a following element, the last P. The last P has one preceding element, the first P, and no following elements, since it's the last child element of the BODY. The EM has no preceding or following element, since it's an 'only child'. In fact, just one more relationship hasn't been covered, even though it's presented nicely within this example: All of the child elements of the BODY element are Siblings. So the H1 and the two P's are Sibling elements.

Why is all of this data-stucture-related material here then? How does it effect how things are rendered in a web browser? Well, as mentioned above, boxes have directions to all of their box-model properties. Their padding, border, and margins can all be assigned different values to different directions. Look at the relationships of the elements from the example above. The H1, and both P's, will be placed one after the other, since they're all Block elements. However, the EM within th first P is an inline element, which means it will flow along with the document. In other words, while the boxes of the H1 and both P's mainly concern themselves with vertical properties, the EM element will be surrounded with elements on all sides. While the preceding element of the last P is the first P, which is above it, the preceeding element of the EM element is the text "This is some ", which is in fact considered by the browser to be another element, a sub-content element of the first P, which is placed to the left of the EM element. Block and inline elements effect whether preceding or following elements are placed vertically, or horizontally.

Box Hierarchy

Vertical vs. Horizontal placement is just one thing to keep in mind. Consdier how this type of relationship applies to the boxes within the document. All boxes within a document are contained within other (parent) boxes, or blocks. If there is no block to contain the most external box, then the browser window is considered to be the outer-most box (or the root block). Hence, when assigning percentage values to the width and height properties of non-absolutely-positioned elements, these percentages are of the corresponding width and height of that element's containing (parent) block. Now consider how this would apply to designing lists, or nested DIVs and SPANs. You have to take many variables into account, or you'll be surprized (and likely rather annoyed) at the outcome.

The Box Model Problem

If all of this wasn't enough to get your mind in a knot, there's still the browser compatibility problem to deal with. Yes, there's a major compatibility issue that persists and will continue to persist in modern browsers. There are actually two Box Models, as it were. Don't worry, it doesn't mean you have to re-learn anything, just to understand how Mozilla (FireFox) sees things as opposed to how Internet Explorer sees them. The W3C CSS specification defines the width of the box as the width of the content area alone, not including the padding, border, or margin. Internet Explorer implements another Box Model, which is valid, it's simply not the default: in it, the width of a box includes both padding and border. This sounds like a bigger problem than it is, though it's still a respectably-sized problem. Before going into the 'how do I throw in the magic words into my CSS' solution, consider that there's a strategic solution. Instead of creating elements and setting their size to the shifting width value, try to design pages so that you 'pour' content into padding-less, border-less elements instead. For example:

<style type="text/css"> <!-- #container { width: 200px; } .fluid { border-style:solid; border-width: 5px; border-color: #999; padding: 5px; width:auto; } --> </style> <div id="container"> <p class="fluid">Content!</p> </div>

It's important to note that the width of the fluid class is set to auto, and not 100%. If it is set to 100%, then you're back to square one, since Mozilla/FireFox will assume that your intention was to set the content area to 100% of the parent's width, which is 200px. However, if your design needs to implement the second Box Model, which many consider to be the more intuitive one, there is a special sauce that you can use:

box-sizing: border-box -moz-box-sizing: border-box;

By placing the above declarations in your CSS, you're explicitly telling the browser that you want the box size to include its padding and border. Browser support may vary, and you may want to check compatibility. As usual, you can always have two different style sheets for the two models/browsers, but then you're involving scripting when you can possibly avoid it.

There's a lot more to cover when it comes to document rendering, but hopefully this answers a few primary threads of interest that pertain to the Box Model and some of the Visual Formatting Model. Remember to test your pages on multiple browsers, and, when possible, platforms. Also, when it doubt, stick to the standards, and then condition your way to the cross-browser goal. Check which browsers support which parts of the standards properly, and fall back from there, not the other way around.



Return to the CSS Articles section, or go the to Main page.





Looking for the old guiStuff?

It's still here, the old content didn't go anywhere.