zoukankan      html  css  js  c++  java
  • 对于BFC(block format context)理解

    前言

    什么是BFC?
    在解释 BFC 是什么之前,需要先介绍Box(块级,行级...)、FormattingContext的概念。

    Box: CSS布局的基本单位&盒模型

    盒模型--块级盒/行内盒

    一个盒包括了内容(content)、边(border)、内边距(padding)、外边距(margin)。下图展示了盒模型的直观意义:

    Image illustrating the relationship between content, padding, borders, and margins.

    盒的尺寸(width与height--计算得到的offsetWidth和offsetHeight)定义受到box-sizing属性的影响。box-sizing可选择content-box(默认)和border-box两种模式。分别代表两种盒子模型:W3c标准盒模型和IE盒子模型。ie8后开始支持通过CSS3属性box-sizing,让我们可以自由选择采用哪种盒子。

    w3c标准盒模型--块级盒

    width = content-width + padding-width + border-width
    height = content-height + padding-height + border-height
    
    IE盒子模型--块级盒

    width = content-width
    height = content-height
    
    行内盒

    1.width、height不起作用,盒子高度由内容决定(font-size/line-height)决定
    2.margin-top/margin-bottom/padding-top/padding-bottom不起作用

    小结:

    • 两类块级盒子可用过设置box-sizing转换。
    • 行内盒与块级盒转换可通过设置display属性来修改。下文将具体说明那些属性生成块级盒,哪些生成行内盒
    • 行内盒参与IFC布局,块级盒参与BFC布局,如果块级盒包含行内盒,但是由于BFC内只有块级盒参与,因此行内盒会被匿名块级盒包含。

    BOX

    Box 是 CSS 布局的对象和基本单位, 直观点来说,就是一个页面是由很多个 Box 组成的。元素的类型和 display 属性,决定了这个 Box 的类型。 不同类型的 Box, 会参与不同的 Formatting Context(一个决定如何渲染文档的容器),因此Box内的元素会以不同的方式渲染。让我们看看有哪些盒子:

    盒子 解释
    block-level box的display 属性为block, list-item, table 的元素,会生成 block-level box。并且参与(BFC)block fomatting context;
    inline-level box的display 属性为inline, inline-block, inline-table 的元素,会生成 inline-level box。并且参与 inline formatting context;
    run-in box css3 中才有, 这儿先不讲了。

    格式化上下文

    格式化上下文( formatting contexts )
    ├── 块级格式化上下文( Block formatting contexts )( BFC )
    ├── 行内格式化上下文( Inline formatting contexts ) ( IFC )
    ├── 自适应格式化上下文( Flex Formatting Contexts )( FFC )
    └── 网格布局格式化上下文( GridLayout Formatting Contexts )( GFC )

    有一类盒被称为块容器,它们能够包含块级盒。块容器要么创建BFC,这样它内部仅仅包含块级盒,要么创建一个IFC,这样它内部仅仅包含行内级元素。(也就是说,块容器中不可能既包含块级盒,又包含行内级盒,一旦他的子盒中有块级盒,所有行内级盒都会被自动创建匿名盒包裹)。

    在非块级格式化上下文中的块容器总是会创建新的BFC:如display为inline-blocks, table-cells, 和table-captions所生成的盒。而自身也在块级格式化上下文中的块容器,则只有overflow不为visible的情形下才会创建新的BFC。

    绝对定位和浮动的块容器则总是会创建新的块级格式化上下文。

    display值为table或者inline-table的元素将会生成表格(table),表格内部会使用特殊的格式化方式来排布其内部元素。

    display值为grid或者inline-grid的元素将会生成格元素(grid element),与table情形类似,它内部也是使用特殊的格式化方式来牌不其内部元素,

    display值为flex或者inline-flex的元素将会生成自适应容器(flex container),自适应容器在其内部产生自适应格式化上下文(flex formatting context)

    What's FC?
    FC的全称是:Formatting Contexts,是W3C CSS2.1规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。

    格式化上下文 定义 应用
    BFC BFC(Block Formatting Contexts)直译为"块级格式化上下文"。Block Formatting Contexts就是页面上的一个隔离的渲染区域,容器里面的子元素不会在布局上影响到外面的元素,反之也是如此。 如何产生BFC?float的值不为none。overflow的值不为visible。 position的值不为relative和static。display的值为table-cell, table-caption, inline-block中的任何一个。 那BFC一般有什么用呢?比如常见的多栏布局,结合块级别元素浮动,里面的元素则是在一个相对隔离的环境里运行。
    IFC IFC(Inline Formatting Contexts)直译为"内联格式化上下文",IFC的line box(线框)高度由其包含行内元素中最高的实际高度计算而来(不受到竖直方向的padding/margin影响).IFC中的line box一般左右都贴紧整个IFC,但是会因为float元素而扰乱。float元素会位于IFC与与line box之间,使得line box宽度缩短。 同个ifc下的多个line box高度会不同。 IFC中时不可能有块级元素的,当插入块级元素时(如p中插入div)会产生两个匿名块与div分隔开,即产生两个IFC,每个IFC对外表现为块级元素,与div垂直排列。 那么IFC一般有什么用呢?水平居中:当一个块要在环境中水平居中时,设置其为inline-block则会在外层产生IFC,通过text-align则可以使其水平居中。垂直居中:创建一个IFC,用其中一个元素撑开父元素的高度,然后设置其vertical-align:middle,其他行内元素则可以在此父元素下垂直居中。
    GFC GFC(GridLayout Formatting Contexts)直译为"网格布局格式化上下文",当为一个元素设置display值为grid的时候,此元素将会获得一个独立的渲染区域,我们可以通过在网格容器(grid container)上定义网格定义行(grid definition rows)和网格定义列(grid definition columns)属性各在网格项目(grid item)上定义网格行(grid row)和网格列(grid columns)为每一个网格项目(grid item)定义位置和空间。 那么GFC有什么用呢,和table又有什么区别呢?首先同样是一个二维的表格,但GridLayout会有更加丰富的属性来控制行列,控制对齐以及更为精细的渲染语义和控制。
    FFC FFC(Flex Formatting Contexts)直译为"自适应格式化上下文",display值为flex或者inline-flex的元素将会生成自适应容器(flex container),可惜这个牛逼的属性只有谷歌和火狐支持,不过在移动端也足够了,至少safari和chrome还是OK的,毕竟这俩在移动端才是王道。 Flex Box 由伸缩容器和伸缩项目组成。通过设置元素的 display 属性为 flex 或 inline-flex 可以得到一个伸缩容器。设置为 flex 的容器被渲染为一个块级元素,而设置为 inline-flex 的容器则渲染为一个行内元素。|伸缩容器中的每一个子元素都是一个伸缩项目。伸缩项目可以是任意数量的。伸缩容器外和伸缩项目内的一切元素都不受影响。简单地说,Flexbox 定义了伸缩容器内伸缩项目该如何布局。

    什么是BFC?(Block formatting contexts)

    w3c规范定义:

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

    BFC的通俗理解:

    首先BFC是一个名词,是一个独立的布局环境,我们可以理解为一个箱子(实际上是看不见摸不着的),箱子里面物品的摆放是不受外界的影响的。转换为BFC的理解则是:BFC中的元素的布局是不受外界的影响(我们往往利用这个特性来消除浮动元素对其非浮动的兄弟元素和其子元素带来的影响。)并且在一个BFC中,块盒与行盒(行盒由一行中所有的内联元素所组成,并非指一个行内元素就产生一个行盒)都会垂直的沿着其父元素的边框排列

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

    BFC布局规则:

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

    那些元素生成BFC

    1. 根元素
    2. float属性不为none
    3. position为absolute或fixed
    4. display为inline-block, table-cell, table-caption, flex, inline-flex
    5. overflow不为visible

    元素与盒

    在HTML中常常使用的概念是元素,而在CSS中,布局的基本单位是盒,盒总是矩形的。

    元素与盒并非一一对应的关系,一个元素可能生成多个盒,CSS规则中的伪元素也可能生成盒,display属性为none的元素则不生成盒。

    除了元素之外,HTML中的文本节点也可能会生成盒。

    正常流

    正常流是页面,大部分盒排布于正常流中。正常流中的盒必定位于某一格式化上下文中,正常流中有两种格式化上下文:块级格式化上下文(block formatting context,简称BFC)和行内格式化上下文(inline formatting context,IFC)。

    在块级格式化上下文中,盒呈纵向排布,在行内格式化上下文中,盒则呈横向排布。

    正常流根容器中是块级格式化上下文,不同的盒可能会在内部产生行内格式化上下文或者块级格式化上下文。

    块级与行内级

    正常流中的盒分为块级与行内级两种,任何一个行内级盒都不能够直接被放入块级格式化上下文中。如果有一个HTML元素生成了一个行内盒,而其所在的上下文是块级的话,那么应当为它生成一个匿名块级盒,匿名块级盒会在内部生成行内格式化上下文。

    元素的display属性会决定盒是行内级还是块级:

    • block, table, flex, grid, list-item 为块级
    • inline, inline-block, inline-table, inline-flex, inline-grid 为行内级

    产生垂直外边距合并的必备条件

    两个margin是邻接的必须满足以下条件:

    • 必须是处于常规文档流(非float和绝对定位)的块级盒子,并且处于同一个BFC当中。
    • 没有线盒,没有空隙(clearance,下面会讲到),没有padding和border将他们分隔开
    • 都属于垂直方向上相邻的外边距,可以是下面任意一种情况
      • 元素的margin-top与其第一个常规文档流的子元素的margin-top
      • 元素的margin-bottom与其下一个常规文档流的兄弟元素的margin-top
      • height为auto的元素的margin-bottom与其最后一个常规文档流的子元素的margin-bottom
      • 高度为0并且最小高度也为0,不包含常规文档流的子元素,并且自身没有建立新的BFC的元素的margin-top和margin-bottom

    最后来看张图慢慢领会

  • 相关阅读:
    检索 COM 类工厂中 CLSID 为 {00024500-0000-0000-C000-000000000046} 的组件失败,原因是出现以下错误: 80070005 拒绝访问。 (异常来自 HRESULT:0x80070005 (E_ACCESSDENIED))。
    SAP middb主键加索引
    【深入理解JVM】类加载器与双亲委派模型 (转)
    一千行MySQL学习笔记 (转)
    Spring框架是怎么解决Bean之间的循环依赖的 (转)
    一步一步带你入门MySQL中的索引和锁 (转)
    如何决定使用 HashMap 还是 TreeMap? (转)
    JVM 线上故障排查基本操作 (转)
    分布式、集群、微服务的区别
    可能是把 Java 内存区域讲的最清楚的一篇文章
  • 原文地址:https://www.cnblogs.com/hoboStage/p/5679349.html
Copyright © 2011-2022 走看看