Grow your CSS skills. Land your dream job.

Box Sizing

Published by Chris Coyier

The "box model" in CSS works like this:

width + padding + border = actual visible/rendered width of box
height + padding + border = actual visible/rendered height of box

It's a little weird, but you get used to it. In IE 6 and earlier, when in "quirks mode," the box model was treated differently.

width = actual visible/rendered width of box
height = actual visible/rendered height of box

The border and padding values moved inward, cutting into the width/height of the box rather than expanding it. Here is a dramatic example of the difference:


It was weird quirk to have to deal with, although the fix was usually as easy as setting a proper DOCTYPE and getting out of quirks mode. More to the point, some people prefered this handling of the box model, claiming it to be more intuitive. It's a valid point. Having the actual visible width of a box not be what you declared in the CSS is a bit mind bending.

The mind bending continues with the modern implementation. Let's say you have a block-level element like a <div> on the page. It's within another parent <div> with a width of 500px. The child div will automatically default to 100% as wide as the parent (500px) without any special CSS. That's how block-level elements work. But now let's say you add 10px of padding all around and a 2px border. The child div will behave like the old quirks-mode box and the padding and border will cut into the box. The visible box will remain 500px in width. Now if you go and explicitly declare the width of that child div to be 100%, the div will actually grow and break out of the parent. The width will start at 500px, but then 10px of padding and 2px of border on either side will leave the visible box at 524px.

If you wanted to ensure the box kissed the edges of the parent, but still use a 100% width declaration, you'd have to set the child divs width to 476px. But now we've run into a problem, and that's fluid width design. Let's say instead of the parent being 500px, you use 72%. Now what do you set the inner divs width to be to make sure it kisses the edges? There is no answer with the current box model. The percentages mixed with pixel values just don't mix well. Setting the inner divs width to 95.2% will work when the parent just happens to be exactly 500px, but if it grows wider, as happens in fluid width design, the div will be too narrow, and if the parent grows narrower, the inner div will be too wide and break out of the parent.

This <div> pseudo markup only takes us so far, because the answer of course is to not use a 100% width declaration. Removing that will solve our problems. However, there is one very important element which really needs this 100% width declaration, and that is the venerable <textarea>.

The <textarea> doesn't care if you make it a block level element, it's width will be determined by the required cols attribute unless you explicitly set it. In a fluid width environment, it is very likely you'll want a textarea that is fluid width as well and your layout may demand that it matches up nicely both left and right. In fact, in the current design of this site, that is the case.


Notice the textarea lines up with the text inputs at either width. The left edge and right edge are also of equal distance from other objects.

To accomplish this, we want to be using 100% width and pixel-based padding and border, and that is the unholy combination that is seemingly impossible. Even the great designer Jon Hicks, known for his excellent fluid width designs, had this to say on the subject in the CSS Wishlist I put together a few years back:

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!

Kapow!

In an epic The DaVinci Code-like plot twist, the answer to our problem is right where we started, the box model itself. If we could force our <textarea> to have padding and border that cut into it's 100% width instead of expanding it, we'd be all set. Wouldn't you know it? There is a way!

textarea { 
  -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
  -moz-box-sizing: border-box;    /* Firefox, other Gecko */
  box-sizing: border-box;         /* Opera/IE 8+ */
}

The box-sizing CSS3 property can do just this. The border-box value (as opposed to the content-box default) makes the final rendered box the declared width, and any border and padding cut inside the box. We can now safely declare our textarea to be of 100% width, including pixel-based padding and border, and accomplish out layout perfectly.

View Demo

Support

Chrome (any): box-sizing
Opera 8.5+: box-sizing
Firefox (any): -moz-box-sizing
Safari 3: -webkit-box-sizing (unprefixed in 5.1+ versions)
IE8+: box-sizing

Min / Max

Box-sizing should and does work with min-width / max-width / min-height / max-height with one exception: Firefox. In even modern Firefox, v11 at the time of this update, min-height and max-height don't respect box-sizing. See this fiddle by Beau Smith to illustrate the problem. This is a known bug since 2005.

