At the risk of over-repeating myself: every element in web design is a rectangular box. This was my ah-ha moment that helped me really start to understand CSS-based web design and accomplish the layouts I wanted to accomplish. We’ve talked about the positioning of these boxes a bit, and about their behavior.
What we haven’t talked about much is the box itself. How is the size of the box calculated exactly?
Here is a diagram:
If you are a Firebug user, you might be used to the diagram like this, which does a nice job of showing you the numbers affecting any box on the page:
Notice in both examples the margin is in the white. 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.
The size of the box itself is calculated like this:
Width | width + padding-left + padding-right + border-left + border-right |
Height | height + padding-top + padding-bottom + border-top + border-bottom |
What if these values are undeclared?
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.
The Default Width of Block Level Boxes
If you don’t declare a width, and the box has static or relative positioning, the width will remain 100% in width and the padding and border will push inwards instead of outward. 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.
The biggest ass-biter I always find with this is textarea elements, which very much need their widths set to fight the required “cols” attribute, and are unable to have children elements. So you often need the textarea to be explicitly set to 100%, yet have padding as well, pushing it too large to fit. In a static width environment, we often resort to pixel widths that fit, but no such luck in fluid width environments.
Absolute Boxes with No Width
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.
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. It feels natural and normal for boxes to expand vertically to accommodate content, but it just feels strange when it happens horizontally. That strange feeling is warranted, as there are plenty of quirks in how different browsers handle this, not to mention just the fact that text renders differently across platforms.
Floated Boxes 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 Elements are Boxes Too
We’ve been kind of focusing on boxes as block-level elements here. It’s easy to think of block-level elements as boxes, but inline elements are boxes too. 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.
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 with your own eyes
Wanna see every single “box” that makes up a page? Try putting this in the stylesheet temporarily:
* {
outline: 1px solid red !important;
}
Wow this is great! Lot’s a neat little tidbits I didn’t know. :)
Good explanation. I will point people to this.
I think that in IE floated boxes still have the 100% or “whatever is left” width, so you need to set a width if you want it to be next to something. I most commonly come across it when floating a nav next to a site title.
Yep, the best thing to do is always set a width on anything floated, absolutely positioned, or fixed positioned to avoid cross browser problems.
Another IE fix with floated elements is to add ‘display: inline’ to the CSS tag.
Good Idea, I didn’t realise that! :-)
–Note to Self–
Be sure to set display:inline before attempting to tweak margins. Oh, the fun I had on one occasion due to missing that tiny (but important) detail.
Yes, it is tricky to set width 100% than fix in pixel. Because pixel varies on different browser.
I hate dealing with IE when it comes to CSS because it renders everything so wrong. Why can’t Microsoft make their browser up to W3C Standards?
very cool! great for someone who is just starting to learn css.
The border on everything is a simple testing tool and can be very revealing.
The web developer toolbar for Firefox shows you all the boxes.. :)
download link
Once again, you’ve outdone yourself with a concise and informative piece of writing. Keep it coming!
Very cool. This is exactly at the level I’m at as a part-time as-needed dabbler. Didn’t know any of this and now it all makes complete sense.
Wow you really took this “Use padding for padding, not positioning” twit seriously. Kinda suprised you will do a box model tutorial in mid of 2009, but again it’s never too late for basics. Excellent presentation of info as usual.
I hate to be a spelling nazi, but it’s “per se”, not “per say”.
Don’t then
This post and the ‘overflow’ post were really helpful. Picked a few things up that could save me some time and frustration.
who cares what the spelling is, if you understood what he meant than just move on. reading your stupid reply just wasted my time.
Wow…you’re an ass.
lick my hairy nut sack Mike & Benjamin
Incorrect. Reading his reply was educational. Reading your post was a waste of everyone’s time. Grow up “jh”.
Hey Afe, you did well, thanks for the small tip.
Great article, thanks!
Reading it I discovered why in your screencasts and articles you reset always margins and padding to 0. Can you give us some tips and tricks related to other markup tags like p, ul, li etc.? I understand that this depends deeply on what you are trying to do, but maybe there are some general rules that you can show us.
Thanks!
Nice post Chris!
By the way how is the box of the TEXT calculated, and how to remove the space surrounding the text by default? Like in the example you made, where it says “hello” there is 1px at the top and 5px at the bottom, and if you increase the font-size that increases too.
I tried by reducing the line-height, but there is always a little extra surrounding.
I suppose that what you mean is the case of font rendering method and differs in each browser. Some fonts are rendered the same way cross-browser and some are not (i.e. Arial). I have found it pretty annoying.
the 1 pixel border has been the default testing tool since what 1997… earlier…. when ever tables were introduced….
Thank You for the Box Model refresher!!!
I am a huge fan of using background colours for testing as it wont break your widths / layout. Aardvark has become one of my no. 1 tools and it has a really nice coulourisation feature where you highlight the element and it will assign a random bg colour to it.
A combination of that and a debug section of css with bg colours is something I use every day when debugging layouts.
Anyways, another great article and I like your back to basics approach to a lot of things.
P.S. Just noticed how cool your appendix notes for links is… progressive enhancement FTW!
awww… the cool link appendix never showed :(
so padding is inside the box by default, but outside when you say width 100% ??? :-(
Padding is still inside the box when the width is 100%. In this example the parent element has a width of 300px. Setting the child element to 100% with a 20px padding makes the box 340px wide (300 width from the parent + 20px left padding + 20px right padding). I think the parent element having a static width is what is throwing you off.
Why does my page down key not work on your blog? Using firefox 3 on XP
Boxes boxes boxes! :-)
great article. there have been consistently informative articles coming from css tricks!
Very well-written and extremely informative article, Chris.
Thank you.
I also find myself using the border-trick often when feeling like losing control a bit. I kinda learned that trick myself (didn’t read/see it anywhere) – fun to read that more people do it that way :)
Note that inline “boxes” are not able to have heights or widths.
See example here.
Adding padding to inline elements is touch and go at best as well. I think some versions of IE allow it. If I remember correctly, Firefox will pad left and right but not top and bottom.
Regardless of browser support, though, inline elements are actually not boxes according to the specs. They have no width, no height, no padding, etc. (unless of course you add display:block ;) )
Well… Thanks for clearing that up! Been using firebug for a while and just looked over the box. :)
I use Outline > Outline Block Level Elements in the web developer toolbar all the time.
Yes, the outline technique is better than using a border imho.
here’s a quick snippet to do something equivalent if you don’t have the Web Developer Toolbar.
* { outline: 2px dotted red }
* * { outline: 2px dotted green }
* * * { outline: 2px dotted orange }
* * * * { outline: 2px dotted blue }
* * * * * { outline: 1px solid red }
* * * * * * { outline: 1px solid green }
* * * * * * * { outline: 1px solid orange }
* * * * * * * * { outline: 1px solid blue }
wow! this is super helpful! thanks for the great info and the way you explain it, even a 5 year old could clearly understand it. I will def. point people to this!
nice post, new with CSS and helped me to understand well.
You do a great job man. Thanks for all the good tips.
Great article. Having a very clear understanding of how the box model works takes out a lot of guesswork.
And thanks for explaining the difference between setting no width and 100% width – I never quite grasped that before. It’s weird how it works that way – you’d think it’d be the same thing either way, but it isn’t.
Also, might be a good idea to remind everyone to declare a proper doctype (which you should be doing anyway); otherwise, IE falls back into quirks mode and uses its own (incorrect) box model implementation.
From previous headaches I’ve learnt these things before and I normally set everything with a width but it’s good to know that there different ways to work with things.
I think I should check out this firebug that seems to get mentioned everywhere, I like the functions in the web developer toolbar, and didn’t see the need to check out firebug. But that box model display looks insanely helpful.
nicely said.
Graphical representation helps to understanding Css more easy
This is a great refresher. Very well written. Thank you for the continuous stream of high-quality content!
Thank you for that. Basics, but you can’t build a house without the foundation.
Just found this site thru Stumble.
Great tips. Always looking for different ways to manage page layout.
Look forward to future articles.
Hmm, don’t understand why Denis Onichshenko would even say such a thing: “Kinda surprised you will do a box model tutorial in mid of 2009 …” Please explain that comment, Denis. Do you not realize that there are people picking this stuff up fresh every year? Fundamentals are always relevant (and important to get right)- yes, every year! Check out the other comments from people who have benefited from this “too basic for you” post.
Thanks for sharing, Chris!
Posts like this help people understand the basics often more than a dry tutorial. It’s very valuable. And if you want to design ‘outside the box’, it’s always good to refresh yourself on how that box works.
As for how older browsers might handle that box…brrr,shudder… maybe an idea for another tutorial.. as much as we might want to leave ie6 double margin etc bugs behind, we still gotta deal with that stuff, and the details of the box model and fixing it for older browsers might put many dispirited, potentially awesome designers off…
it’s a cool post, thanks chris
It’s worth noting that when applying a width to your carefully arranged boxes, adding a red border (or any colour) for testing etc does add 2px to the width and height which can be enough to break your layout while testing.
I usually change the background colour temporarily to see what’s going on, that way, your sizing doesn’t change.
Not entirely true. For example you can set a 80% width and a 10% padding and it will fit nicely to 100%. The only problem would be if for some reason you don’t want percents for the padding.
And a big issue is that the border cannot assume a percent measurement. But the ems are also a good choice in my opinion. 0.1em usually fits 1px.
like this:
margin:0.5em auto; border: 0.1em solid #000000; width:80%; padding:5%;
And display:block; because it’s an em element in this case
Another interesting thing to note is that elements with relative position (much like the ones with fixed position) automatically gain higher z-index than the elements with static position that follow. But this can be countered with setting the z-index property to an appropriate value.
well… the script stripped the inline style off the em element, so nevermind
Well explained. There are tons of books and so on but this is really informative and descriptive.
Excellent post. You have bought up some interesting points here. The section about default values has gave me something to think about. Understanding the different ways in which different browsers work with these models is essential for cutting out unnecessary and time consuming hacking, no names mentioned, …IE.
Will certainly be retuning here for more post in the future.
Cool basic stuff for newbie like me :D. Thanks.
Very useful information Chris…Stumbled!
Although I’m not as newbie as I used to, CSS basics and fundamentals are always worth a read to refresh my knowledge.
Also a well populated comments section thrives with unexpectedly helpful tips and tricks.
waw i never get all these boxes work as i wanted to be.
now i know why.
greatly explained.
Thanks for sharing
Thanks, its helping me to understand CSS better, each day a little bit more of it is making sense to me.
Thanks for sharing this :)
nice man thanks for sharing this its really cool description
nice neat simple idea that border one. wish i’d thought of that. would have made my life easier.
Well explained. There are tons of books and so on but this is really informative and descriptive.
Thank you so much for posting! Recently started using CSS stylesheets and your post is a great help :)
This article is such an eye opener for me. Can’t thank you enough for this :)
This is probably a pretty good article. But I am seeking one that deals with how to use these stupid divs. That is, I don’t see them as boxes at all, I am a graphic artist. It is easy to draw round boxes, even circular ones. The idea of the box model is simply defining a space, a space that can be round. The very name, box model, is highly counter productive.
But my problem is that I am trying to define a layout with multiple spaces the same way I used to do it with tables, only better. So if anyone knows where I can find a decent tutorial or discussion on making a simple div layout actually work correctly, please contact me and point me to it.