详解css盒模型与外边距重叠

1,058 阅读6分钟
原文链接: segmentfault.com

盒模型的构成

之前写了一篇关于如何解决css的外边距重叠问题,可是后来发现,我有些本末倒置了,对于一个问题的正确的处理流程就应该是先发现问题,分析问题,解决问题,所以我在这篇文章中就对下css的盒模型,什么是外边距重叠,为什么会发生外边距重叠,以及怎样计算外边距重叠一一进行解读,旨在透过现象看本质,达到掌握的目的.文章可能会有点长,为节省时间大家可以根据掌握的情况浏览阅读.

1.结构
为了给文档树中的各个元素排版定位(布局),浏览器会根据渲染模型,为每个元素生成四个嵌套的矩形框,他们分别是content box,padding box, border box,margin box,他们是不可分割的,并在一定情况下会重合, 这就是css规范中所描述的盒模型,它是以CSS的角度去看一个元素被渲染后的抽象形态,是一个元素自身的构成部分.

图片描述

注:padding、border 和 margin 区域都包括 top、right、bottom、left 四部分。如图所示("LM" 代表 left margin,"RP" 代表 right padding,"TB" 代表 top border……)。

2.边界

上述四个区域(content, padding, border, margin)分别有他们的边界,细化来说, 每个区域都有top, right, bottom, left四个边界.

  • Content边界/内边界: content边界环绕在由该元素的宽和高决定的一个矩形上,这个尺寸通常由该元素渲染后的内容决定,这四个content边界组成的矩形框就是该元素的content box.

  • Padding边界:padding边界环绕在该元素的padding区域的四周,顾名思义,填充背景色.如果padding的宽度为零,则padding边界与content边界重合.这四个padding边界组成的矩形就是该元素的padding box.

  • Border边界:border边界环绕在该元素的border区域的四周.如果border的宽度为零,则border边界与padding边界重合.这四个border边界组成的矩形就是该元素的border box.

  • Margin边界:margin边界环绕在该元素的margin区域的四周,如果margin的宽度为零,则margin边界与border边界重合.这四个margin边界组成的矩形就是该元素的margin box.

3.一些小的注意事项,如果你已掌握,请忽略
(1) 对于行内非替换元素(例如span),垂直方向上的margin不起作用
(2) margin不适用于table类型的元素,如table-caption,table,inline-table,以及td,th,tr等.
(3) border-style的可用值有:’none’(无样式),’hidden’(隐藏),’dotted’(点线),’dashed’(虚线),’solid’(实线),’double’(双线),’groove’(3D凹槽轮廓),’ridge’(3D吐槽轮廓),’inset’(3D凹边轮廓), 'outset'(3D凸边轮廓).后四项很少用到,所以在此提一下,大家可以尝试自己运行下,看看他们之间的区别.

外边距重叠

这个也是我这篇文章要重点介绍的.Collapsing margins,即外边距重叠,指的是毗邻的两个或多个普通流中的块元素垂直方向山的外边距会合并为一个外边距.

其中所说的margin毗邻可以归结为以下两点:

  • 这两个或多个边距没有被非空内容,padding,border或clear分隔开

  • 这些margin都处于普通文档流中注意一点,在没有被分割开的情况下,一个元素的margin-top回和它普通流的第一个元素的margin-top相邻,只有在一个元素的height是'auto'的情况下,他的margin-bottom才会和它普通流中的最后一个元素(非浮动元素等)的margin-bottom相邻.

示例代码:

<div style="border:1px solid red; width:100px;">
    <div style="margin:50px 0; background-color:green; height:50px; width:50px;" class="C">
       <div style="margin:20px 0;">
           <div style="margin:100px 0;">B</div>
       </div>
    </div>
</div>

效果图:
图片描述

因为.C这个div的高度不是auto,所以他的margin-bottom和他的子元素B的margin-bottom不相邻,因此,不会发生重叠,依然只有50px;

折叠后margin的计算
1.参与折叠的margin都是正值
例子:

<div style="height:50px; **margin-bottom:50px;** width:50px; background-color: red;">A</div>
<div style="height:50px; **margin-top:100px;** width:50px; background-color: green;">B</div>

在 margin 都是正数的情况下,取其中 margin 较大的值为最终 margin 值.

示意图:
图片描述

2.参与折叠的margin都是负值
例子:

<div style="height:50px; **margin-bottom:-75px;** width:50px; background-color: red;">A</div>
<div style="height:50px; **margin-top:-50px;** width:50px; background-color: green;">B</div>

在 margin 都是负值的时候,取的是其中绝对值较大的,然后从零开始,负向位移.
示意图:
图片描述

3.参与折叠的margin中有正值有负值
例子:

<div style="height:50px; **margin-bottom:-50px;** width:50px; background-color: red;">A</div>
<div style="height:50px; **margin-top:100px;** width:50px; background-color: green;">B</div>

在 margin中有正值有负值的时候,要从所有负值中选出绝对值最大的,所有正值中选择绝对值最大的,二者相加,此例的结果即为: 100px + (-50)px =50px;

示意图:

图片描述

4.相邻的margin要一起参与计算
例子:

<div style="margin:50px 0; background-color:green; width:50px;">
    <div style="**margin:-60px 0;**">
           <div style="**margin:150px 0;**">A</div>
    </div>
</div>
<div style="**margin:-100px 0**; background-color:green; width:50px;">
    <div style="**margin:-120px 0;**">
           <div style="**margin:200px 0;**">B</div>
    </div>
</div>

请注意,多个 margin 相邻折叠成一个 margin,所以计算的时候,应该取所有相关的值一起计算,而不能分开分步来算。以上例子中,A 和 B 之间的 margin 折叠产生的 margin,是6个相邻 margin 折叠的结果。将其 margin 值分为两组:

正值:50px,150px,200px
负值:-60px,-100px,-120px
根据有正有负时的计算规则,正值的最大值为 200px,负值中绝对值最大的是 -120px,所以,最终折叠后的 margin 应该是 200 + (-120) = 80px。

浮动元素,inline-block元素,绝对定位的元素和创建了块级格式化上下文的元素,不和它的子元素发生 margin 折叠

另外,要注意,自身的margin-botom和margin-top相邻时也会发生重叠,只有当自身内容为空,垂直方向上border,padding,均为空时,自身的margin-top与margin-bottom才会相邻.

原文连接:w3help.org/zh-cn/kb/00…
推荐网站: w3help.org 这个网站可以帮我们详细解读了css很多的特性,非常棒的网站.

以上都是我个人的粗浅之见,希望口下留情,错误之处可评论或者私信给我指明,我会及时改正的.另外关于这篇文章的不解之处或者说觉得我说的不完善或者不明确的地方都可以评论或者私信给我.如果觉得这篇文章帮到你了,记得点赞或者收藏奥!.