CSS 右边距在溢出滚动的 div 中不起作用
Posted
技术标签:
【中文标题】CSS 右边距在溢出滚动的 div 中不起作用【英文标题】:CSS Right Margin Does Not Work Inside a Div With Overflow Scroll 【发布时间】:2012-07-26 13:51:53 【问题描述】:我正在尝试制作两个 div,一个在另一个里面。内层div大于外层,外层有overflow:scroll
,内层有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 任何地方。
【问题讨论】:
brunildo.org/test/scroll-child-margin.html有一个很好的问题演示 【参考方案1】:TL;DR:
边距用于将元素从包装器中移入,而不是向外扩展包装器。
长解释:
除了在文档中的任意位置指定水平margin
之外,此行为与指定width
一致。为了分解它,请考虑以下 sn-p,其中我指定了一个没有 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 formatting model details”的“Block-level, non-replaced elements in normal flow”部分:
在其他属性的使用值中必须保持以下约束:
'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
。
现在,由于您有一个固定的 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
不包括边距?
主要是因为规范没有说应该。让我们看一下 overflow
属性的 CSS 2 规范。
摘自“Visual effects”的“Overflow and clipping”部分:
每当发生溢出时,'overflow' 属性指定一个框是否被剪裁到其填充边缘,如果是,是否提供滚动机制来访问任何被剪裁的内容。
看看它是如何具体说“剪辑的内容”的。关于“内容”的解释,请参考 CSS 2 规范中的下图。
来自“Box model”的“Box dimensions”部分的图形:
正如我们所见,margin
与 content
是分开的。然而,此时值得注意的是,填充和边框包含在滚动区域中,所以当规范说“内容”时,它可能指的是边框框,或者至少,它似乎是这样解释的。
为什么display: inline-block
有效?
基本上,inline-block
元素的边距表现不同,因为它们是内容级别而不是块级别,并且它们没有“过度约束”的概念。
【讨论】:
【参考方案2】:将display:inline-block;
添加到#inner
div
看到这个fiddle
【讨论】:
您能否解释一下为什么 div 必须是inline-block
元素才能使右边距推出外部 div?
它与依赖于空白的渲染有关,除此之外我不太确定。 designshack.net/articles/css/… 有一个很好的参考资料
感谢您的参考。仍然不是我所期望的,但这确实有些道理。
应该指出,如果您有依赖于 width:auto 的内部内容的 css,这不是一个好的解决方法。像 jQuery UI 的选项卡这样的东西不会再填满整个 div,因为它没有已知的父宽度。【参考方案3】:
所以这里的答案实际上并不能解决问题! (虽然对它不起作用的原因非常详细)
我需要一个解决方案。这是我的未来读者。使用 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>
【讨论】:
如果您可以简化 CSS 以去除不相关的部分(例如border-radius
),那就太好了,但是 +1 可以找到现代的 flexbox 解决方案!
当然,@SeantheBean 清理了一点。也可以随意编辑。我正在快速复制我自己的代码!对 flexbox 的热爱!以上是关于CSS 右边距在溢出滚动的 div 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章