我正在尝试制作两个div,一个在另一个里面。内部div大于外部div,外部div具有overflow:scroll
,内部div具有margin:25px
。所以我这样做:
#outer {
width: 200px;
height: 100px;
overflow: scroll;
}
#inner {
width: 400px;
height: 200px;
margin: 25px;
}
...
<div id="outer">
<div id="inner">
</div>
</div>
而不是内部div具有25px的边缘,如预期的那样,三边有25px的边距,但在右边没有。在我看来,这非常违反直觉。
如果我添加一个宽度足够宽的中间div来包含内部div + 50px,我们可以让它看起来正确,但这看起来像是一个hacky解决方法。
请参阅我在JSFiddle上的示例:http://jsfiddle.net/d3Nhu/16/
在每个主流浏览器中都会出现相同的情况。这种行为有什么好的理由吗?根据CSS规范,这是正确的行为吗?
注意:正如您在此示例中所期望的那样,如果您使用overflow:auto
而不是overflow:scroll
,则没有任何区别。
编辑:请注意,我不正在寻找此行为的解决方法。 (我已经找到了一个。)我正在寻找关于此行为的原因的任何见解,特别是如果它在CSS specification任何地方都有记录。
答案 0 :(得分:47)
边距用于从包装器移动元素,而不是向外扩展包装。
此行为与在文档中的任何位置指定水平width
之外的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规范中记录的Visual格式化模型详细信息中。
以下约束必须包含在其他属性的已使用值中:
'margin-left'+'border-left-width'+'padding-left'+'width'+'padding-right'+'border-right-width'+'margin-right'=包含的宽度块
[...]
如果以上所有都具有“auto”以外的计算值,则称这些值为“过度约束”,并且其中一个使用的值必须与其计算值不同。如果包含块的'direction'属性值为'ltr',则忽略指定的'margin-right'值,并计算该值以使等式为true。如果'direction'的值是'rtl',则会发生'margin-left'。
摘录非常密集,所以简单地说,让我们忽略border
和padding
的宽度,两者都是0
,留给我们width
,{ {1}}和margin-left
。
现在,由于您有margin-right
和width
的固定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
属性的CSS 2规范。
每当发生溢出时,'overflow'属性指定是否将框剪切到其填充边缘,如果是,则是否提供滚动机制来访问任何剪切的内容。
看看它是如何具体说“剪掉内容”。有关“内容”的说明,请参阅CSS 2规范中的以下图表。
我们可以看到,overflow
与margin
是分开的。但是,在这一点上值得注意的是,滚动区域中包含填充和边框,因此当规范说“内容”时,它可能指的是边框,或者至少,它似乎是如何被解释的
content
有效?基本上,display: inline-block
元素的边距表现不同,因为它们是内容级别而不是块级别,并且它们没有“过度约束”的概念。
答案 1 :(得分:16)
将display:inline-block;
添加到#inner
div
请参阅此fiddle
答案 2 :(得分:1)
因此,这里的答案实际上并不能解决问题! (尽管超级详细地说明了它不起作用的原因)
我需要一个解决方案。这是我将来的读者的地方。使用display:flex;
与伪:: after元素的组合来伪造div的存在以提供所需的边距。
.wrapper {
display: flex;
width: 400px;
height: 100%;
padding: 40px;
background: lightGrey;
}
.lists_container {
display: flex;
flex-direction: row;
justify-content: flex-start;
overflow: auto;
position: relative;
background: grey;
padding: 40px;
margin: 40px;
width: 100%;
}
.card {
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
min-width: 250px;
max-width: 500px;
height: 100px;
margin: 50px 0;
padding: 20px;
background: orange;
margin-right: 30px;
}
.card.last::after {
content: '';
position: absolute;
right: -100px;
width: 40px;
height: 100%;
background: red;
}
<div class="wrapper">
<div class="lists_container">
<div class="card">
</div>
<div class="card">
</div>
<div class="card last">
</div>
</div>
</div>