为什么 CSS 中的边距/填充百分比总是根据宽度计算?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11003911/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 04:11:15  来源:igfitidea点击:

Why are margin/padding percentages in CSS always calculated against width?

w3ccss

提问by mqp

If you look at the CSS box model spec, you'll observe the following:

如果您查看CSS 盒模型规范,您将观察到以下内容:

The [margin] percentage is calculated with respect to the widthof the generated box's containing block. Note that this is true for 'margin-top' and 'margin-bottom' as well.If the containing block's width depends on this element, then the resulting layout is undefined in CSS 2.1. (emphasis mine)

[margin] 百分比是根据生成的框的包含块的宽度计算的。请注意,对于“margin-top”和“margin-bottom”也是如此。如果包含块的宽度取决于此元素,则生成的布局在 CSS 2.1 中未定义。 (强调我的)

This is indeed true. But why? What on earth would compel anyone to design it this way? It's easy to think of scenarios where you want, e.g. a certain thing to always be 25% down from the top of the page, but it's hard to come up with any reason why you would want vertical padding to be relative to the horizontal size of the parent.

这确实是事实。但为什么?到底是什么迫使任何人以这种方式设计它?很容易想到您想要的场景,例如某个东西总是从页面顶部向下 25%,但很难想出任何理由为什么您希望垂直填充相对于水平尺寸父母。

Here's an example of the phenomenon I'm referring to:

这是我所指的现象的一个例子:

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

http://jsfiddle.net/8JDYD/

http://jsfiddle.net/8JDYD/

采纳答案by Ryan Kinal

Transferring my comment to an answer, because it makes logical sense. However, please note that this is unfounded conjecture. The actual reasoning of why the spec is written this way is still, technically, unknown.

将我的评论转移到答案中,因为它合乎逻辑。但是,请注意,这是毫无根据的猜想。为什么以这种方式编写规范的实际推理在技术上仍然未知。

Element height is defined by the height of the children. If an element has padding-top: 10% (relative to parent height), that is going to affect the height of the parent. Since the height of the child is dependent on the height of the parent, and the height of the parent is dependent on the height of the child, we'll either have inaccurate height, or an infinite loop. Sure, this only affects the case where offset parent === parent, but still. It's an odd case that is difficult to resolve.

元素高度由子元素的高度定义。如果元素具有 padding-top: 10%(相对于父级高度),这将影响父级的高度。由于孩子的身高取决于父母的身高,而父母的身高又取决于孩子的身高,我们要么高度不准确,要么无限循环。当然,这只会影响 offset parent === parent 的情况,但仍然如此。这是一个很难解决的奇怪案例。

Update: The last couple sentences may not be entirely accurate. The height of the leaf element (child with no children) has an effect on the height of all elements above it, so this affects many different situations.

更新:最后几句话可能不完全准确。叶元素(没有子元素的子元素)的高度会影响其上方所有元素的高度,因此这会影响许多不同的情况。

回答by Chuck Kollars

For "n%" margin (and padding) to be the samefor margin-top/margin-right/margin-bottom/margin-left, all four have to be relative to the same base. If top/bottom used a different base than left/right', then "n%" margin (and padding) wouldn't mean the same thing on all four sides.

对于margin-top/margin-right/margin-bottom/margin-left 的“n%”边距(和填充)相同,所有四个都必须相对于相同的基数。如果顶部/底部使用的基数与左/右'不同,那么“n%”边距(和填充)在所有四个边上的含义并不相同。

(Also note having the top/bottom margin relative to the widthenables a weird CSS hack that allows you to specify a box with an unchanging aspect ratio ...even if the box is rescaled.)

(另请注意,相对于宽度的顶部/底部边距启用了一个奇怪的 CSS hack,它允许您指定一个具有不变纵横比的框......即使框被重新缩放。)

回答by Joy

I vote for the answer from @ChuckKollars after playing with this JSFiddle(on Chrome 46.0.2490.86) and referring to this post(written in Chinese).

在玩过这个JSFiddle(在 Chrome 46.0.2490.86 上)并参考这篇文章(用中文写)后,我投票支持@ChuckKollars 的答案。