Update November 2012: This bug was fixed as of Firefox 17
Reader Iago reports that IE 9, while in IE 8 mode, exhibits the same bug. See research. Reader Adrien reports it's not just IE 9 in IE 8 mode, but IE 8 itself has the same bug.

Notes

Comments

  1. Perfect entry! Thanks!

  2. Nice useful tutorial.

  3. Thomas
    Permalink to comment#

    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.

  4. Permalink to comment#

    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.

  5. Ivan Nikolić
    Permalink to comment#

    Great property to use if you work on layouts for orientation change capable devices like iPhone.

  6. Michael
    Permalink to comment#

    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:

    <div>
      <div style="margin:10px;">
         your content
      </div>
    </div>

    Of course this adds more code, but it is as safe as it can be, across all browsers and even in quirks mode.

    • Permalink to comment#

      But how would you do that with the textarea example?

    • Cao
      Permalink to comment#

      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.

    • ahmad
      Permalink to comment#

      I think wen can use this:

      and

      #parent {width:35%; padding:15%; border:3px; }
      #paddingholder { padding:5%; border:2px;}
      #content { width:100%; height:100px; }

  7. David
    Permalink to comment#

    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.

    • Permalink to comment#

      Same for me, man I also definitely think padding belongs to the inside of the elements it just doesn’t make any sense…

    • Permalink to comment#

      the one thing that IE got right, the spec got wrong… c’est la vie

  8. Jason Evers
    Permalink to comment#

    Ya just blew my mind, yo.

    *boom*

  9. Permalink to comment#

    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.

  10. Permalink to comment#

    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!

  11. Permalink to comment#

    Should’ve posted a link to my tests… I do apologise!

    http://www.devseo.co.uk/examples/facebook-style-overlay-css/

  12. David Garbacz
    Permalink to comment#

    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.

  13. Permalink to comment#

    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.

  14. Permalink to comment#

    You can also use `display: table` to throw items into border-box sizing mode.

    • Permalink to comment#

      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.

  15. Asker
    Permalink to comment#

    you’re not getting any good topics to write..is it right Chris?

  16. Carey
    Permalink to comment#

    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.

  17. Omnipotent
    Permalink to comment#

    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.

    • Permalink to comment#

      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.

  18. ‘border-box’ have to remember this one, excellent tip. LT

  19. Permalink to comment#

    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.

  20. 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.

  21. Permalink to comment#

    about box-sizing and border-box,

    can it also be imbued in JQuery and traditional JS:

    [identifier].style.boxSizing
    and
    [identifier].style.borderBox

    thanks…

  22. clara vargas
    Permalink to comment#

    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!

  23. Nice Article.

  24. Cédric Darné
    Permalink to comment#

    Very usefull article! This will help me a lot. Thanks!

  25. Hey, I really appreciate this legal trick.

  26. Excellent short tut. I was sick and tired of declaring so many different values to fix for padding and borders.

    Thanks!

  27. “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).

  28. Interesting, but not cross-browsing :(

  29. likeuclinux
    Permalink to comment#

    your demo code won’t work for:

    • likeuclinux
      Permalink to comment#

      won’t work for doctype contains:
      “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”

  30. Acaz
    Permalink to comment#

    The best article ever…

  31. Kal
    Permalink to comment#

    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.

  32. yvan
    Permalink to comment#

    Hey there, why in the ” lame try ” dont you just use a padding with 3% and use an outline instead of the border ?

  33. Suraj Shakya
    Permalink to comment#

    Thanx for the great article, really helped me exactly what i was wondering about.

  34. Permalink to comment#

    I would like a “box-sizing: margin-box”, then tricks like this wouldn’t be necessary.

    Any W3C peeps listening?

  35. Gopu
    Permalink to comment#

    .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..

  36. 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.

  37. Franzele
    Permalink to comment#

    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.

  38. Wayne
    Permalink to comment#

    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.

  39. The code throws warnings in Firefox console for (css warnings) box-sizing:border-box; Is that a Firefox bug?

  40. Permalink to comment#

    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.

  41. Permalink to comment#

    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.

  42. Sanjeev
    Permalink to comment#

    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”.

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".