任务11- inline-block、BFC、边距合并

问题

1. 在什么场景下会出现外边距合并?如何合并?如何不让相邻元素外边距合并?给个父子外边距合并的范例

外边距合并指的是,当两个垂直外边距相遇时,它们将形成一个外边距。合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者。

外边距合并主要有 2 种典型的例子:
  1. 相邻元素的外边距合并
  2. 父子元素的外边距合并(假如“父”与“子”都在正常的文档流里面,“父”没有 border 和 padding ,那么它们之间就会产生外边距合并,取其中的最大值。)
  3. 自身“空元素”(无内容,无 border,无 padding)也有可能发生合并(这种情况比较特殊)
demo - 父元素与子元素的外边距合并
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>父元素与子元素外边距合并</title>
    <style media="screen">
        * {
            margin: 0;
            padding: 0;
        }
        .container {
            width: 300px;
            height: 300px;
            background-color: blue;
            /*border: 1px solid;*/
            margin: 100px;
        }
        .box {
            width: 100px;
            height: 100px;
            background-color: red;
            margin: 100px;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="box"></div>
    </div>
</body>
</html>
父元素与子元素外边距合并1.png

可以看出,父元素的 margin-top 与子元素的 margin-top 发生合并,变为 100px。

当父元素有 border 的时候,
.container {
            width: 300px;
            height: 300px;
            background-color: blue;
            border: 1px solid;
            margin: 100px;
        }
父元素与子元素外边距合并2.png

当父元素添加了 border ,父元素与子元素的外边距没有合并

demo-兄弟元素和它们的子元素
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>兄弟元素和它们的子元素</title>
    <style media="screen">
        * {
            margin: 0;
            padding: 0;
        }
        .ct1 {
            width: 300px;
            height: 300px;
            margin-bottom: 25px;
            background-color: yellow;
        }
        .box1 {
            width: 100px;
            height: 100px;
            background-color: red;
            margin-bottom: 100px;
        }
        .box2 {
            width: 100px;
            height: 100px;
            background-color: blue;
            margin-top: 100px;
            margin-bottom: 200px;
        }
        .ct2 {
            width: 300px;
            height: 300px;
            margin-top: 50px;
            background-color: lightgreen;
        }
    </style>
</head>
<body>
    <div class="ct1">
        <div class="box1"></div>
        <div class="box2"></div>
    </div>
    <div class="ct2"></div>
</body>
</html>
兄弟元素和它们的子元素1.png

注意:ct1 和 ct2 之间的间隔只有 50px。(各元素之间并没有“间隔”padding,border,BFC),推测:这个 “50px” 是 ct2 的。

当 ct2 的 margin-top 改为 30px 时,间隔为 30px。
兄弟元素和它们的子元素2.png
当 ct2 的 margin-top 改为 10px 时,ct1 与 ct2 之间的间隔为 25px。
兄弟元素和它们的子元素3.png
所以知道,ct1 与 box2 之间的下外边距为 “ct1”的。

原因:bottom margin of a last in-flow child and bottom margin of its parent if the parent has 'auto' computed height
(对于margin-bottom来说,父元素高度需为auto才能和子元素合并。)

设置 height 为 auto
.ct1 {
            width: 300px;
            /*height: 300px;*/
            margin-bottom: 25px;
            background-color: yellow;
        }
兄弟元素和它们的子元素4.png

ct1 和 ct2 之间的 “间隔” 为 box2200px

demo - “空元素”,高度为0并且最小高度也为0(无内容)的元素
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>空元素</title>
    <style media="screen">
        * {
            margin: 0;
            padding: 0;
        }
        .box {
            background-color: red;
            margin-top: 100px;
            margin-bottom: 100px;
        }
        p {
            background-color: green;
        }
    </style>
</head>
<body>
    <div class="box"></div>
    <p>testtesttesttesttesttesttesttest</p>
</body>
</html>
空元素外边距合并1.png

可以看见,.box 的上下 margin 发生合并(100px)。

当 .box 设置了 height (有数值)时,
.box {
            height: 100px;
            background-color: red;
            margin-top: 100px;
            margin-bottom: 100px;
        }
空元素上下外边距合并2.png
tips:
  1. 当 2 个 “div” 之间没有 border、padding以及不满足 BFC 的时候,会发生外边距合并。
  2. 在CSS当中,相邻的 2 个盒子(可能是兄弟关系也可能是祖先关系)的外边距可以结合成一个单独的外边距。
  3. 外边距合并的规则
  • 两个相邻的外边距都是正数时,折叠结果是它们两者之间的较大值
  • 两个相邻的外边距都是负数时,折叠结果是它们绝对值的较大值两者之间的较小值(例如,一个是 -90px, 另一个是 -30px, 则取 -90px)
  • 两个外边距一正一负时,折叠结果时两者相加的和
拓展阅读:
  1. CSS基础学习十五:盒子模型补充之外边距合并
  2. MDN_外边距合并
  3. 细说 CSS margin

2. 去除 inline-block 内缝隙有哪几种常见的方法?

!!!!!代码之间的“间隔”会显示为这个“内缝隙”
这个“间隔”可以理解为一个“空格”,可以应用“font”。

消除 inline-block 内缝隙方法
第 1 种方法:(删除间隔)

可以直接把各行代码的间隔全部删掉(简单粗暴的方法)

第 2 种方法:(设置margin-left)

设置 margin-left: -4px;(这个 -4px 是个约定俗成的数字)然后单独为第一个元素设置 margin-left: 0px;(防止走出父容器)

第 3 种方法:(font-size: 0px;)

font-size: 0px;然后为每个“字体”单独设置各自的“font-size”

第 4 种方法:(float)

float + 清除浮动

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>inline-block缝隙</title>
    <style media="screen">
        html,body,ul,li {
            margin: 0;
            padding: 0;
        }
        li {
            list-style: none;
        }

        .box {
            border: 1px solid green;
            overflow: auto;
            /*font-size: 0;*/
        }
        .box>li:first-child {
            /*margin-left: 0*/
        }
        .box>li {
            display: inline-block;
            /*margin-left: -4px;*/
            float: left;
            background-color: blue;
            color: #fff;
            padding: 3px;
            /*font-size: 12px;*/
        }
    </style>
</head>
<body>
    <ul class="box">
        <li>tag1</li>
        <li>tag2</li>
        <li>tag3</li>
    </ul>
    <p>
        dfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdf
    </p>
</body>
</html>

没清除浮动的后果:
没有清除浮动.png

父容器没有撑开,后面的 p围绕着浮动元素。

清除浮动:
已清除浮动.png

3. 父容器使用 overflow: auto | hidden 撑开高度的原理是什么?

overflow,指定如果内容溢出一个元素的框,会发生什么。
描述
visible 默认值。内容不会被修剪,会呈现在元素框之外
hidden 内容会被修剪,并且其余内容是不可见的
scroll 内容会被修剪,但是浏览器会显示滚动条以便查看其它的内容
auto 如果内容被修剪,则浏览器会显示滚动条以便查看其余的内容
inherit 规定应该从父元素继承 overflow 属性的值
首先,先来看看满足 BFC 的条件:
  1. float 的值不是 none
  2. position 的值不是 static 或者 relative
  3. display 的值是 inline-block、table-cell、flex、table-caption、inline-flex
  4. overflow 的值不是 visible

所以,只要 overflow 的值不是 visible ,都能形成 BFC。
这样,就可以让容器内的元素不受外面影响。

BFC是一个名词,是一个独立的布局环境,我们可以理解为一个箱子(实际上是看不见摸不着的),箱子里面物品的摆放是不受外界的影响的。转换为BFC的理解则是:BFC中的元素的布局是不受外界的影响(我们往往利用这个特性来消除浮动元素对其非浮动的兄弟元素和其子元素带来的影响。)

拓展阅读:
  1. 关于overflow:hidden
  2. 清理浮动的全家

4. BFC 是什么?如何形成 BFC,有什么作用?

Block formatting contexts,块级格式化上下文。

创建了 BFC 的元素就是 1 个独立的盒子,不过只有 Block-level box 可以参与创建 BFC,它规定了内部的 Block-level box 如何布局,并且与这个独立盒子里的布局不受外部影响,当然它也不会影响到外面的元素。

BFC 是个很奇怪的东西,它一直隐式地存在CSS的样式里,但是要记住 BFC 是页面元素里一个独立存在作用块,它不影响它外面的布局,外面的元素也不会影响到 BFC 里面的布局。

定义:浮动元素和绝对定位元素,非块级盒子的块级容器(例如:inline-blocks, table-cells, table-captions),以及 overflow 值不是 “visible” 的块级盒子,都会为他们的内容创建新的 BFC (块级格式上下文)。

一个 HTML 元素要创建 BFC ,则满足下列的任意一个或多个条件即可:
  1. float 的值不是 none
  2. position 的值不是 static 或者 relative
  3. display 的值是 inline-block、table-cell、flex、table-caption、inline-flex
  4. overflow 的值不是 visible
作用:
  1. 撑开父元素
  2. 阻止外边距
  3. 清除浮动的文字环绕和位置的影响

BFC 是一个独立的布局环境,其中的元素布局是不受外界的影响,并且在一个 BFC 中,块盒与行盒(行盒由一行中所有的内联元素所组成)都会垂直地沿着其父元素的边框排列。

BFC 有以下特性:
  1. 内部的 Box 会在垂直方向,从顶部开始一个接一个地放置。
  2. Box 垂直方向的距离由 margin 决定。属于同一个 BFC 的 2 个相邻 Box 的 margin 会发生叠加。
  3. 每个元素的 margin box 的左边,与包含块 border box 的左边相接触(对于从左到右的格式化,否则相反)。即使存在浮动也是如此。
  4. BFC 的区域不会与 float box 叠加。
  5. BFC 就是页面一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然。
  6. 计算 BFC 的高度时,浮动元素也参与计算。
拓展阅读:
  1. CSS之BFC详解

5. 浮动导致的父容器高度塌陷指什么?为什么会产生?有几种解决方法

父容器里面的元素浮动-->脱离文档流,父容器自然就会高度塌陷
这种情况,清除浮动即可。

父容器高度塌陷例子:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>父容器高度塌陷</title>
    <style media="screen">
        .container {
            width: 500px;
            border: 1px solid red;
        }
        .item1 {
            width: 100px;
            height: 100px;
            background-color: blue;
            float: left;
        }
        .item2 {
            width: 100px;
            height: 100px;
            background-color: green;
            float: right;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="item1"></div>
        <div class="item2"></div>
    </div>
</body>
</html>
父容器高度塌陷.png

清理浮动的方法

1. 清理浮动-使用带有 clear 属性的空元素
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>清理浮动-使用带有 clear 属性的空元素</title>
    <style media="screen">
        .container {
            width: 500px;
            border: 1px solid red;
        }
        .item1 {
            width: 100px;
            height: 100px;
            background-color: blue;
            float: left;
        }
        .item2 {
            width: 100px;
            height: 100px;
            background-color: green;
            float: right;
        }
        .clear {
            clear: both;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="item1"></div>
        <div class="item2"></div>
        <div class="clear"></div>
    </div>
</body>
</html>
清理浮动-使用带有 clear 属性的空元素.png

尽管这种方法兼容所有浏览器并且随用随清,但是这会添加大量无语义的 html 元素。

2. 使用 CSS 的 :after 伪元素
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用CSS的 :after 伪元素</title>
    <style media="screen">
        .container {
            width: 500px;
            border: 1px solid red;
        }
        .item1 {
            width: 100px;
            height: 100px;
            background-color: blue;
            float: left;
        }
        .item2 {
            width: 100px;
            height: 100px;
            background-color: green;
            float: right;
        }
        .container:after {
            content: '';
            display: block;
            clear: both;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="item1"></div>
        <div class="item2"></div>
    </div>
</body>
</html>
CSS-after清除浮动.png

父容器添加一个看不见的块元素( :after )来清理浮动。
需要注意的是,为了兼容 IE6 和 IE7,要添加一条 zoom:1; 来触发 haslayout (可以写到 IE6 和 IE7 的 CSS hacker 文件里,这样不会影响 W3C 标准验证。)

这种方法需要给每组浮动元素都添加一个容器,推荐在页面布局时使用。大量使用依然会对代码量造成一些影响。

3. 使用 CSS 的 overflow 属性
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用 CSS 的 overflow 属性进行怪异处理</title>
    <style media="screen">
        .container {
            width: 500px;
            border: 1px solid red;
            
            /*overflow: hidden;*/
            overflow: auto;
        }
        .item1 {
            width: 100px;
            height: 100px;
            background-color: blue;
            float: left;
        }
        .item2 {
            width: 100px;
            height: 100px;
            background-color: green;
            float: right;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="item1"></div>
        <div class="item2"></div>
    </div>
</body>
</html>
使用 overflow 属性.png

虽然很多地方以“将来浏览器可能不兼容”为由,不建议使用这个方法。但是短时间内浏览器不会在这个问题上后退处理。另外,这个方法无需添加额外的 class ,在做主题时比较实用。建议,在局部和无法添加 class a 的地方使用该方法清理浮动,但不要作为主要清理浮动方式。 overflow: auto; 还是不要用了。

4. 给浮动元素的容器添加浮动
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>给浮动元素的容器添加浮动</title>
    <style media="screen">
        .container {
            width: 500px;
            border: 1px solid red;
            float: left;
        }
        .item1 {
            width: 100px;
            height: 100px;
            background-color: blue;
            float: left;
        }
        .item2 {
            width: 100px;
            height: 100px;
            background-color: green;
            float: right;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="item1"></div>
        <div class="item2"></div>
    </div>
</body>
</html>
给浮动元素的容器添加浮动.png

给浮动元素的容器添加浮动属性也可清除内部浮动。但是这会对接下来的文档造成影响。
建议,在容器原本就浮动,或者容器使用了绝对定位时使用这个方法。不要在主要布局中使用。

5. 使用邻接元素清理
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用邻接元素清理</title>
    <style media="screen">
        .container {
            width: 500px;
            border: 1px solid red;
        }
        .item1 {
            width: 100px;
            height: 100px;
            background-color: blue;
            float: left;
        }
        .item2 {
            width: 100px;
            height: 100px;
            background-color: green;
            float: right;
        }
        .content {
            clear: both;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="item1"></div>
        <div class="item2"></div>
        <div class="content"></div>
    </div>
</body>
</html>
使用邻接元素清理.png

给浮动元素后面的元素添加 clear 属性。
要确保后面的元素与浮动元素同在一个容器(.container)内。
如果 .content 在 .container 后面,建议使用 :after 伪元素清理。

总结:

在网页主要布局中,使用 :after 伪元素作为主要清理浮动方式。
在小模块( ul )使用 overflow: hidden; (留意可能产生的隐藏溢出元素问题。
如果本身就是浮动元素则可自动清除内部浮动,无需额外处理。
正文中,使用邻接元素清理之前的浮动。

需要熟悉各种清理方式的原理和利弊。

拓展阅读:

清理浮动的那些事儿

6. 以下代码每一行的作用是什么?为什么会产生作用?和 BFC 撑开空间有什么区别?

.clearfix:after{
    content: '';
    display: block;
    clear: both;
}
.clearfix{
    *zoom: 1;
}
/* 这段代码用于普通浏览器清除浮动 */
.clearfix:after{  /* :after 伪元素清理浮动 */
    content: '';  /* 在后面添加一个“空”的内容 */
    display: block;  /* 设置这个“空”的内容为块级元素 */
    clear: both;  /* 这个”空“的内容左右两边不能有浮动元素 */
}

/* 用于 IE 浏览器清除浮动 */
.clearfix{  /* class 属性为 clearfix 的元素 */
    *zoom: 1;  /* 设置缩放比例为 1 ,这是 IE 专有属性。*/
}

第一段代码:在父容器后面加一个“空”元素,令这个“空”元素左右不能有浮动元素。然后这个“空”元素就会下移,这样就撑开了父元素。

第二段代码:zoom: 1; 缩放页面,重新排版,父元素重新计算浮动元素的高度。父容器就因此撑开了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260

推荐阅读更多精彩内容