深入了解CSS: CSS 与浏览器元素排列

349 阅读8分钟

参考文章:blog.csdn.net/jnshu_it/ar… 写一下自己在阅读文章时的一些理解 理解之后再用自己的话大概复述一次文章内容

层叠上下文

每个元素的位置都是三维的 在垂直于电脑屏幕的z轴上按照一定的顺序进行排列 所以元素之间有可能会发生层叠

而层叠上下文就是一个使用了特殊css的元素(也可能是根元素) 他就会包裹一些元素当做他的儿子 然后处理自己儿子的层叠关系 他兄弟元素的层叠他就管不着了 他和他的兄弟都归他的爸爸上下文管 而追溯到最祖先的层叠上下文就是html根元素

形成层叠上下文的方法有很多 常见的有以下几个:

  • 根元素
  • position
    • 值为 absolute|relative 且 z-index 值不为 auto
    • 值为 fixed|sticky
  • z-index 值不为 auto 的 flex 元素 即父元素属性 display:flex|inline-flex
  • opacity 属性值小于 1 的元素
  • transform 属性值不为 none 的元素
  • filter值不为none
  • perspective 值不为none
  • will-change 中指定了任意 CSS 属性 即便你没有直接指定这些属性的值
  • -webkit-overflow-scrolling 属性设置为 touch 的元素

层叠等级

层叠等级决定了在同一个层叠上下文中 元素在z轴上的排列顺序

需要注意的是一个普通的元素是不能突破爸爸上下文的控制 跑去和别人家的孩子做比较的 对于层叠等级的比较就只限于当前的上下文 只能是兄弟之间互相比较

层叠等级不一定就由z-index决定 只有定位元素的层叠等级才会被z-index影响 而其他元素对z-index免疫 而且层叠等级由层叠顺序、在html代码中出现的顺序、祖先元素的层叠等级一起决定

在html代码中出现的顺序就不用仔细说了 但是祖先元素的层叠等级很重要 要是元素A的爸爸等级比元素B的爸爸要低 那元素A不管怎么作 就算z-index设置到10000000000 都不可能被排列到元素B上面

详细讲一下层叠顺序

层叠顺序

  • 背景和边框:形成层叠上下文的元素的背景和边框
  • 负z-index值:层叠上下文内有着负z-index值的定位子元素 负的越大层叠等级越低
  • 块级盒:文档流中的块级、非定位子元素
  • 浮动盒:非定位浮动元素
  • 行内盒:文档流中行内、非定位子元素
  • z-index: 0: z-index 为 0 或 auto 的定位元素 这些元素形成了新的层叠上下文
  • 正z-index值:z-index 为正的定位元素正的越大层叠等级越高 这一层的元素会显示在之前顺序元素的上方 看起来像覆盖了更低级的元素

对于同一个层叠顺序的元素 按照在HTML里面出现的顺序依次层叠

文档流

常规流

在常规流中有三种排列方式 对应三种类型的元素

  • 行内元素横着排列
  • 块级元素竖着排列
  • 对于position为static和relative 而且不浮动的元素 会保留原本的位置
    • position为static就是默认值 排列方式就上面两种
    • position为relative 盒子的位置有left等四个方位属性来决定

浮动

浮动之后盒子会失去自己的高度 导致行内元素或块级元素都环绕在他周围

这里有一个小小的疑问 原文说道:浮动元素不会影响块级元素的布局 但是我觉得怪怪的..没看太懂 之前看了张鑫旭老师的博客 说浮动元素有"包裹性" 相当于变成了一个行内块元素 所以才影响了行内元素的布局 但是同时该元素又失去了自己的高度 所以后面的块元素也会跑上来挤掉他的位置

例如: 图中是一个列表 我们对第一个元素使用了浮动 然后后面的li元素也跑上来了

所以我认为浮动元素还是会影响块级元素的布局的 哪天要是被打脸了再偷偷改回来😊😊

