1
0
mirror of https://github.com/Daotin/Web.git synced 2024-10-29 20:14:46 +08:00
Web-main/#HTML-CSS阶段经验总结/03-BFC的概念,清除浮动.md
2018-10-30 11:06:25 +08:00

8.8 KiB
Raw Blame History

BFC的概念及案例

BFC的概念

BFC(Block formatting context)直译为“块级格式化上下文”。它是一个独立的渲染区域只有Block-level box参与 它规定了内部的Block-level Box如何布局并且与这个区域外部毫不相干。

BFC的布局规则

  • 内部的Box会在垂直方向一个接一个地放置。
  • Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
  • 每个元素的margin box的左边 与包含块border box的左边相接触
  • BFC的区域不会与float box重叠。
  • BFC就是页面上的一个隔离的独立容器容器里面的子元素不会影响到外面的元素。
  • 计算BFC的高度时浮动元素也参与计算所以会清除浮动。

哪些元素或属性能触发BFC

  • 根元素 html
  • float属性不为none
  • position为absolute或fixed
  • display为inline-block, table-cell, table-caption, flex, inline-flex
  • overflow不为visible

案例一:两栏布局

要求:左边固定宽度,右边宽度可变。

方式一:

思路左边固定宽度浮动右边不设置宽度设置margin-left空出左边的宽度。

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .dv1 {
            width: 200px;
            height: 500px;
            background-color: pink;
            float: left;
        }

        .dv2 {
            margin-left: 200px;
            height: 500px;
            background-color: peru;
        }
    </style>
</head>

<body>
    <div class="dv1"></div>
    <div class="dv2"></div>
</body>

</html>

方式二:

思路BFC的区域不会与float box重叠。所以将右边设置为BFC区域。

这里是有 absolute 绝对定位。

body {
	position: relative;
}

.dv1 {
  width: 200px;
  height: 500px;
  background-color: pink;
  float: left;
}

.dv2 {
  height: 500px;
  background-color: peru;
  position: absolute;
  left: 200px;
  right: 0;
}

注意:右边一定要加 right:0;

方式三:

思路:使用 overflow不为visible 将右边设置为BFC区域。

.dv1 {
  width: 200px;
  height: 500px;
  background-color: pink;
  float: left;
}

.dv2 {
  height: 500px;
  background-color: peru;
  overflow: hidden;
}

案例二:三栏布局

要求:左边固定宽度,右边固定宽度,中间宽度自适应。

方案一:

思路:使用两栏布局的方案一

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .dv1 {
            width: 200px;
            height: 500px;
            background-color: pink;
            float: left;
        }

        .dv2 {
            height: 500px;
            background-color: peru;
            margin-left: 200px;
            margin-right: 200px;
        }

        .dv3 {
            width: 200px;
            height: 500px;
            background-color: pink;
            float: right;
        }
    </style>
</head>

<body>
    <div class="dv1"></div>
    <div class="dv2"></div>
    <div class="dv3"></div>
</body>

</html>

可以看到 dv3 掉了下来???

为什么呢因为dv2是块级元素单独占一行所以dv3只能显示在下一行。

怎么办呢我们将dv2和dv3的顺序调换一下就好了

<div class="dv1"></div>
<div class="dv3"></div>
<div class="dv2"></div>

方案二:

思路:使用两栏布局的方案二

body {
  position: relative;
}

.dv1 {
  width: 200px;
  height: 500px;
  background-color: pink;
  float: left;
}

.dv2 {
  height: 500px;
  background-color: peru;
  position: absolute;
  left: 200px;
  right: 200px;
}

.dv3 {
  width: 200px;
  height: 500px;
  background-color: pink;
  float: right;
}

方案三:

思路:使用两栏布局的方案三

.dv1 {
  width: 200px;
  height: 500px;
  background-color: pink;
  float: left;
}

.dv2 {
  height: 500px;
  background-color: peru;
  overflow: hidden;
}

.dv3 {
  width: 200px;
  height: 500px;
  background-color: pink;
  float: right;
}