A major reason against the infinite calculationconjecture is that: using widthfaces the same infinite calculationproblem.

反对无限计算猜想的一个主要原因是:使用width面临同样的无限计算问题。

Have a look at this JSFiddle, the parentdisplay is inline-block, which is eligible to define margin/padding on it. The childhas margin value 20%. If we follow the infinite calculationconjecture:

看看这个JSFiddleparent显示是inline-block,它有资格在其上定义边距/填充。在child有边距值20%。如果我们遵循无限计算猜想:

  1. The width of the childdepends on the parent
  2. The width of the parentdepends on the child
  1. 宽度child取决于parent
  2. 宽度parent取决于child

But as a result, Chrome stops the calculation somewhere, resulting:

但结果是,Chrome 在某处停止了计算,结果:

enter image description here

在此处输入图片说明

If you try to expand the "result" panel horizontally on the JSFiddle, you will find that the width of them will not change. Please note that the content in the childis wrapped into two lines(not, say, one line), why? I guess Chrome just hard-code it somewhere. If you edit the childcontent to make it more (JSFiddle), you will find that as long as there is extra space horizontally, Chrome keeps the content two lines.

如果您尝试在 JSFiddle 上水平展开“结果”面板,您会发现它们的宽度不会改变。请注意,里面的内容child被包装成两行(不是说,一行),为什么?我猜 Chrome 只是在某个地方对其进行了硬编码。如果您编辑child内容使其更多(JSFiddle),您会发现只要水平方向有额外的空间,Chrome 会将内容保留两行。

So we can see: there is some way to prevent the infinite calculation.

所以我们可以看到:有一些方法可以防止无限计算



I agree with the conjecture that: this design is just to keep the four margin/padding values based on the same measure.

我同意这样的猜想:这种设计只是为了保持基于相同度量的四个边距/填充值。

this post(written in Chinese) also proposes another reason is that: it is because of the orientation of reading/typeset. We read from top to down, with the width fixed and height infinite (virtually).

这个帖子(用中文写的)还提出了另一个原因:这是因为阅读/排版的方向。我们从上到下阅读,宽度固定,高度无限(实际上)。

回答by VKK

I realize the OP is asking whythe CSS specification defines top/bottom margin percentages as a % of width (and not, as would be assumed, height), but I thought it might also be useful to post a potential solution.

我意识到 OP 是在问为什么CSS 规范将顶​​部/底部边距百分比定义为宽度的百分比(而不是假设的高度),但我认为发布潜在的解决方案也可能有用。

Most modern browsers support vw and vh now which lets you specify margin numbers against the viewport width and viewport height.

大多数现代浏览器现在都支持 vw 和 vh,它允许您根据视口宽度和视口高度指定边距数字。

100vw/100vh equals 100% width/100% height (respectively) if there's no scrollbar; if there is a scrollbar the viewport numbers don't account for this (while the % numbers do). Thankfully, nearly all browsers use scrollbar sizes of 17px (see here), so you can use css calc function to account for this. If you don't know whether a scrollbar will appear or not, then this solution will not work.

如果没有滚动条,100vw/100vh 等于 100% 宽度/100% 高度(分别);如果有滚动条,则视口数字不考虑这一点(而 % 数字可以)。值得庆幸的是,几乎所有浏览器都使用 17px 的滚动条大小(请参阅此处),因此您可以使用 css calc 函数来解决此问题。如果您不知道是否会出现滚动条,则此解决方案将不起作用。

For example: Assuming no horizontal scrollbar, a top margin of 50% of height, could be defined as "margin-top: 50vh;". With a horizontal scrollbar, this could be defined as "margin-top: calc(0.5 * (100vh - 17px));" (remember that the minus and plus operators in calc require spaces on both sides!).

例如:假设没有水平滚动条,高度的 50% 的顶部边距可以定义为“margin-top: 50vh;”。使用水平滚动条,这可以定义为“margin-top: calc(0.5 * (100vh - 17px));” (请记住,calc 中的减号和加号运算符要求两边都有空格!)。