A 文档流布局以及margin:auto的原理

本文详细探讨了CSS中的常规流布局原理,包括块级元素和行内元素的排列方式,以及盒模型的宽度计算规则。重点阐述了width、margin为auto时的处理方式,外边距的auto如何适应空间,以及浏览器如何调整元素以满足水平布局。此外,还介绍了外边距合并的现象和解决方法,以及负外边距如何影响元素位置。通过实例解释了负外边距导致元素溢出和覆盖的视觉效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考:
https://www.zhihu.com/question/21644198

常规流布局

也叫常规流、文档流、普通文档流、常规文档流,浏览器默认的排列方式。将窗体自上而下分成一行行,按照源代码的顺序排列将块级元素从上到下、行内元素在每行中从左至右的依次排放元素,并占据文档一定的空间。

常规流快盒的水平布局规则:
每个块盒的总宽度(margin border padding content加起来),必须刚好等于包含块的宽度,因为要独占一行。

盒模型属性中只有这三个值可以设置auto的值:
width、margin-left、margin-right

宽度(width)的默认值:
auto表示适应包含块内容区的宽度,计算包含块内容区的可用空间作为宽度值,实际元素的宽度减去margin、border、padding就是content.width的值。

如下所示:
红色子元素的包含块是蓝色元素,红色子元素的width默认值为auto,那么子元素auto到底等于多少呢?

父元素的width为719.2px,子元素的margin占据父元素内容区的4px,那么父元素内容区的还剩715.2px,子元素宽度会计算父元素剩余的可用空间,所以子元素的宽度也就是715.2。
在这里插入图片描述

外边距的auto:
表示auto表示适应包含块内容区的宽度,也会计算剩余空间,和width是一样的。

一个元素在其父元素中,水平布局必须要满足一下等式
水平格式化布局的计算规则:

margin-left + border-left + padding-left + width + margin-right + border-right + padding-right=其包含块内容区的宽度。

因为是快盒,要占满一行,如果盒模型上面几个属性相加的整个宽度不等于包含块内容区的宽度,哪浏览器肯定要制定一套计算规则来约束,由浏览器去调整盒模型的值以满足占满一行的条件。

浏览器的调整的情况(如果等式不满足):
1.如果这7个值没有auto的情况,则浏览器会自动调整margin-right值,就是由margin-right去计算剩余空间,以使等式满足。

比如:
父元素宽度是500px
子元素的总宽度根据等式: margin-left + border-left + padding-left + width + padding-right + border-right + margin-right = container.width。
0 + 0 + 0 + 300 + 0 + 0 + 0 = 300
并不等于父元素的宽度500,于是浏览器会调整margin-right值,由margin-right计算可用空间,因此margin-right会计算为200px。加在一起为500刚好满足这个等式。

2.如果这7个值某个值为auto,则会自动调整为auto哪个值,以使等式成立。

3.如果一个宽度和一个外边距设置为auto,则宽度会被调整计算可用空间(宽度胜出),设置为auto的外边距会自动为0。

5.如果三个值都设置为auto,则外边距都设置为0,由宽度计算可用空间

6.如果将两个外边距设置为aut,,宽度固定值,则外边距都会计算可用空间,得到的结果是margin两边会均分包含块内容区剩余空间,这样元素就居中了。

在这里插入图片描述
7. 如果width超出父元素的宽度那么浏览器会把margin设置为负值,以使等式满足。

8.替换元素的水平计算规则和不可替换元素一样唯一不同的是width:为auto不会参与调整,元素的宽度则是内容固有宽度。

每个块盒垂直方向上的auto:
因为垂直方向的总宽度并不要求占满,所以垂直方向上的height和margin没有哪个上面的条件等式。
所以:
height:auto 适应内容,由内容撑开。
margin-top及margin-bottom:auto 表示0。

盒子百分比取值:
padding、宽、margin可以取值为百分比。
以上的所有百分比(包括上下方向上的百分比)相对于包含块的宽度计算。
也就是说margin-top和bottom的百分比也会相对于宽度计算。

注:水平方向适用于行盒,垂直方向不适用,因为行盒垂直方向属性无效,还有width、height也无效。

快盒高度的百分比:

  1. 包含块的高度(就是auto值适应内容)取决于子元素的高度(父元素设置auto,子元素设置百分比,子元素多高父元素多高,子元素的高度是父元素的一半,这个是相互矛盾的所以无效),设置百分比无效
  2. 包含块的高度不取决于子元素的高度(父元素高度固定死),百分比相当于父元素的高度

