The box-sizing
property can make building CSS layouts easier and a lot more intuitive. It’s such a boon for developers that here at CSS-Tricks we observe International Box-Sizing Awareness Day in February.
But, how is it so helpful and beloved that it deserves its own internet holiday? Time for a little bit of CSS history.
Box Model History
Since the dawn of CSS, the box model has worked like this by default:
width + padding + border = actual visible/rendered width of an element’s box
height + padding + border = actual visible/rendered height of an element’s box
This can be a little counter-intuitive, since the width and height you set for an element both go out the window as soon as you start adding padding and borders to the element.
Back in the old days of web design, early versions of Internet Explorer (<= IE6) handled the box model differently when it was in "quirks mode". The "quirks" box model worked like this: width = actual visible/rendered width of an element's box height = actual visible/rendered height of an element's box The border and padding values were moved inside the element's box, cutting into the width/height of the box rather than expanding it.
Some people preferred this “quirky” interpretation of the box model and considered it more intuitive. It’s a valid point. Having the actual visible width of a box turn out differently from what you declared in the CSS is a bit mind bending.
But, in the days of fixed-width design, it wasn’t particularly complicated to work with the default box model once you understood it. You could do a bit of arithmetic to figure out how many pixels you needed to trim off of an element’s declared width or height to accommodate its padding and border. The problem for present-day developers is that those absolute pixel lengths don’t translate to responsive design, so the same math doesn’t apply anymore.
As responsive design (or, as it was once known, “fluid” or “liquid” layout) started to gain popularity, developers and designers wished for an update to the box model. The great designer Jon Hicks, known for his excellent fluid width designs, had this to say on the subject in the CSS Wishlist we put together in 2008:
I would love a different box model! I find it bizarre that padding and border add the width of an object, and would love to be able to give something like a textarea 100% width and 3px padding without worrying what it’s going to do the layout. Perhaps something like padding-inside as a new selector?
In that vein I also wish I could specify a 100% width for an element, minus a set fixed width. Again, very useful when creating fluid designs with form elements!
box-sizing
Present-Day Those wishes were granted when the box-sizing
property was introduced in CSS3. Though box-sizing
has three possible values (content-box
, padding-box
, and border-box
), the most popular value is border-box
.
Today, the current versions of all browsers use the original “width or height + padding + border = actual width or height” box model. With box-sizing: border-box;
, we can change the box model to what was once the “quirky” way, where an element’s specified width and height aren’t affected by padding or borders. This has proven so useful in responsive design that it’s found its way into reset styles.
At this point you may be asking yourself, “Is it possible that Old IE did something right?” Plenty of people think so.
Demo
This demo shows how border-box
can help make responsive layouts more manageable. The parent div
‘s width is 50%, and it has 3 children with different widths, padding, and margins. Click the border-box
button to get all the children in the right place inside the parent.
See the Pen Box Sizing Layout Demo by CSS-Tricks (@css-tricks) on CodePen.
box-sizing
Reset Methods
Good, Better, and (Probably) Best border-box
Reset
The “Old” The earliest box-sizing: border-box;
reset looked like this:
* {
box-sizing: border-box;
}
This works fairly well, but it leaves out pseudo elements, which can lead to some unexpected results. A revised reset that covers pseudo elements quickly emerged:
Universal Box Sizing
*, *:before, *:after {
box-sizing: border-box;
}
This method selected pseudo elements as well, improving the normalizing effect of border-box
. But, the *
selector makes it difficult for developers to use content-box
or padding-box
elsewhere in the CSS. Which brings us to the current frontrunner for best practice:
Universal Box Sizing with Inheritance
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
This reset gives you more flexibility than its predecessors — you can use content-box
or padding-box
(where supported) at will, without worrying about a universal selector overriding your CSS. We went into more depth on this technique and the reasoning behind it in “Inheriting box-sizing
Probably Slightly Better Best Practice”. One potential gripe with it is that box-sizing
isn’t normally inherited, so it’s specialized behavior, not quite the same as something you’d normally put in a reset.
Vendor Prefixes
Every current browser supports box-sizing: border-box;
unprefixed, so the need for vendor prefixes is fading. But, if you need to support older versions of Safari (< 5.1), Chrome (< 10), and Firefox (< 29), you should include the prefixes -webkit
and -moz
, like this:
html {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
*, *:before, *:after {
-webkit-box-sizing: inherit;
-moz-box-sizing: inherit;
box-sizing: inherit;
}
Known Issues
box-sizing: border-box;
is supported in the current versions of all major browsers. The less-commonly used padding-box
is only supported in Firefox at the moment. There’s more comprehensive information about browser support in our box-sizing
almanac entry.
There are a few issues with older versions of Internet Explorer (8 and older). IE 8 doesn’t recognize border-box
on elements with min/max-width
or min/max-height
(this used to affect Firefox too, but it was fixed in 2012). IE 7 and below do not recognize box-sizing
at all, but there’s a polyfill that can help.
Perfect entry! Thanks!
Nice useful tutorial.
Nice, didn’t know that works in IE8 – so its actually usable ;)
Unlike “decorative” CSS3 properties like text- or box shadow, box-sizing will totally ruin your design if the browser doesn’t get it.
dont say İE8, i hate him
me too. I hate IE versions. Unfortunately in my country people use ie6 until 10 years later.
So true. Thus, make sure you know your audience very well
Fantastic tutorial, the best I have see for this subject
Just to make more sense to can you change the line….
“height + padding + border = actual visible/rendered width of box”
think it should read – rendered “height” of box.
Great property to use if you work on layouts for orientation change capable devices like iPhone.
Hi,
My solution to this: never use padding. You get the same (optical) effect when you set margins for inner elements. By doing that, everything will be calculated and treated correctly.
If you have multiple elements inside and don’t want to set margin for everything, than group them in another nested div and set a margin for this one, so that the parent will get a padding.
Example:
Of course this adds more code, but it is as safe as it can be, across all browsers and even in quirks mode.
But how would you do that with the textarea example?
Interesting take Michael, but, doesn’t that messes backgrounds? paddings allow more background to be shown, while margins cut the backgrounds right out. I guess I could work for some cases where your inner element is 100% content.
I think wen can use this:
and
#parent {width:35%; padding:15%; border:3px; }
#paddingholder { padding:5%; border:2px;}
#content { width:100%; height:100px; }
This is something that has always irked me.
From the beginning of learning css/html I always thought it would be logical that added padding would be put inside the box, not outside. It still frustrates me to this day.
Same for me, man I also definitely think padding belongs to the inside of the elements it just doesn’t make any sense…
the one thing that IE got right, the spec got wrong… c’est la vie
Ya just blew my mind, yo.
*boom*
Great article! I’m from Brazil, I’ve been following your works for a while and I’m always learning new things from you, congratulations.
Oddly enough, I’ve just been working with this myself! In creating a Firefox addon I’m using a nice fluid layout so that my section fit no matter what size browser you have. However, I also wanted a very nice ‘Facebook-style’ border with rgba colours so that they were see-through.
If you set a background-color on the element and apply a border, it won’t be see-through because the border is *technically* on top of the content. Using a mixture of border-box and background-clip I managed to get the desired effect, with ease!
Should’ve posted a link to my tests… I do apologise!
http://www.devseo.co.uk/examples/facebook-style-overlay-css/
I guess I never really thought of it that way. If you think about cellpadding with tables, it worked in that way didn’t it where the padding cut into the cell instead of adding to the outside.
I’ll have to agree with Jason above and say that you definitely blew my mind on this one. Big grin came across my face because of how big of a dork I am and found this to be super intriguing.
Always bother me time and time again when creating a box with a specific box, but after setting up with padding and some borders, the size of the box it completely different. I’ve scratch my head few times , until made some experiment myself that found out the padding+border is the cause of it.
Nevertheless, a wonderful explanation.
You can also use `display: table` to throw items into border-box sizing mode.
LOL, sup AJ? How are things at Egghead? How random.
On topic: If you have to choose one box model, the W3 box model is more versatile than the IE one. It bugs me when people who haven’t even read the spec view the W3 model as inferior simply because it is less intuitive.
Now that we have the alternate box sizing available, we get the best of both worlds. For IE6/7 in standards mode, you could use CSS expressions to bring them in line.
I’m guessing that this property will be extended soon – I can think of other box-sizing methods that, like border-box, would be useful in special situations. A value for instructing a block element to take up all the height that it can (in the same way that a block element takes up all the width it can) could be incredibly useful.
you’re not getting any good topics to write..is it right Chris?
I’ve found that border-box sizing is pretty much required if you want to do a fixed size header and footer with scrolling content inset into the page (with overflow-y: scroll). It seems to be the only way to make the content and all its parents 100% high, with fixed top and bottom padding.
Very nice and useful. it’s awesome that it works in IE 8, and hopefully im IE 9 too.
all this css3 goodness and still not all that practical, finally one that could really help with the design.
The idea of “practical” CSS3 at this point is a little out of the question. Actually – we’re getting there, but if you’re designing a site that has any respectable amount of traffic coming in over a browser that doesn’t support CSS3, you wouldn’t want to make your site dependent upon it.
As an aside, I’m confident IE9 will be quite standards compliant.
‘border-box’ have to remember this one, excellent tip. LT
This is definitely good to know. I struggle with this every time a do a new design. I’ve liked the 3-across style input fields above the actual comment form for awhile now, but I went back to the standard layout for the comment form for the most recent design of my personal site because of this issue. Even though my site isn’t fluid width (yet), the comments have been fluid since they added that cool new reply feature in 2.8 or so. I’ll definitely be looking for this article again shortly.
This is one of the biggest error W3C have ever done, in 1997 more that 95% of browser share was occupied by browsers using box sizing model (quirk model) or browsers which didn’t understand those CSS at all. W3C should change specification at this point to reflect reality (over theory) and add new property: inner-padding.
about box-sizing and border-box,
can it also be imbued in JQuery and traditional JS:
[identifier].style.boxSizing
and
[identifier].style.borderBox
thanks…
When I first checked out this web write-up discussing the Facebook audience claim that’s off by 17,000 times I concluded CSS Trick’s regulars should check
this out! http://hubpages.com/hub/Lies-Damned-Lies-Statistics-ComScores-Facebook-Audience-Claims-Are-Wrong-By-A-Factor-Of-17-000 According to ComScore, the
average Facebook user is online half a second per day! Yeah, sure!
Nice Article.
Very usefull article! This will help me a lot. Thanks!
Hey, I really appreciate this legal trick.
Excellent short tut. I was sick and tired of declaring so many different values to fix for padding and borders.
Thanks!
“But hey, IE 9 is about to drop right, won’t be a problem for much longer,”
Except IE9 won’t run on XP, which, for some users means not just getting a new browser, but a new PC.
IE9 shipping is not a magical bullet for web devs. IE7 will become the new IE6. Then IE8. And let’s face it, a lot of devs will still be dealing with IE6 for years to come (especially those in enterprise land).
IE7 is dying faster than IE6. Even if it does become ‘the new IE6’, it won’t be another ‘IE6’.
People are slowly upgrading PC’s and that is steadily killing older versions of IE.
I don’t think anyone would buy a new PC to specifically run a certain browser, but if most of the PC’s running Vista and Win7 did upgrade to IE9, we could then relax knowing that an extra 15%+ would be able to make use of CSS3. Obviously this won’t happen over night, but the IE9 usage share will steadily grow per month.
IE9 might not be a magical bullet, but I think it at least qualifies as a poisoned-dagger.
That’s pretty interesting. I bet it’s true… Do you have any data you’ve seen to support that?
http://marketshare.hitslink.com/browser-market-share.aspx?qprid=3
http://www.w3schools.com/browsers/browsers_explorer.asp
http://www.w3counter.com/trends
http://www.xmarks.com/topic/browser_statistics
there are no “world wide” statistics, but those mentioned above show some trends
Very cool.
Seems to me they indicate that they are falling about equally fast, but IE 7 has a larger slice still. So if they stay at and even falling rate, IE 7 will always have a higher percentage. That would be pretty crazy if IE 6 ever got higher than IE 7 again.
Interesting, but not cross-browsing :(
your demo code won’t work for:
won’t work for doctype contains:
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”
The best article ever…
This has always been my biggest gripe with doing CSS layouts — well, aside from catering to all Internet Explorer’s quirks of course. Ironic that IE actually used to do it the border-box way.
Thanks for the article. I’m going to introduce this into all my sites from now on — screw IE 7. Did I say that? I mean, we’ll find a dodgy workaround for IE in it’s own stylesheet or something.
Hey there, why in the ” lame try ” dont you just use a padding with 3% and use an outline instead of the border ?
Thanx for the great article, really helped me exactly what i was wondering about.
I would like a “box-sizing: margin-box”, then tricks like this wouldn’t be necessary.
Any W3C peeps listening?
.navigation_main ul li a {
background-color: #FFFFFF;
border-radius: 5px 5px 0 0;
color: #003366;
font-size: 13px;
margin: 1.2px;
padding: 5px;
}
in this code padding and margin is working with only chrome and firefox, i need to work this code over IE 9…but alignmnt pblm is arising, help me to fix this issue..
http://jsfiddle.net/nsrau/ptt58/
SubtractJS offers a different take on the box model.
SubtractJS can fill an edge of the screen or of any box that is positioned relative or absolute. It can also fill the entire box.
It sizes the contents so that the contents plus the padding, border, and margin exactly fill the containing box.
It is great for creating sticky headers, footers, or edges, as well as for precisely filling an absolute or relatively positioned element.
Just a little addition.
Be warned that pseudo-elements ::after and ::before don’t seem to adhere to the rule in the general selector
* {
box-sizing: border-box;
}
so the best way to make them look as you want is to repeat the box-sizing rule in the ::after/before declaration itself.
So, correct me if I’m wrong but I think what I’m hearing is that you prefer the Microsoft box model and you wish that’s the way all browser had always done it by default.
I agree.
The code throws warnings in Firefox console for (css warnings)
box-sizing:border-box;
Is that a Firefox bug?Hi Chris,
What solution do you recommend for IE7 – Do you know of a light PolyFill?
Cheers,
Dan
Personally, I would not even bother trying if I had to support IE 7. The old way is harder to think about it, but not THAT much harder. Penalizing older browsers with a polyfill (more code) doesn’t feel right.
Thanks for the quick response Chris.
I’m so used to using border-box and not even thinking about ie7 but the client I’m currently working for supports it. I considered a polyfill but you’re right seems a bit OTT.
Nice share as always, thanks Chris.
For IE box-sizing property depends on IE Document Mode, it works on “IE8 Standards mode” & higher. So it will work in IE8 browser also if document mode is “IE8 Standards mode”.