为什么CSS的宽度和高度属性不会自动调整填充(padding)的大小?

10

首先,为了铺垫一下,让我们来简单介绍一下:

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;
}

这将在所有现代浏览器中产生类似于以下内容的效果:

CSS interior width test showing the inner box exceeding the container

现在我知道这是符合标准的行为(就像我之前知道的那样,但在这篇文章中得到了确认),我也知道如果我将这段代码包含在内部CSS声明中:
box-sizing:border-box;
-moz-box-sizing:border-box;
-webkit-box-sizing:border-box

...它将采用"border-box"模型并获得我认为更直观的行为,但我发现自己试图逻辑上证明这是为什么会是这样,但我无法做到。

对我来说,在表面上看,内部框应始终填满容器的100%宽度,而不管内部框的填充或边框如何。当我尝试将带有边框或类似4px内部填充的文本区域的宽度设置为100%时,我经常遇到这个问题...文本区域总是会溢出容器。

因此,我的问题是...在设置元素的宽度时忽略其边框和填充的默认行为背后的逻辑是什么?


在所有现代浏览器中,除了IE 8之外,它会产生一个基本上是红色方块的结果。 - NotMe
2
IE是穴居人的浏览器。 - JCOC611
@JCOC611:我曾经也这样认为。但我注意到所有的浏览器都有时会出现严重问题。至少使用严格的doctype我可以让IE8、Chrome和Firefox至少以相同的方式显示所有内容。现在,如果Firefox能够修复他们的打印问题,Chrome能够可靠地加载页面,那么我就会很高兴地远离IE。 - NotMe
当然,所有的浏览器都有它们的缺陷。IE 并不算太糟糕,问题在于它不遵循默认设置,所以我们必须为 IE 编写一段代码,为其他“正常”的浏览器编写另一段代码。 - JCOC611
@JCOC611:如果你没有一个严格的文档类型声明,那么他们的“怪异”模式绝对与其他人的怪异模式不同。然而,你必须承认,即使Chrome和Firefox在怪异模式下显示文档,它们也会以不同的方式显示,这意味着(忽略IE),你仍然需要为它们编写不同的代码。 - NotMe
5个回答

37

CSS 采用盒模型的原因如下:

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

CSS是一种文档样式语言,最初是为研究论文和其他正式文档设计的,而不是为了制作漂亮的图形。因此,模型围绕内容而不是容器。

CSS不是编程语言,而是样式语言。它并没有明确告诉文档应该如何显示,而是建议浏览器遵循某些指导方针。所有这些都可以被实际编程语言JavaScript覆盖和修改。

回到内容模型的概念,考虑以下CSS:

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

height未被指定,因为内容定义高度。它可能长,也可能短,但是不确定并且不重要。 width设置为400px,因为这就是内容(文本)应该有的宽度。

padding只是一种扩展背景颜色的方法,以便文本可以远离边缘而清晰可读,就像在纸张上书写/打印时留下空间一样。

border是一种围绕某些内容以区别于其他背景或在各个元素之间提供边框的方法。

margin告诉段落在边缘之间留出一些空间,通过边距折叠,每个组都将保持均匀的间距,而无需为第一个或最后一个元素指定不同的边距。

为了保持流动性,width默认为auto,这意味着宽度尽可能宽:

  1. 不会不合理地压缩内容
  2. 不会使填充超出其容器

当然,在极端情况下,填充将超出其容器,因为内容可能会被压缩。 一切都关乎内容。


感谢您的详细回复!如果我可以将文本区域设置为 display:block 并自动填充其容器的宽度,那肯定会很好,但不幸的是它似乎没有这种行为。我想知道,既然 CSS 的使用现在(相当大的程度上)用于网页的视觉设计,他们是否会在未来重新审查这个规范。 - treeface
文本区域(textareas)与其他元素略有不同,它们应该具有指定的行数和列数。CSS3 使其能够被调整大小以更好地适应用户需求。 - zzzzBov
3
我没时间在之前详细解释文本区域,但是让它们“动态”的诀窍是将它们放在 div 中。把文本区域的边距、边框和内边距都设置为 0,并将宽度和高度设为 100%。然后,给 div 添加一些内边距和边框,使其看起来像是文本区域。 - zzzzBov