绝对定位

这里说的绝对定位是元素的position为absolute或者是fixed的时候 这个时候盒子会从常规流中移除 (原文说不影响常规流的布局 我有点懵..意思应该是说不参与常规流的布局?)

对于absolute的元素会相对于上级的定位元素进行定位 而fixed会相对于浏览器窗口进行定位

BFC 块级格式化上下文

BFC是我们的页面中负责布局块级盒子一块渲染区域 他有一套渲染规则 能够决定其子元素如何布局 以及和其他元素之间的关系和作用 同时BFC任然属于文档中的普通流

BFC能够决定盒子的布局和浮动范围(行内盒子用IFC) 他的一个特征是内部的子元素不管怎么翻江倒海都不会影响到外部元素

BFC的范围

一个BFC的范围包含创建这个上下文的元素的所有子元素 但是不包括创建了新的BFC的子元素 也就是说如果元素A创建了一个BFC 他的儿子A_A也创建了BFC 那么元素A的BFC不包括A_A 但是包括所有没创建BFC的子元素A_B A_C...

这也就说明了一个元素不能同时存在于两个BFC中 BFC起到了一个隔离的作用

触发BFC的方式

  • 根元素
  • 浮动元素
  • overflow值不为visible的元素
  • display:inline-block | flex | inline-flex | grid | inline-grid | table-cell | table-caption | table | inlinetable
    • 其中table能够生成BFC的原因是table会生成一个匿名的table-cell
  • 定位元素 position:absolute | fixed
  • contain: layout | content | paint

BFC的三个特性

常见的用法有三个:

  1. 阻止相邻元素的margin合并
    同一个BFC下 两个相邻的块级元素外边距会发生折叠 如果想要避免外边距重叠 就可以把它们放在不同的BFC容器中去

    解决方法:
    可以给任意一个相邻的块级盒子外面包裹一个div 然后改变div的属性来形成新的BFC

  2. 阻止元素被浮动元素覆盖
    由于浮动元素实际上没有高度 (张鑫旭老师的博客提到过的) 因此一个正常的文档流的块级元素可能会被浮动元素覆盖

    面对这种情况 我们可以触发BFC 由于两个BFC的布局不会相互影响 就会被分割开来




    ----------
    根据规定,一个块级格式化上下文的边框不能和它里面的元素(文章里说是里面的元素 但我觉得应该是他外面的块级格式化上下文)的外边距重叠。这就意味着浏览器将会给块级格式化上下文创建隐式的外边距来阻止它和浮动元素的外边距叠加。由于这个原因,当给一个挨着浮动的块级格式化上下文添加负的外边距时将会不起作用。

    ---------- 引用自:那些年我们一起清除过的浮动

    通俗来讲就是说 BFC元素的边框不能和他外面的BFC元素的margin重叠 于是就自己用外边距挪挪挪 挪到挨着浮动元素的地方
    ps: 其实说是外面的块级格式化上下文也不太对 应该说是同一个父级BFC的BFC..

  3. 块级格式化上下文通常可以包含浮动
    闭合(清除)浮动 解决高度塌陷问题


    ----------
    建立块格式化上下文的元素的高度计算如下:
    绝对定位的子代将被忽略,而相对定位的框将被视为没有偏移。请注意,子框可能是一个匿名阻止框。
    此外,如果元素具有任何浮动后代,其后边缘的边缘低于元素的底部内容边缘,则高度会增加以包括这些边缘。仅考虑参与此块格式化上下文的浮点数,例如,绝对定位后代内的浮点数或其他浮点数均不考虑在内。

    ----------[引用自:视觉格式化模型详细信息]

    通俗来讲就是说 如果BFC里面有浮动元素 他就把自己的高度拉长拉长拉长 直到包含浮动元素

参考文章

  1. 对BFC的理解
  2. 那些年我们一起清除过的浮动