It’s February 1st today, which I’ve decided to declare International box-sizing Awareness Day. In honor of, you guessed it, the most humble and undersung, yet awesome and useful CSS property: box-sizing
.
The date corresponds to Paul Irish’s post where he introduced the concept of using it on every single element on the page. We’ve talked about it around here a few times as well.
Here it is, in all it’s glory:
*, *:before, *:after {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
box-sizing
property doesn’t normally cascade, and you would be forcing it to, but it makes it a lot easier to override at a component level.The default value for box-sizing
is content-box
, which is what we are overriding here. There is also a padding-box value but… kinda useless if you ask me. We’ll get to what this means shortly.
Notice we’re using the *
selector to select all elements, as well as making pseudo elements use the same model, which otherwise wouldn’t be selected by the *
selector alone.
Here’s the browser support situation. “-” = “this version and down”. “+” = “this version and up”.
*, *:before, *:after {
/* Chrome 9-, Safari 5-, iOS 4.2-, Android 3-, Blackberry 7- */
-webkit-box-sizing: border-box;
/* Firefox (desktop or Android) 28- */
-moz-box-sizing: border-box;
/* Firefox 29+, IE 8+, Chrome 10+, Safari 5.1+, Opera 9.5+, iOS 5+, Opera Mini Anything, Blackberry 10+, Android 4+ */
box-sizing: border-box;
}
In the fairly near future we won’t need any prefixes at all for it, but I like to just leave that kind of thing to Autoprefixer.
Why all the HOO-RAH?!
It makes working with boxes so super duper much nicer.
When you set the width of an element, that’s the width that it is. If you set the width to 25%, it will take up 1/4 of the horizontal space available in its parent element. That’s it.
That’s not always the case. With the default box-sizing, as soon as an element has either padding or border applied, the actual rendered width is wider than the width you set.
Actual width = width + border-left + border-right + padding-left + padding-right
The math is bad enough, but when combined with percentages (or any mixed units, really) the result is impossible to do in your head and, more importantly, ends up being some useless number that you can’t do anything with.
You might think of it this way: with box-sizing: border-box
the padding and border press their way inside the box rather than expand the box. The result is a box the exact width you set it to be and can count on.
Columns is a particularly useful case, but this comes in useful all the time and becomes one of those things that just makes CSS development better.
Remember to read Paul’s original post which covers some more ground like performance (don’t worry about it), jQuery (don’t worry about it), and third-party content (easy to fix).
Happy International box-sizing Awareness Day! Maybe next year we can get organized about it and all wear groovy square sunglasses or something.
I love this. I have been using it for a while now and it is one of my favourite parts of CSS. Create a little sass mixin and you don’t even have to remember all the prefixes.
Then
@include box-sizing
;This is more useful if you don’t need to apply it to EVERYTHING that is included on the page the stylesheet is linked to.
That totally works! Just a few notes…
Or just use a pre-processor that does the prefixing for you, helps keep your code clean! I recommend Prepros.
@chris I had no idea that Compaass had a mixin for it. Probably should spend some time looking into what they provide. I have only used the transition and transform mixins.
I also need to look into the @extend property more, it seems awesome!
I am having some issues getting Autoprefixer working with CodeKit. I’ll keep playing with it.
Thanks Chris! :)
I’m with Chris on this one. The universal selector is very apropos for box-sizing, especially with responsive design making layouts all percentish and what not.
what use will a mixin be if it doesn’t have to be repeated. I find mixins most useful if it’s a property I need to use severally and requires vendor prefixes. The wildcard * can just handle it all as shown earlier in the article
*,*:before,*:after{box-sizing: border-box;}
Border-box is nice but content-box is still useful. Here is a useful case: You want an element to be a fluid container that is centered and doesn’t grow more than 1000px and still has padding if the browser window is smaller than 1000px.
Not sure I totally follow. Simple demo. How does box-sizing affect your ability to do that?
It’s just nice to be able to switch between the two. In my example, padding is acting like a second margin since I’m using margin to center my container.
In my case I want a container to put elements in that doesn’t grow larger than exactly 1000px. Since I want to use a percentage gap on the sides it is more difficult to use border-box so that my inside area doesn’t grow larger than 1000px.
Here is an example of doing the same thing as the content-box example above only using border-box.
I had to use calc to add the padding to the max-width. Now measure the P element inside the DIV when you stretch your browser wider than 1048px, it is exactly 1000px.
When I first started to explore HTML and CSS ten years ago I was a child (~12yo) and used to try with IE on Windows ME (yeah, you’re laughing, I know). :D
Then I discovered “normal” CSS stuff (with Firefox) and started to learn the true box model. The only thing I’ve always missed about IE was it’s wrong interpretation of the model (I mean, IE6 used to do everything as per
border-box
). Whenborder-box
came out, I was so glad my idea of"width: 100%"
was available again. :)Just to be clear, that’s a slight misconception. PRE IE 6 was like that, but IE 6 was the normal box model except when in quirks mode, which was triggered by stuff like an incorrect or missing DOCTYPE.
This WikiPedia article explains it pretty well.
Traditionally it’s been advised to use a more robust reset like Eric Meyer’s for performance reasons.
If you’re already using the universal selector to apply
box-sizing
, is there any reason to not use that same declaration for your reset?That’s my go-to reset.
you should switch to normalize. universal resets are so oldschool.
Nothing ‘old-school’ about it. Different concept with different goals. Personal preference.
Personal preference, yes. However, “traditionally” universal resets are indeed “old school.” There is nothing wrong with “old school” approaches as long as they still work, but you’ll likely see more use of normalize in the future as normalize is a more finely-tuned approach which doesn’t require a lot of extra manual effort.
In the end, it could be argued that normalize is a more DRY approach. Of course, normalize is only a guideline. Each person can have their own “normalize” routine and preprocessors are doing a good job lately of allowing this kind of customization.
The standard box model is one of the worst mistakes that the W3C has ever made.
Microsoft was, once in a while, correct thinking that designers wanted to size the container, not the content.
As a result, IE6-7 doesn’t even support border-box sizing (natively – there are workarounds with CSS expressions) unless in quirks mode, that nobody ever should use. Ever.
Here’s hoping next year will be International FlexBox Awareness Day.
I wish I had even known about resizing this way. I have to do so many nested elements to achieve this – going to really clean up some of my code.
Being a baby-faced web designer has its perks; since I starting learning CSS a year ago, I’ve never had to use the older
box-sizing
value due to solid browser support across the board. It made learning float-based layout much, much easier and fought off loads of potential frustration.Bootstrap 3 and Foundation 5 both use
box-sizing: border-box
on every element by default nowadays. Pretty much cements it as a best practice in my mind.i wonder, if mozilla is ever going to drop the prefix. there have been discussions about dropping it since 2004(!): https://bugzilla.mozilla.org/show_bug.cgi?id=243412
They have, will be stable in 29 as I understand it.
Awesome post! I’ve read several blog posts and read about
box-sizing:border-box
but I actually created a CodePen this evening after reading this article. It’s pretty freakin’ sweet!I remember when I was first learning html/css about a few years ago, I had no idea about border-box or calc. To make a box to fill a certain percentage of the page AND have a border was close to impossible, you either had to do really weird things with the html/css, not use borders, or use JavaScript, which I wasn’t very good at at the time. I am so glad this property exists, it’s so much more intuitive.
After I getting learnt with box-sizing
border-box
.But, silly argument I got from old designers (who still followtable tr td
is it is very hard to size the layout seperately to IE-6/6- versions. So, it is better to go for!
content-box
for all content rather than resets.!“—“But, i thought its right for the guys to go with
content-box
who copies PSD web template as it is with photoshop slicers!If you’re designing for IE 5 and down, this is the least of your worries.
I happened upon the awesome benefit of this code snippet just days before Paul published his original post and have been using it ever since.
As MaxArt mentions above this CSS is not supported by IE6 and IE7 which probably isn’t a problem for most people.
I had to support IE7 on a project when I was still using LESS. So I wrote up this simple little mixin on CodePen to create a fallback for IE6-7 by using a conditional class added to the HTML.
I’m now using Sass, and have been mid 2012 so I decided to recreate that mixin using Sass which I’ve also got on CodePen.
I also wrote up how it works on my blog late last year.
That mixin is also included in my little Sass library – Sassifaction
Indeed a BIG HOORAY! All that fuzzing with percentages all the time is now history! Thanks!!!
Star (
*
) before pseudoelement name is unneeded.*, :before, :after
is sufficient.By the way, at the time of Paul’s writing,
box-sizing
could not yet actually be used globally since Firefox had a bug resulting in incorrect calculation ofmin-height
/max-height
when used in conjunction withbox-sizing: border-box
. Since then, the bug has been fixed in Firefox 17 released on November 2012, and now defaultbox-sizing: border-box
can indeed be used.True on the selector naming! The star essentially stands for “any element” which is what not saying anything stands for. Just like
*.class
is the same as.class
, even in terms of specificity since*
has none. (test case).Nice reminder of that min- max- saga too. I’m not sure it would have made it unusable, but it was certainly something that needed attention.
Until recently I only really used it to make responsive forms behave properly and I was a bit shocked when someone at work suggested using it globally. Now it’s included as part of my reset in every project.
Beautiful! I never knew! This is going to make life so much easier. Thanks Chris!
I’m really new to the whole ‘web development’ thing, and to be honest this whole thing seems so much harder than it needs to be; this little trick has definitely made my web development career so much easier. Thank you so much.
I used JavaScript in some projects to fix these kinds of problems and nested divs inside divs to override content going outside bounds. Thanks for this info! It’s very useful for me! ;)
I try to make every day International Box-Sizing Day. I can’t sing its praises enough. Every time I’m given a layout to fix from one of the designers at work, adding it is the first fix I make. Viola, stuff aligns.
Why am I not using box-sizing?!
I personally hate resets, but this is one snippet of code I apply to everything first. And since I have started using it, I have had a fraction of the cross-browser issues. It has probably saved me hundreds of hours in trouble shooting IE vs everyone else.
Once again, all I have to do is casually come to this site and I learn something super useful. Thanks Chris (and originally Paul)!
I’m surprised folks haven’t heard of this beforeā¦ that alone is blowing my mind.
Agreed! Good reason for someone with the wide-spanning audience Chris has to continue to blog about these things. Sometimes we’re focusing so much on the future and the now that we forget how challenging it can be to keep up. Sometimes getting sucked into a project for 6 months where you have no time to keep up means you miss important things like this.
Am I the only one who prefers leaving the browser default content-box and only apply border-box when needed? Then I don’t need to set back to content-box in my CSS whenever that makes sense to use. Both box models make sense in certain situations, and on most elements on a page they make no difference.
Anyway it just feels cleaner to me only to apply border-box where needed, no big deal if people prefer otherwise.
I know where you’re coming from, but once you switch to a universal selector, you find all kinds of places where it has come in handy. Especially true with anything responsive.
Since there are very few side effects, it’s one less thing to calculate. It just works.
Border Box is my best friend in CSS land.
I still die a little inside every time I realize “Gee, the IE6 honestly had it right with the box model.”
Regardless, it’s the truth.
why? at the time ie6 was the best and most modern browser by a long shot.
It wasn’t IE6, it was IE5.5 and earlier. IE6 only did this in quirks mode (which I believe was by design, to be backwards compatible with the IE5.5 box model). IE6 rendered the box model just fine, aside from some (admittedly major) float/margin bugs and other layout issues.
Nothing was wrong with IE6 when it came out. It was far ahead of the rest of the browsers when it came out. It’s just that they stopped innovating until the monopoly was threatened.
This is going to make my life so much easier. Thanks Chris!
This snippet is in my default css without a doubt. Finally someone is raising awareness for something I actually care about! (tongue in cheek, perhaps, but still)
Thank you, I had no idea this even existed….thank you.
Thanks Chris for sharing this important article. I have faced this issue few weeks ago when one of my client needs 300px width fixed box and after i have applied border and padding to that box, i noticed that the width of box in exceeding from 300px. Further inspecting it in Firebug layout i calculate width with formula you mentioned above its 305px. Now its good to use box-sizing rather then calculating widths. Thanks
Someone should notify CSSLint, I dont use the program due to it hating the use of the global element to style anything, and I am not going to go and load up a reset file for each known possibly unknown HTML element. I really enjoy linting tools I just wish amazing fixes like this one made it into that one.
I love box-sizing.
I found I would always add it to so many elements, then found out about the select or elements method ( * )
I will admit, it did cause me a headache when one element just wasn’t working properly, it was because of the box-sizing. But once I understood what was the cause, it was an easy fix ( Might have been on the container etc ).
So I prefer selecting all, and making the one modification to fix a little issue.
I’ve wondered if I should do this – now I will!
Excuse my ignorance but I can’t work out why you need the before and after pseudo elements?
Because the global selector does not select them.
Oh yeah thanks!
Whoa!!! I av been seeing this for a while but I neva bothered to find out what it means. now that I know what it does I will use it all the time. Thanks
Sass + Compass
I use box-sizing like I use deodorant.
A project I’m working used the global and pseudo-selectors approach. One of our significant layout elements completely failed to render properly in Firefox, of all browsers. It took me ages to work out the fix (simply specifying width: 100%: which you’d think was unnecessary). For far too long it looked like a rendering problem caused by the global box-sizing: border-box;.
I think I’m alone in disliking the global approach. Sorry Chris (and sorry Paul Irish who’s got a similar posting). I appreciate the frustration the content-box model causes (I’ve suffered that pain too), but i feel the problems it causes only arise on a handful of containers per page. To me this doesn’t justify using a global selector that radically changes the layout model of the entire page.
I’m finding that this doesn’t work for Button element.