快盒上下外边距的合并:
两个常规流块盒,上下外边距相邻,会进行合并(父子元素也会合并因为相邻)。
两个外边距取最大值。

案例:
1)两个外边距相邻了(中间没有任何东西阻挡),会进行合并重叠
在这里插入图片描述
2)父子元素也会发生外边距相邻.
在这里插入图片描述

发生合并的取值情况:
1.如果相邻的外边距一正一负,取两者的和。
2.如果相邻的外边距都是负数,两者中取绝对值较大的。
3.如果参与折叠的外边距中包含负值,折叠后的外边距的值为最大的正边距与最小的负边距(即绝对值最大的负边距)的和,;也就是说如果有三个元素有margin:-13px 8px 100px叠在一起,最大正边距是100,最小负边距是-13,那么边界范围的技术就是 100px-13px=87px(这个三个一起是87px) 用于父子嵌套的情况,先取出负 margin 中绝对值中最大的,然后,和正 margin 值中最大的 margin 相加。
4.即使某一外边距为0,这些规则仍然适用。因此就算父元素的外边距是0,第一个或最后一个子元素的外边距仍然会“溢出”到父元素的外面。
浮动元素、inline-block 元素、绝对定位元素的 margin 不会和垂直方向上其他元素的 margin 折叠

解决方法:
1.外边距合并的条件是相邻,任何东西把他们隔开它们就不会合并,所以可以设置padding或者border。
2.可以创建bfc,创建bfc的元素里面和外面是两个渲染区域互不影响。

负外边距:
在这里插入图片描述

父内容区的宽度为659.2px,首先子元素boder为4px margin为-114px,而witdh为auto,按照上面的等式:margin-left + border-left + padding-left + width + margin-right + border-right + padding-right=其包含块内容区的宽度。

等式:
-57px + 2px + 0px + auto(width) + 0px + 2px + -57px = parent.content.width

根据块盒的水平计算规则width:auto计算剩余空间,所以width等于769.2就满足上面的方程。

那么width计算剩余空间就会等于769.2px。等于元素内容区的宽度比你整个元素盒模型的宽度都宽,就变成这个效果了,但实际它总宽度还是659.2。

就相当于子元素宽度比父元素宽度大,使得子元素溢出了父元素,元素的4个边都是如此:如果外边距设置为负值,内容就会超出外边界,浮动元素也是如此。

        .a{
          width: 100px;
          height: 50px;
          border: 5px solid #ccc;
          display: inline-block;
        }
        .b{
          width: 200px;
          height: 50px;
          background-color: yellow;
        }

        .c{
          width: 200px;
          height: 50px;
          background-color: red;
          display: inline-block;
        }
		<div class="a">
        	<div class="b"></div>
   		</div>
   		<div class="c"></div>

在这里插入图片描述
我们可以看到黄色元素溢出了,并且被红色元素覆盖了,这是因为后面的元素会覆盖前面的元素,而且实际父元素是100px,而子元素c是200px,在布局时,只算父元素的大小,所以被覆盖了。

我们把父元素的灰色边框去掉:
在这里插入图片描述
这相当于啥,这相当于我们把黄色元素的margin-right设置为-100px,然后被红色元素覆盖了,所以很多教程说margin为负值是往反方向移动,其实是因为元素margin-right为-100px;实际上右边有100px是不占据实际空间大小的,所以红色元素会往左100px填补这个空间,所以你从视觉上感觉红色元素覆盖了黄色元素。

黄色元素盒模型的计算(假设黄色元素margin为-100px):
margin-left + border-left + padding-left + content + padding-right + border-right + marin+right = 元素的总宽度
0 + 0 + 0 + 200px + 0 + 0 + (-100px) = 100px;
上面计算可以知道黄色元素的总宽度是100px,右边还有100px被负margin-right剪掉了,但是内容区的宽度是200px,根据背景的规则,背景会覆盖元素内边距和内容区,所以就变成这样了,于是你感觉像是元素被覆盖了.

反正一般来说margin为正值是向元素外面增加距离,而外边距为负值则会往元素里面缩短距离,大家可以看到这张图,右边框到右边界的距离就是外边距,你可以把右外边界看成是外边距的参考线,一般情况下为正值都是往右边移动增加距离的,如果为负值右外边界则会往左移动,这样就往元素里面缩短距离。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值