结果也是dv3 被挤了下来。调换dv2和dv3的顺序即可。

方案四:

思路:使用弹性布局

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        body {
            display: flex;
        }

        .dv1 {
            width: 200px;
            height: 500px;
            background-color: pink;
        }

        .dv2 {
            width: 100%;
            height: 500px;
            background-color: red;
            flex: 1;
        }

        .dv3 {
            width: 200px;
            height: 500px;
            background-color: pink;
        }
    </style>
</head>

<body>
    <div class="dv1"></div>
    <div class="dv2"></div>
    <div class="dv3"></div>
</body>

</html>

案例三解决父元素与子元素之间的margin-top问题

原文链接:https://www.cnblogs.com/ranyonsue/p/5461749.html

问题描述

父元素的盒子包含一个子元素盒子给子元素盒子一个垂直外边距margin-top的时候父元素盒子也会往下走margin-top的值而子元素和父元素的边距则没有发生变化如下图

源代码:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    body,
    html {
      padding: 0;
      margin: 0;
    }

    .parent {
      width: 200px;
      height: 200px;
      background-color: #aaa;
    }

    .children {
      width: 100px;
      height: 100px;
      background-color: yellow;
      margin-top: 50px;
    }
  </style>
</head>

<body>
  <div class="parent">
    <div class="children"></div>
  </div>
</body>

</html>

原文分析

官方介绍:

In this specification, the expression collapsing margins means that adjoining margins (no non-empty content, padding or border areas or clearance separate them) of two or more boxes (which may be next to one another or nested) combine to form a single margin.

所有毗邻的两个或更多盒元素的margin将会合并为一个margin共享之。

毗邻的定义为同级或者嵌套的盒元素并且它们之间没有非空内容、Padding或Border分隔。

这就是原因了。“嵌套”的盒元素也算“毗邻”,也会 Collapsing Margins。这个合并Margin其实很常见就是文章段落元素<p/>并列很多个的时候每一个都有上下1em的margin但相邻的<p/>之间只会显示1em的间隔而不是相加的2em。

解决办法

这个问题的避免方法很多,只要破坏它出现的条件就行。给 Outer Div 加上 padding/border或者给 Outer Div / Inner Div 设置为 float/position:absolute(CSS2.1规定浮动元素和绝对定位元素不参与Margin折叠)。

1、修改父元素的高度增加 padding-top 样式模拟padding-top1px常用

2、为父元素添加 overflow: hidden样式即可完美

3、为父元素或者子元素声明浮动floatleft可用

4、为父元素添加 border-topborder-top: 1px solid transparent; 可用) 

5、为父元素或者子元素声明绝对定位 。

案例四:清除浮动

来自笔记CSS/03-链接伪类、背景、行高、盒子模型、浮动

清除浮动不是不用浮动,清除浮动产生的问题。

问题:当父盒子没有定义高度,嵌套的盒子浮动之后,下边的元素发生位置错误(占据父盒子的位置)。

方法一

**额外标签法:**在最后一个浮动元素后添加标签。

clear: left  |  right  | both  /*用的最多的是clear:both;*/

方法二

给浮动元素的父集元素使用overflow:hidden;

注意:如果有内容出了盒子,不能使用这个方法。

方法三(推荐使用)

伪元素清除浮动。

: after 相当于在当前盒子后加了一个盒子。

清除浮动总结:

  1. 给父元素高度,缺点:高度无法自适应
  2. 父元素加 overflow:hidden; 缺点:超出会被隐藏
  3. 父元素加定位absolute/fixed缺点脱离文档流。
  4. 父元素加浮动,缺点:可能父元素的父元素继续塌陷
  5. 父元素加inline-block缺点行内块的缺点。
  6. 浮动元素的最后加一个额外标签标签使用clear:both; 缺点:结果冗余
  7. 万能清除法,伪元素清除浮动。
content: ".";
display: block;
height: 0;
visibility: hidden;
clear:both;
overflow: hidden;