理解CSS
CSS 全名 Cascading Style Sheet,也就是层叠样式表,是第一个具有层叠概念的语言。我们所说的 CSS3 都是指代 CSS2.1 之后的 CSS 内容。
层叠的意思是一个元素的样式按照一种层叠规则应用样式,也就是对于同种修饰,元素会应用优先级更高的样式。
样式层叠优先级(递减)
- 用户代理样式表 - 浏览器默认样式
- 用户样式表 - 很少用
- 作者样式表 - 开发者编写的内容
- 作者样式表使用了 !important
- 用户样式表使用了 !important
- 用户代理样式表使用了 !important
选择器优先级 / specificity 特异性(递减)
- (O 类别,不属于选择器,放在这里方便比较)内联样式
- (A 类别)id 选择器
- (B 类别)class 选择器 = 属性选择器 = 伪类选择器 ( pseudo-class )
- (C 类别)标签选择器 = 伪元素选择器 ( pseudo-element )
样式优先级判断示例:
ul li.green
优先级 = A: 0 + B: 1 + C: 2,其标记(A, B, C)为 (0, 1, 2)
没有 #xxx 这样的 id 选择器,有一个 class 选择器和两个标签选择器 ( ul 和 li )
div :is(p, #card)
补充::is() 本身没有优先级,以其参数中优先级最高的为准,:where 的优先级为 0
优先级 = A: 1 + B: 0 + C: 1,其标记(A, B, C)为 (1, 0, 1)
:is() 中 id 选择器 #card 优先级比标签选择器 p 优先级更高,所以 :is(p, #card) 属于一个 A 类别,还有一个 div 属于标签选择器属于 C 类别。
.class.class VS .class
前者优先级 = A: 0 + B: 2 + C: 0,其标记(A, B, C)为 (0, 2, 0)
后者优先级 = A: 0 + B: 1 + C: 0,其标记(A, B, C)为 (0, 1, 0)
所以该元素会应用 .class.class 中所编写的样式
标记(A, B, C)是为了方便我们判断为同一个元素添加的样式中,哪一个会被应用在元素上
这里有一张表可以帮助更好的理解这个规则:specifishity.com/specifishit…
也推荐阅读这些内容:
juejin.cn/post/710386… 一篇 CSS 优先级的博客
developer.mozilla.org/zh-CN/docs/… CSS优先级 - MDN
源码位置也会影响优先级
“The last declaration in document wins.” 文档最后声明的样式胜出。
- 对于通过 @import 引入的样式,按照 @import 的顺序
- 对于 link 和 style 标签的样式,根据在 document 中的顺序决定。
盒模型
浏览器根据视觉格式化模型 ( visual formatting modal ) 将所有元素表示为盒子模型,CSS 通过盒子模型做 layout。
W3C 标准盒模型(content-box)
"在标准模型中,如果你给盒设置 width 和 height,实际设置的是内容部分。padding 和 border 再加上设置的宽高一起决定整个盒子的大小。"
例如,其总宽度 = 内容宽 + 左 padding + 右 padding + 左 border + 右 border(没有 margin 计算在内)
替代(IE)盒模型
IE5.x 和 IE6 有自己的非标准盒模型,例如,其总宽度 = 设置的宽度。也就是说 width 设置了多少,实际宽就是多少,并且已经包含了 border 和 padding 在内,那么实际的内容 content 的宽度就是总宽度 - 左 padding - 右 padding - 左 border - 右 border。
我们可以通过 box-sizing 的 content-box 和 border-box 来切换这两个模型(后者是 IE 盒模型)
常规流布局
任意盒子都有内外显示类型,外部显示类型(display-outside)决定了该盒子如何与同一格式化上下文中的元素一起显示,而内部显示类型(display-inside)规定了该盒子内部的布局方式,
例子:
display: flex 外部会显示为 block,参与块级格式化上下文(BFC),而 display: inline-flex 外部会显示为 inline,参与内联格式化上下文。但这两个属性内部都参与弹性布局。
BFC
也就是 block formatting context(块级格式化上下文)。其布局规范是:“在一个块级格式区域中,盒子会从包含块的顶部开始,按顺序垂直排列。同级盒子间的垂直距离会由 margin 属性决定。相邻两个块级盒子之间的垂直间距会遵循外边距折叠原则被折叠。 在一个块格式区域中,每个盒子的左外边缘与包含块左边缘重合”
我们平时说的 BFC 是一个盒子是 BFC 或者具有 BFC 特性,此时 BFC 表示 block formatting context root。不管外部表示类型是什么,其内部表示是 flex-root,也就是说这个盒子内部形成了一个新的块级格式化上下文。
触发一个盒子 BFC 特性的条件:
- display: flow-root | inline-block
- position: absolute | fixed
- float 不为 none
- overflow 不为 visible
外边距塌陷
这些情况会导致外边距塌陷:
- 两个兄弟元素之间相邻的上下外边距
- 父子元素之间相邻的上下外边距
- 内容为空元素自己上下外边距相邻
解决办法:
- 在相邻元素上下之间增加 border、padding 或者 内联元素,使得它们不再相邻
- 在父子元素重叠时,可以设置父元素为 BFC,使父子在不同的块级格式化上下文中
IFC
“在内联格式区域中,盒子会从包含块的顶部开始。按序水平排列。只有水平外边距、边框和内边距会被保留。这些盒子可以以不同方式在垂直方向上对齐,可以底部对齐或顶部对齐,或者按照文字底部对齐。我们把包含一串盒子的矩形区域称为一个线条框 ( line-box ) ”
line-box 的高度是最高元素的顶部到最低元素的底部。
相关的应用是通过设置字体的 line-height 为其包裹元素的 height 使得文字垂直居中,以及为了使得图片和文字水平居中对齐,设置图片 vertical-align: middle 的同时设置图片的父亲元素 font-size 为 0。(这是因为图片设置 vertical-align: middle 使得图片在 baseline 水平基线的基础上上移了半个 x 字母的高度,设置其父元素字体大小为 0 可以使图片水平中线和文字基线对齐)
Position 定位
relative
元素相对于原来在文档流的基础上移动
absolute
元素被移除文档流,其原本的位置不存在了,相对于最近的非 static 定位祖先元素进行定位
fixed
元素被移除文档流,元素相对于屏幕视口进行定位,屏幕滚动不会改变其位置。
sticky
元素相对于它最近滚动祖先(祖先的 overflow 是 scoll/hidden/auto)的视口 ( scrollport ) 进行移动。
层叠上下文(The stacking context)
层叠上下文是对HTML元素的三维构想,将元素沿着垂直屏幕的虚构 z 轴排开。 形成新的层叠上下文的条件:
- position: relative 或 absolute 并且 z-index 不是 auto
- position: fixed 或 sticky
- flex 或 grid 的子元素;并且 z-index 不是 auto
- opacity 的值小于 1
- transform的值不为 none
- will-change 的值不为通用值
- ... 见规范