6
您可能需要查看w3c的以下内容:http://www.w3.org/TR/CSS21/box.html 盒模型的高度和宽度与元素的内容区域相关。填充在该区域之外,这就是为什么您看到内部框超出了外部框。
在填充后,如果有边框,则为边框。然后边距应用于边框之外。这意味着元素的实际宽度定义为:宽度+填充+边框+边距。
实际上,您的CSS定义了内部框具有300px x 150px的内容区域,再加上5px的填充,因此得到一个310px x 160px的框。
个人而言,我同意宽度应该包括填充。但是,规范并不是这样说的。
顺便提一下,怪异模式确实将填充(和边框)包含在实际宽度中。不幸的是,怪异模式会破坏许多其他事情,通常最好只处理w3c规范的模型,而不是尝试创建修复其他“怪异”问题所需的所有CSS。
另一个站点(赞同您和我的站点)在此处:http://www.quirksmode.org/css/box.html 他们提到CSS3包括box-sizing声明(正如您发现的那样),这应该为您提供更多控制使用哪个框模型的选项。看起来几乎每个人(IE8、Chrome、Firefox)都支持这个,这是好事。

1
谢谢提供链接!那个quirksmode.org的文章正是我在寻找的。很高兴知道我不是唯一觉得内容模型有些反直觉的人。 - treeface

1
尽管这可能不是 CSS 盒模型的原始意图,但另一个好处是如果您想要具有偏移背景图像(例如,图像在文本的左侧或右侧),则可以指定填充为背景图像的宽度,以使文本不重叠,并仍然为文本本身指定宽度。例如:
.imageDiv{
width:200px;
background-image:url('someimage.png') /*this image is 50 px wide*/
background-repeat:no-repeat;
padding-left:50px;
}

现在,任何输入到具有类名imageDiv的div中的文本都将显示图像,该图像与文本重叠并位于其左侧。


1
回答你的问题,我认为逻辑在于这一切都与内容有关;如果你指定了尺寸,那么内容就会按照这些尺寸进行展示。
但最终这只是一个选择,我们必须与之共同努力。

1
看一下下面的图片: enter image description here

现在考虑当您将宽度和高度的值设置为100%时会发生什么-这张图片的填充和边框是否应该神奇地消失?作为开发人员,您如何以合理的方式处理它?
“宽度和高度是宽度和高度,边框和填充是其他东西” - 对我来说,没有比这更合乎逻辑的了。
另一方面,
“宽度和高度是宽度和高度,但有时当您选择将它们设置为100%时,它们也是边框和填充” - 对我来说这毫无意义。
但是,一个人的逻辑可能是另一个人的无稽之谈,所以我不知道这是否会对您有所帮助;)

当然,在这个层面上,我确实理解它为什么会这样做。事实上,我以前见过并使用过这个框,但在我的大多数用例中,将元素的宽度设置为100%(或150px或其他)并将其填充设置为5px更有意义,并将它们视为不同的概念。现在,视觉开发网页通常意味着将border + padding + width相加,这不是很直观。这将使我能够说“好的,我想让它宽450像素”,然后再说“嗯...现在我想要5像素的填充”,而不会使总宽度跳到460像素。 - treeface
@treeface:这是因为对于你来说,宽度是在盒子的外部测量的,而对于盒子模型来说,它是在内部测量的。这不是关于逻辑,而是关于定义——你会如何测量房子的平方米?从外面还是里面?对我来说,里面更有意义,但对于一些人来说,外面可能更合适……我认为这归结于你的心态 :) - Martin Jespersen
确实……这自然是一个观点问题。但显然我的观点是正确的;-) - treeface

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接