这篇文章主要介绍BFC和层叠上下文的相关知识点。

块格式化上下文(BFC)

一、BFC的定义
  BFC(块级格式化上下文 Block Formatting Context): 是一个独立的渲染区域,盒子内部元素的布局不会影响到盒子外部。它属于普通流

二、那些方式会创建块格式化上下文
  1) 根元素(<html>) body
  2) 浮动元素(元素的 float 不是 none)
  3) 绝对定位元素(元素的 position 为 absolute 或 fixed)
  4) 行内块元素(元素的 display 为 inline-block)
  5) overflow 值不为 visible 的块元素
  6) 弹性元素(display为 flex 或 inline-flex元素的直接子元素)
  7) 网格元素(display为 grid 或 inline-grid 元素的直接子元素)
  8) 表格单元格(元素的 display为 table-cell,HTML表格单元格默认为该值)
  9) 表格标题(元素的 display 为 table-caption,HTML表格标题默认为该值)
  10) 匿名表格单元格元素(元素的 display为 table、table-row、 table-row-group、table-header-group、table-footer-group(分别是HTML table、row、tbody、thead、tfoot的默认属性)或 inline-table)
  11) display 值为 flow-root 的元素
  12) contain 值为 layout、content或 paint 的元素
  13) 多列容器(元素的 column-count 或 column-width 不为 auto,包括 column-count 为 1)
  14) column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中(标准变更,Chrome bug)。

三、BFC特性及应用:
  1) 同一个BFC下外边距会发生折叠,若想避免外边距的折叠,可以将其放在不同的BFC容器中
  2) BFC可以包含浮动元素,也就是清除浮动
  3) BFC可以阻止元素被浮动元素覆盖,可以用来实现两栏自适应

四、普通流定义
  普通流: 就是元素按照其在HTML中的先后顺序自上而下布局,在这个过程中,行内元素水平排列,直到当行被占满然后换行,块级元素则会被渲染为完整的一个新行,除非另外指定,否则所有元素默认都是普通流定位,也可以说,普通流中元素的位置由该元素在 HTML 文档中的位置决定。

五、margin折叠规则
  外边距折叠: 块级元素的上外边距和下外边距有时会合并(或折叠)为一个外边距,其大小取其中的最大者。注意浮动元素绝对定位元素的外边距不会折叠。
  发生外边距折叠的三种基本情况:
    1) 相邻的两个元素之间的外边距会折叠(除非后一个元素需要清除之前的浮动)。
    2) 如果在父元素与其第一个子元素之间不存在边框、内边距、行内内容,也没有创建块格式化上下文、或者清除浮动将两者的 margin-top 分开;或者在父元素与其最后一个子元素之间不存在边框、内边距、行内内容、height、min-height、max-height将两者的 margin-bottom 分开,那么这两对外边距之间会产生折叠。此时子元素的外边距会“溢出”到父元素的外面。
    3) 如果一个块级元素中不包含任何内容,并且在其 margin-top 与 margin-bottom 之间没有边框、内边距、行内内容、height、min-height 将两者分开,则该元素的上下外边距会折叠。

参考链接:
  MDN上的BFC概念
  关于Block Formatting Context--BFC和IE的hasLayout
  10分钟理解BFC原理
  外边距重叠

层叠上下文

一、定义
  层叠上下文: 假定用户正面向(浏览器)视窗或网页,而 HTML 元素沿着其相对于用户的一条虚构的 z 轴排开,层叠上下文就是对这些 HTML 元素的一个三维构想。众 HTML 元素基于其元素属性按照优先级顺序占据这个空间。默认情况下,网页内容是没有偏移角的垂直视觉呈现,当内容发生层叠的时候,一定会有一个前后的层叠顺序产生。所有的元素都有层叠水平,文档根元素会创建层叠上下文。普通元素的层叠水平优先由层叠上下文决定,因此,层叠水平的比较只有在当前层叠上下文元素中才有意义。

二、折叠顺序
桌面.png
    图片侵权删
  CSS的层叠顺序(从低到高): 层叠上下文元素的background/border(装饰属性) -> 负z-index -> block块状水平盒子(布局) -> float浮动盒子(布局) -> inline/inline-block水平盒子(内容) -> z-index:auto或看成z-index:0或者不依赖z-index的层叠上下文 -> 正z-index
  注:z-index:0实际上和z-index:auto单纯从层叠水平上看,是可以看成是一样的。注意这里的措辞——“单纯从层叠水平上看”,实际上,两者在层叠上下文领域有着根本性的差异。z-index不为0时,position值为absolute和relative以及flex的项目z-index不为0时才能够产生层叠上下文。

