TL;博士:
边距用于将元素从包装器中移入,而不是向外扩展包装器。
长解释:
此行为与在文档中的任何位置指定width
除了水平之外的 a一致。margin
要分解它,请考虑以下片段,其中我指定了一个没有overflow
属性的包装器,并且margin
不扩展包装器元素。
body {
padding: 20px;
}
.outer {
width: 400px;
border: 1px solid black;
}
.inner {
width: 400px;
height: 40px;
margin: 0 20px;
background: grey;
}
<div class="outer">
<div class="inner">
</div>
</div>
如您所见,margin
并没有导致包装器的大小扩大,元素只是继续溢出。此行为记录在 CSS 2.1 规范中的视觉格式化模型详细信息下。
在其他属性的使用值中必须保持以下约束:
'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = 包含块的宽度
[...]
如果以上所有的计算值都不是“auto”,则这些值被称为“过度约束”,并且使用的值之一必须与其计算值不同。如果包含块的'direction'属性的值为'ltr',则忽略'margin-right'的指定值并计算该值以使等式成立。如果 'direction' 的值是 'rtl',这会发生在 'margin-left' 上。
这段摘录非常密集,所以简单来说,让我们忽略 和 的宽度border
,padding
两者都是0
,留下width
,margin-left
和margin-right
。
现在,由于 and 有一个固定的andwidth
值,因此这些值是“过度约束的”。现在在我们的示例中,由于默认方向是方向,因此强制进行补偿。margin-left
margin-right
ltr
margin-right
要查看方向的效果,让我们尝试向dir="rtl"
包装元素添加一个属性。
body {
padding: 20px;
}
.outer {
width: 400px;
border: 1px solid black;
}
.inner {
width: 400px;
height: 40px;
margin: 0 20px;
background: grey;
}
<div class="outer" dir="rtl">
<div class="inner">
</div>
</div>
现在元素溢出到左边。让我们看看这个dir="rtl"
属性是否对您的overflow: scroll
示例具有相同的效果。
#outer {
border: 1px solid #00F;
width: 200px;
height: 100px;
overflow: scroll;
}
#inner {
border: 1px solid #F0F;
margin: 25px;
width: 400px;
height: 200px;
}
<div id="outer" dir="rtl">
<div id="inner">
</div>
</div>
是的,确实如此。现在左边缺少边距,而不是右边。
但为什么不overflow: scroll
包括边距?
主要是因为规范没有说应该。让我们看一下该overflow
属性的 CSS 2 规范。
每当发生溢出时,'overflow' 属性指定一个框是否被剪裁到其填充边缘,如果是,是否提供滚动机制来访问任何剪裁出来的内容。
看看它是如何具体说“剪掉的内容”的。关于“内容”的解释,让我们参考 CSS 2 规范中的下图。
正如我们所见, 与margin
是分开的content
。然而,此时值得注意的是,填充和边框包含在滚动区域中,所以当规范说“内容”时,它可能指的是边框框,或者至少,它似乎是这样解释的。
为什么display: inline-block
有效?
基本上,边距在inline-block
元素上的行为不同,因为它们是内容级别而不是块级别,并且它们没有“过度约束”的概念。