如果查看CSS box model spec,您会看到以下内容:
[margin]百分比是根据生成的框的包含块的宽度计算的。 请注意,对于'margin-top'和'margin-bottom'也是如此。如果包含块的宽度取决于此元素,则在CSS 2.1中未定义结果布局。 (强调我的)
确实如此。但为什么?究竟是什么迫使任何人以这种方式设计它?您可以轻松地想到您想要的场景,例如:从页面顶部开始总是降低25%,但很难想出为什么你希望垂直填充相对于父级的水平大小。
以下是我所指的现象的一个例子:
<div style="border: 1px solid red; margin: 0; padding: 0; width: 200px; height: 800px;">
This div is 200x800.
<div style="border: 1px solid blue; margin: 10% 0 0 10%;">
This div has top-margin of 10% and left-margin of 10% with respect to its parent.
</div>
</div>
答案 0 :(得分:57)
将我的评论转移到答案,因为它具有逻辑意义。但请注意,这是毫无根据的猜想。在技术上,这种方式编写规范的实际原因仍然是未知的。
元素高度由高度定义 儿童。如果元素具有padding-top:10%(相对于父级 高度),这将影响父亲的身高。自从 孩子的身高取决于父母的身高,以及 父母的身高取决于孩子的身高,我们会 要么是高度不准确,要么是无限循环。当然,这只是 影响偏移父===父,但仍然。这是一个 奇怪的情况很难解决。
更新:最后几句话可能不完全准确。叶元素的高度(没有子元素的子元素)对其上方所有元素的高度有影响,因此这会影响许多不同的情况。
答案 1 :(得分:26)
对于“n%”边距(和填充)为margin-top / margin-right / margin-bottom / margin-left的相同,所有四个必须相对于相同基础。如果顶部/底部使用与左/右不同的底部,那么“n%”边距(和填充)在所有四个边上都不会意味着相同的东西。
(另请注意,相对于 width 具有顶部/底部边距会启用一个奇怪的CSS hack,允许您指定具有不变宽高比的框...即使该框重新缩放。 )
答案 2 :(得分:3)
在使用此JSFiddle(在Chrome浏览器46.0.2490.86上)并参考this post(用中文书写)后,我投票支持@ChuckKollars的答案。
反对无限计算猜想的一个主要原因是:使用width
面临同样的无限计算问题。
查看此JSFiddle,parent
显示为inline-block
,有资格在其上定义边距/填充。 child
的边距值为20%
。如果我们按照无限计算猜想:
child
的宽度取决于parent
parent
的宽度取决于child
但结果是Chrome停止了计算,结果是:
如果您尝试扩展&#34;结果&#34;在JSFiddle上水平放置面板,你会发现它们的宽度不会改变。请注意child
中的内容包含在两行中(不是说,一行),为什么?我想Chrome只是在某处硬编码。如果您修改child
内容以使其更多(JSFiddle),您会发现只要水平有额外的空间,Chrome就会将内容保留两行。
所以我们可以看到:有一些方法可以阻止无限计算。
我同意这个猜想:这个设计只是为了保持四个边距/填充值基于相同的度量。
this post(中文)还提出另一个原因是:它是因为阅读/排版的方向。我们从上到下阅读,宽度固定,高度无限(虚拟)。
答案 3 :(得分:3)
我意识到OP要求为什么 CSS规范将顶部/底部边距百分比定义为宽度的百分比(而不是,假设高度),但我认为它也可能是发布潜在的解决方案很有用。
现在大多数现代浏览器都支持vw和vh,它允许您根据视口宽度和视口高度指定边距数。
如果没有滚动条,100vw / 100vh等于100%宽度/ 100%高度(分别);如果有滚动条,则视口编号不会考虑到这一点(而%数字会这样做)。值得庆幸的是,几乎所有浏览器都使用17px({{3}})的滚动条大小,因此您可以使用css calc函数来解释此问题。如果您不知道是否会出现滚动条,则此解决方案将无效。
例如:假设没有水平滚动条,高度为50%的上边距可以定义为&#34; margin-top:50vh;&#34;。对于水平滚动条,这可以定义为&#34; margin-top:calc(0.5 *(100vh - 17px));&#34; (请记住,calc中的减号和加号运算符需要两边都有空格!)。
答案 4 :(得分:1)
我知道这个问题有点老了,但是我想针对CSS3刷新它。虽然CSS2.1规范确实说相对于包含块的宽度定义了填充百分比和边距,但这并非总是总是。这取决于写入模式。这直接来自CSS3 specs:
作为推论,相对于CSS3中包含块的内联大小,总是根据CSS2.1中包含块的宽度计算出的边距和填充属性百分比。
我在tutorial on aspect ratios with CSS中对此进行了介绍。
具体地说,在Percentage Padding in Horizontal vs. Vertical Writing Modes上有一节。默认情况下,元素具有水平书写模式,其中文本从左到右水平(沿“内联”方向)流动。但是,实际上,您可以使用writing-mode
CSS属性将模式设置为垂直模式(文本从右向左或从左向右流动)。这是水平和垂直书写模式的一些示意图:
这些摘自MDN docs on writing modes。
在垂直书写模式下,填充百分比将相对于包含块的高度,而不是宽度。
这是证据:
.document {
writing-mode: vertical-rl;
width: 100%;
height: 100vh;
}
.parent {
width: 100%;
height: 200px;
background-color: black;
color: white;
}
.child {
padding: 10%;
background-color: white;
color: black;
border: solid 1px;
}
<div class="document">
<div class="parent">
<div class="child">
Child
</div>
</div>
</div>
孩子获得20px的填充,是其包含的块的高度(200px)的10%。
关于问题的原因,这里的其他帖子对此做了很好的介绍。