三、折叠规则和特征
  层叠规则:
    1) 在同一个层叠上下文领域,层叠水平大的覆盖小的
    2) 当元素层叠水平一致、层叠顺序相同的时候,在DOM流中处于后面的元素会覆盖前面的元素
  层叠上下文元素的特征:
    1) 层叠上下文的层叠水平要比普通元素高
    2) 层叠上下文可以阻断元素的混合模式
    3) 层叠上下文可以嵌套,内部层叠上下文及其所有子元素均受制于外部的层叠上下文
    4) 每个层叠上下文和兄弟元素独立,也就是当进行更改过层叠变化或渲染的时候,只需要考虑后代元素
    5) 每个层叠上下文是自成体系的,当元素发生层叠的时候,整个元素被认为是在父层叠上下文的层叠顺序中

四、如何创建层叠上下文:
  1) 文档根元素(<HTML>);
  2) position 值为 absolute(绝对定位)或 relative(相对定位)且 z-index 值不为 auto 的元素;
  3) position 值为 fixed(固定定位)或 sticky(粘滞定位)的元素(沾滞定位适配所有移动设备上的浏览器,但老的桌面浏览器不支持);
  4) flex (flexbox) 容器的子元素,且子元素的 z-index 值不为 auto;
  5) grid (grid) 容器的子元素,且 z-index 值不为 auto;
  6) opacity 属性值小于 1 的元素。opacity的值不为1时,层叠顺序是z-index:auto级别,跟没有值的absolute绝对定位元素是平起平坐的;
  7) mix-blend-mode 属性值不为 normal 的元素;
  8) 以下任意属性值不为 none 的元素:
    a. transform
    b. filter
    c. perspective
    d. clip-path
    e. mask / mask-image / mask-border
  9) isolation 属性值为 isolate 的元素;
  10) -webkit-overflow-scrolling 属性值为 touch 的元素;
  11) will-change 值设定了任一属性而该属性在 non-initial 值时会创建层叠上下文的元素
  12) contain 属性值为 layout、paint 或包含它们其中之一的合成值(比如 contain: strict、contain: content)的元素。
例:

<!-- html -->
<div class="wrap">
    <div class="box">
        <img src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1575261998206&di=575862b8836db6fbf9b81b76b8e0aa47&imgtype=0&src=http%3A%2F%2Fimg8.zol.com.cn%2Fbbs%2Fupload%2F19571%2F19570481.jpg"
            alt="">
    </div>
</div>
/* style */
    /* 1.文档根元素下,创建层叠上下文,那怕z-index为负,也会显示在背景色之上 */
    body {
        background: yellow;
    }
    .box {
        position: relative;
        z-index: -1;
    }

/* 2.利用定位生成CSS层叠上下文,如果去掉wrap的定位或z-index就会导致图片跑到背景下面 */
    .wrap {
        position: relative;
        z-index: 0;
        width: 300px;
        height: 300px;
        background-color: yellowgreen;
    }
    .box {
        position: relative;
        z-index: -1;
    }
    img {
        width: 200px;
    }
/* 3.利用父元素flex和子元素z-index不为auto来使子元素生成层叠上下文 */
    .wrap {
        display: inline-flex;
        width: 300px;
        height: 300px;
    }
    .box {
        z-index: 0;  /* 此处生效 */ 
        background-color: yellowgreen;
    }
    img {
        position: relative;
        z-index: -1;
        width: 200px;
    }
/* 4.利用opacity不为1生成层叠上下文 */
    .wrap {
        width: 300px;
        height: 300px;
    }
    .box {
        opacity: .5;
        background-color: yellowgreen;
    }
    img {
        position: relative;
        z-index: -1;
        width: 200px;
    }
    

五、为什么inlin-block和inline的层叠顺序比浮动元素和块级元素都高?
  因为float和块级元素一般都作布局,内联元素都是内容。而一个网页中最重要的就是内容,所以一定要让内容的层叠顺序相当高,这样可以在发生层叠时,重要的图片、文字内容可以优先暴露在屏幕上。
参考来源: MDN层叠上下文
张鑫旭CSS层叠上下文

以上内容如有不对,希望大家指出,谢谢。


雨夜望月
207 声望13 粉丝