10

So first a bit of meat to set the scene:

HTML

<div id="container">
    <div id="inner">test</div>
</div>

CSS

#container {
    width:300px;
    height:150px;
    background-color:#d7ebff;
}

#inner {
    width:100%;
    height:100%;
    padding:5px;
    background-color:#4c0015;
    opacity:.3;
}

This will produce something that looks like this in all modern browsers:

CSS interior width test showing the inner box exceeding the container

Now I know this is the standards-compliant behavior (as I knew before, but reconfirmed in this post, and I also know that if I include this code in the inner CSS declaration:

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

...it will adopt the "border-box" model and get the behavior that seems more intuitive to me, but I just found myself trying to logically justify the reasoning behind why this is the way it is and I was unable to do it.

It seems (on the surface of things) more logical to me for the inner box to always fill the container to exactly 100% of the container's width, regardless of the padding or border of the inner box. I run into this problem all the time when I'm trying to set the width of a textarea to 100% that has a border or something like a 4px interior padding...the textarea will always overflow the container.

So my question is...what is the logic behind setting the default behavior to ignore the border and padding of an element when setting its width?

Community
  • 1
  • 1
treeface
  • 13,270
  • 4
  • 51
  • 57
  • "in all modern browsers" -- except IE 8 which produces a basically red square. – NotMe Feb 04 '11 at 22:38
  • 2
    IE is the caveman's explorer. – JCOC611 Feb 04 '11 at 22:39
  • @JCOC611: I used to think that as well. However, I've noticed that all of the browsers have sometimes cripling issues. At least with a strict doctype I can at least get IE8, Chrome, and Firefox to at least display everything identically. Now, if Firefox would fix their printing items and Chrome could reliably just load pages then I'd happily get away from IE. – NotMe Feb 04 '11 at 22:51
  • Of course, all browsers have their flaws. IE isn't that bad, the thing is that it doesn't follow the defaults so one has to write one code for IE and another code for the other "normal" browsers. – JCOC611 Feb 04 '11 at 22:53
  • @JCOC611: If you don't have a strict doctype, then yes their "quirks" mode is absolutely different from everyone elses quirks. However, you have to agree that even when Chrome and Firefox display a document in quirks mode it does so differently from each other, which means (ignoring IE) you would still have to write different code for them as well. – NotMe Feb 04 '11 at 22:56

5 Answers5

37

The reason CSS uses the box model as:

+---------------------
|       Margin
| +-------------------
| |     Border
| | +-----------------
| | |   Padding
| | | +---------------
| | | | Width x Height

Is because CSS is a document styling language. It was (originally) designed with research papers and other formal documents in mind, not as a way to make pretty graphics. As such, the model revolves around the contents, not the container.

CSS isn't a programming language, it's a styling language. It doesn't explicitly tell the document how it should be displayed, it suggests some guidelines the browser should follow. All of these can be overwritten and modified by an actual programming language: JavaScript.

Going back to the content-model idea, consider the following CSS:

p
{
  background-color: #EEE;
  border: 1px solid #CCC;
  color: #000;
  margin: 10px;
  padding: 9px;
  width: 400px;
}

height isn't specified, because the content defines the height, it may be long, it may be short, but it's unknown, and unimportant. The width is set to 400px because that's how wide the content (text) should be.

The padding is just a means of extending the background color so that the text can be nicely legible away from the edges, just like how you leave space when writing/printing on a sheet of paper.

The border is a means of surrounding some content to differentiate it from the other backgrounds, or to provide a border (go figure) between various elements.

The margin tells the paragraph to leave some space between edges, and with margin-collapsing, each group will remain evenly spaced without having to specify a different margin for the first or last element.

To maintain fluidity, width defaults to auto, which means the width will be as wide as possible:

  1. without squishing the content unreasonably
  2. without the padding extending beyond its container

Of course, in edge cases, the padding will extend beyond its container because the content might get squished. It's all about the content.

zzzzBov
  • 174,988
  • 54
  • 320
  • 367
  • Thank you for this lengthy reply! It would certainly be nice if I could set the textarea to `display:block` and have it auto-fill the width of its container, but it sadly doesn't seem to have this behavior. I wonder if, since the use of CSS is now (by quite a sizable margin) used for the visual design of web pages, they will revisit this spec in the future. – treeface Feb 04 '11 at 23:12
  • textareas are a bit different, they are supposed to have a specified number of rows and columns. CSS3 gives them the ability to be resized to suit the user better. – zzzzBov Feb 05 '11 at 01:59
  • 3
    I didn't have time to expand on textareas before, but the trick to getting them "dynamic" is to put them in a div. make the textarea margin, border, padding all equal 0, and have width and height be 100%. Then add a bit of padding and a border to the div to make it *look* like it's the textarea. – zzzzBov Feb 05 '11 at 05:00
6

You might want to review the following at w3c: http://www.w3.org/TR/CSS21/box.html

The box model is such that the height and width pertain to the content area of the element. Padding is outside of that area which is why you see the inner box overflowing the outer one.

After padding comes the border, if any. Then Margin applies outside of the border. This means the elements actual width is defined as: Width + Padding + Border + Margin.

In effect, the css you have defines the inner box to have a 300px by 150px content area plus an additional 5px of padding beyond that which yields a box that is 310px by 160px.

Personally, I agree that the Width should include the padding. However, that isn't what the spec says.

As a side note, quirks mode does include the padding (and border) in the actual width. Unfortunately, quirks mode screws up so many other things that it's usually better to just deal with the w3c spec'd model than try and create all the css necessary to fix the other "quirky" things.

Another site (who agrees with you and I) is here: http://www.quirksmode.org/css/box.html

They mention that CSS3 includes the box-sizing declaration (as you've found) which is supposed to give you more control over which box model to use. It looks like just about everyone (IE8, chrome, Firefox) supports that which is good.

NotMe
  • 87,343
  • 27
  • 171
  • 245
  • 1
    Thanks for the links! That quirksmode.org entry is exactly the sort of thing I was looking for. I'm glad that I'm not alone in thinking that the content model is a bit counterintuitive. – treeface Feb 04 '11 at 23:19
1

To answer your question, I think the logic is that it is all about the content; if you specify dimensions, these are the dimensions that the content is going to get.

But in the end it is just a choice that was made and that´s what we have to work with.

jeroen
  • 91,079
  • 21
  • 114
  • 132
1

Look at the following picture: enter image description here

Now consider what happens when you set the values width and height to 100% - should the padding and border just magically disappear from this picture? How would you as a developer ever handle that in a reasonable way?

width and height is width and height, border and padding is something else - to me it does't get anymore logical than that.

On the other hand

width and height is width and a height, but sometimes when you choose to set them to 100% they are also border and padding - now that would make no sense to me.

But then, one mans logic can be another mans nonsense, so i don't know if this will help you ;)

Martin Jespersen
  • 25,743
  • 8
  • 56
  • 68
  • Sure, on this level I definitely understand why it does that. Indeed, I've seen and used this box many times in the past, but in most of my use cases, it makes more sense to set the width of an element to 100% (or 150px or whatever) and set its padding to 5px and have them be considered separate concepts. As it is now, visually developing a webpage usually means summing the `border + padding + width`, which is not very intuitive. This would allow me to say "OK, I want it to be 450px wide" and later say "hm...now I want 5px padding" and not have the total width jump up to 460px. – treeface Feb 04 '11 at 23:16
  • @treeface: that is because to you the width is measured on the outside of the box, where as to the box model it is measured on the inside. It is not really about logic, but about definition - how would you measure the square meters of a house? on the outside or inside? to me, inside makes sense, but to some outside might fit better... i think it comes down to your state of mind :) – Martin Jespersen Feb 04 '11 at 23:24
  • Indeed...naturally it is a matter of opinion. But clearly my opinion is correct ;-) – treeface Feb 04 '11 at 23:51
1

Although this may not have been an original intention of the CSS box model, another benefit is if you want something with an offset background image (e.g. the image is to the left or right of the text). Then you could specify the padding to be the width of the background image so that the text does not overlap it, and still specify a width for the text itself. For example:

.imageDiv{
width:200px;
background-image:url('someimage.png') /*this image is 50 px wide*/
background-repeat:no-repeat;
padding-left:50px;
}

Now any text entered into a div with the class imageDiv will show the image to the left of the text with any overlap.

Zak
  • 2,688
  • 4
  • 29
  • 45