当前位置: 首页 > Web前端 > CSS

为什么margin-top设置百分比是根据父元素的宽度来计算的?

时间:2023-03-30 15:28:26 CSS

margin-top和padding-top设置百分比的问题我们都知道css很简单。所以在平时的开发中,并没有在意一些具体的细节。我们知道某个属性值的大概含义。比如我们知道CSS的盒子模型由四部分组成:margin、border、padding、content。如果我们要设置一个元素的外边距,只需要设置外边距值即可。margin的值可以是数值、百分比和自动。margin是一种缩写形式,我们也可以分别设置margin的top、right、bottom、left值。例如,我们编写如下代码:margincontent

那么问题来了,其中,margin-top:10%;这个百分比是基于谁的?让我们看另一个例子:帕迪ngcontent
这里的padding-top:20%;百分比是根据谁计算的?如果你已经知道答案,那么可能就没有必要再往下看了,但如果你还有疑惑,那么我们接下来就来一探究竟。结果分析先不看结果,按照常规思维来想一想。页面中有一个.margin-container容器元素和一个.margin-child子元素。容器元素和子元素设置了相应的宽度和高度。我们都知道块级元素在页面的垂直方向上是一个接一个排列的,而margin-top是当前设置元素的外上边距,所以应该是在垂直方向上设置的一个距离。如果设置为百分比,应该按照元素的高度来计算。暂且不计较对错。这里有两个问题:margin-top在设置百分比的时候是根据自身元素的值还是根据容器元素的值来计算的?margin-top百分比是根据高度还是宽度计算的?接下来我们看一下具体的结果:其实从这张图我们就可以得到我们想要的答案了。首先,让我们看看margin-child的margin-top值设置为10%。在chrome开发者工具中,我们可以看到计算出来的margin-top值为40px。我们的margin-child的宽和高分别是200px和100px,margin-container的宽和高分别是400px和200px。所以我们可以得出margin-child对应的margin-top为10%,也就是其父元素margin-container宽度400px的10%。所以上面两个问题的答案是:margin-top设置百分比是根据容器元素的值计算的margin-top设置百分比是根据width计算的当然如果看padding-top设置的话。也会得到同样的结果。为什么?为什么它是根据宽度而不是高度来计算的?为什么是基于父元素而不是子元素计算呢?(另外这里注意观察的话,我们把margin-child的margin-top设置为10%。我的直觉应该是margin-child和margin-container之间会有10%的距离,但是从根据渲染结果,margin-container和body的距离实际上是10%,这就涉及到margin合并的问题,不清楚的可以自行参考相关问题。)我们可以从W3C规范文档中得知:thisisspecificationinthespecification,也就是浏览器或者浏览器的渲染引擎(注:也许这样说不太合适)是这样实现的。那为什么会有这样的规定呢?根据身高计算有什么问题?这篇文章给出了一些相应的解释,总结了两点:margin/padding是根据一个值计算的,width是计算的,可以保证top,right,bottom,left这四个值的一致性,因为父元素的高度是根据它包含的子元素计算的。如果子元素的margin/padding是根据父元素的高度计算的,会造成高度计算的循环依赖。让我们关注第二点。假设我们在第一个例子中没有为margin-container设置宽度和高度。保证金容器{背景:#333;color:#fff;边距内容此时父元素的宽度为714px,高度为100px。因为目前只有一个子元素,子元素的高度为100px,子元素的margin-top为父元素宽度的10%,计算后为71.4px。由于错误,渲染显示显示为71.391px,子元素的边距与父元素的边距合并,因此看起来父元素距离body顶部为71.391px。所以父元素的高度是100px。试想如果我们根据高度计算margin百分比,那么margin-child的margin-top值应该是100px*10%=10px。好像没什么问题,但是渲染的时候我们知道body的宽度。由于没有设置margin-container的宽高,所以我们在渲染margin-contaner的时候需要计算它的宽高。这时候我们可以确定它的宽度就是body的宽度714px。高度未知,需要根据子元素的高度计算高度,于是马上进行margin-child的分析计算,发现子元素的高度为100px,margin-top是父元素高度的10%,现在父元素的高度是不确定的,那么margin-child的margin-top应该是多少呢?那么有人可能会说,父元素的高度不就是根据子元素的高度来计算的吗?子元素的高度为100px,所以父元素的高度为100px,所以子元素的margin-top值为10px。如果浏览器引擎按照解析子元素高度->计算父元素高度->计算子元素边距的顺序解析css,似乎是合理的。那么我们来看下面的例子:.margin-container{background:#333;颜色:#fff;}.margin-child{margin-top:10%;宽度:200px;高度:100px;background-color:black;边距内容边距内容2运行结果为:此时的父元素包含两个子元素。父元素的高度计算为第一个子元素的高度+第二个子元素的高度+第二个子元素的margin-top。按照刚才说的,如果浏览器引擎按照解析子元素高度->计算父元素高度->计算子元素边距的顺序解析CSS,那么子元素的高度为200px->父元素的高度为200px->子元素margin-top为10%=20px。结合前面的操作结果,父元素的高度计算为第一个子元素的高度+第二个子元素的高度+第二个子元素的margin-top。这时候父元素的高度又变了,子元素的高度margin值还需要改吗?如果需要改变,父元素的高度又会改变,这就是行程的循环依赖。那么,你真的了解css中的margin和padding吗?以上是我个人的看法。其实还有一些不严谨的地方。浏览器的css解析和渲染序列流等等,这里抛出问题的权利。如有错误,希望指出指正,共同讨论学习。