核心概念和知识
CSS全称Cascading Style Sheets,中文翻译为样式层叠表。是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言
CSS 规则
CSS 的核心功能是将 CSS 属性设定为特定的值。一个属性与值的键值对被称为声明:
color: red;
用{}包裹的成为声明块:
{
color: red;
text-align: center;
}
声明块如果需要作用到对应的 HTML 元素,那还需要加上选择器。选择器和声明块组成了CSS 规则集(CSS ruleset),常简称为 CSS 规则。
.box {
color: red;
text-align: center;
}
CSS注释
CSS支持单行和多行注释:
/* 单行注释 */
/*
多行
注释
*/
CSS @规则
CSS有时需要导入其它外部样式表,字体,此时就需要@规则这样的语句。CSS 里有以下常用 @规则:
- @font-face:指定一个用于显示文本的自定义字体
- @keyframes:描述 CSS 动画的关键帧。
- @supports: 用于查询特定的 CSS 是否生效
- @media:如果满足媒体查询的条件则条件规则组里的规则生效。
- @import: 导入一个外部样式表。
@font-face
@font-face {
font-family: "iconfont";
src: url('iconfont.ttf') format('truetype'),
url('iconfont.woff2') format("woff2"),
}
@keyframes
@keyframes slidein {
from {
transform: translateX(0%);
}
to {
transform: translateX(100%);
}
}
@keyframes identifier {
0% { top: 0; left: 0; }
30% { top: 50px; }
68%, 72% { left: 50px; }
100% { top: 100px; left: 100%; }
}
@supports
@supports (display: grid) {
div {
display: grid;
}
}
@media
@media 规则可置于你代码的顶层或位于其他任何@ 条件规则组:
@media screen and (min-width: 900px) {
article {
padding: 1rem 3rem;
}
}
@supports (display: flex) {
@media screen and (min-width: 900px) {
article {
display: flex;
}
}
}
媒体类型
- all:适用于所有设备;
- print:适用于在打印预览模式下在屏幕上查看的分页材料和文档;
- screen:主要用于屏幕;
- speech:主要用于语音合成器。
逻辑操作符
- and:查询条件都满足的时候才生效;
- not:查询条件取反;
- only:整个查询匹配的时候才生效,常用语兼容旧浏览器,使用时候必须指定媒体类型;
- 逗号或者 or:查询条件满足一项即可匹配;
媒体功能
根据属性判断当前使用 css 所在的设备,或是浏览环境的具体特征。表达式是可选的,它负责判断这些特性或特征是否存在、值为多少。每条媒体特性表达式都必须用括号括起来。 常用媒体功能:
height输出设备中的页面可见区域高度。width输出设备中的页面可见区域宽度。max-aspect-ratio输出设备的屏幕可见宽度与高度的最大比率。max-device-aspect-ratio输出设备的屏幕可见宽度与高度的最大比率。max-device-height输出设备的屏幕可见的最大高度。max-device-width输出设备的屏幕最大可见宽度。max-height输出设备中的页面最大可见区域高度。max-width输出设备中的页面最大可见区域宽度。min-height输出设备中的页面最小可见区域高度。min-width输出设备中的页面最小可见区域宽度。
如下样式限制为:带有屏幕的设备,宽度至少为 30 em的横向的设备:
@media screen and (min-width: 30em) and (orientation: landscape) { ... }
在媒体查询 4 级规范可以这样写:
@media (30em <= width <= 50em ) { ... }
@import
link 和 @import 都能导入一个样式文件,它们有什么区别吗?
- link 是 HTML 标签,除了能导入 CSS 外,还能导入别的资源,比如图片、脚本和字体等;而 @import 是 CSS 的语法,只能用来导入 CSS
- link 导入的样式会在页面加载时同时加载,@import 导入的样式需等页面加载完成后再加载
选择器
基本选择器
通用选择器
选择所有元素。(可选)可以将其限制为特定的名称空间或所有名称空间。
语法: * ns|* *|*
例子: * 将匹配文档的所有元素。
元素选择器
按照给定的节点名称,选择所有匹配的元素。
语法: elementname
例子: input 匹配任何 <input> 元素。
类选择器
按照给定的 class 属性的值,选择所有匹配的元素。
语法: .classname
例子: .box 匹配任何 class 属性中含有 "box" 类的元素。
ID选择器
按照 id 属性选择一个与之匹配的元素。需要注意的是,一个文档中,每个 ID 属性都应当是唯一的。
语法: #idname
例子: #app 匹配 ID 为 "app" 的元素。
属性选择器
语法::
[attr]:指定属性的元素[attr=val]:属性等于指定值的元素[attr*=val]:属性包含指定值的元素[attr^=val]:属性以指定值开头的元素[attr$=val]:属性以指定值结尾的元素[attr~=val]:属性包含指定值(完整单词)的元素[attr|=val]:属性以指定值(完整单词)开头的元素
分组选择器
选择器列表
, 是将不同的选择器组合在一起的方法,它选择所有能被列表中的任意一个选择器选中的节点。
语法: A, B
示例: div, span 会同时匹配 <span> 元素和<div>。
组合器
- 后代组合器:
A B - 直接后代选择器:
A > B - 一般兄弟组合器:
A ~ B - 紧邻兄弟选择器:
A + B
后代组合器
“ ”(空格)组合器选择前一个元素的后代节点。
语法: A B
例子: div span 匹配所有位于任意 <div> 元素之内的 <span> 元素。
直接后代选择器
> 组合器选择前一个元素的直接子代的节点。
语法: A > B
例子: ul > li 匹配直接嵌套在 <ul> 元素内的所有<li> 元素。
一般兄弟组合器
~ 组合器选择兄弟元素,也就是说,后一个节点在前一个节点后面的任意位置,并且共享同一个父节点。
语法: A ~ B
例子: p ~ span 匹配同一父元素下,<p> 元素后的所有 <span> 元素。
紧邻兄弟选择器
+ 组合器选择相邻元素,即后一个元素紧跟在前一个之后,并且共享同一个父节点。
语法: A + B
例子: h2 + p 会匹配紧邻在 h2元素后的第一个 <p> 元素。
伪选择器(Pseudo)
伪类
条件伪类
:lang():基于元素语言来匹配页面元素:dir():匹配特定文字书写方向的元素:has():匹配包含指定元素的元素:is():匹配指定选择器列表里的元素:not():用来匹配不符合一组选择器的元素
行为伪类
:active:鼠标激活的元素:hover: 鼠标悬浮的元素::selection:鼠标选中的元素
状态伪类
:target:当前锚点的元素:link:未访问的链接元素:visited:已访问的链接元素:focus:输入聚焦的表单元素:required:输入必填的表单元素:valid:输入合法的表单元素:invalid:输入非法的表单元素:in-range:输入范围以内的表单元素:out-of-range:输入范围以外的表单元素:checked:选项选中的表单元素:optional:选项可选的表单元素:enabled:事件启用的表单元素:disabled:事件禁用的表单元素:read-only:只读的表单元素:read-write:可读可写的表单元素:blank:输入为空的表单元素:current():浏览中的元素:past():已浏览的元素:future():未浏览的元素
结构伪类
:root:文档的根元素:empty:无子元素的元素:first-letter:元素的首字母:nth-child:元素的首行:nth-child(n):元素中指定顺序索引的元素:nth-last-child(n):元素中指定逆序索引的元素:first-child:元素中为首的元素:last-child:元素中为尾的元素:only-child:父元素仅有该元素的元素:nth-of-type(n):标签中指定顺序索引的标签:nth-last-of-type(n):标签中指定逆序索引的标签:first-of-type:标签中为首的标签:last-of-type:标签中为尾标签:only-of-type:父元素仅有该标签的标签
伪元素
::before:在元素前插入内容::after:在元素后插入内容
优先级
!important- 内联样式
- ID 选择器
- 类选择器、伪类选择器、属性选择器
- 元素选择器、伪元素选择器
- 通配选择器、后代选择器、兄弟选择器:对优先级没有影响
继承性
存在默认继承行为的属性,分为下面几类:
- 字体相关:
font-family、font-style、font-size、font-weight等 - 文本相关:
text-align、text-indent、text-decoration、text-shadow、letter-spacing、word-spacing、white-space、line-height、color等 - 列表相关:
list-style、list-style-image、list-style-type、list-style-position等 - 其他属性:
visibility、cursor等
文档流
文档流的概念
在 CSS 的世界中,会把内容按照从左到右、从上到下的顺序进行排列显示。正常情况下会把页面分割成一行一行的显示,而每行又可能由多列组成,所以从视觉上看起来就是从上到下从左到右,而这就是 CSS 中的流式布局,又叫文档流。文档流就像水一样,能够自适应所在的容器,一般它有如下几个特性:
- 块级元素默认会占满整行,所以多个块级盒子之间是从上到下排列的;
- 内联元素默认会在一行里一列一列的排布,当一行放不下的时候,会自动切换到下一行继续按照列排布;
脱离文档流
脱流文档流指节点脱流正常文档流后,在正常文档流中的其他节点将忽略该节点并填补其原先空间。文档一旦脱流,计算其父节点高度时不会将其高度纳入,脱流节点不占据空间。有两种方式可以让元素脱离文档流:浮动和定位。
- 使用浮动(float)会将元素脱离文档流,移动到容器左/右侧边界或者是另一个浮动元素旁边,该浮动元素之前占用的空间将被别的元素填补,另外浮动之后所占用的区域不会和别的元素之间发生重叠;
- 使用绝对定位(
position: absolute;)或者固定定位(position: fixed;)也会使得元素脱离文档流,且空出来的位置将自动被后续节点填补。
盒模型
在 CSS 中任何元素都可以看成是一个盒子,而一个盒子是由 4 部分组成的:内容(content)、内边距(padding)、边框(border)和外边距(margin)。
盒模型有 2 种:标准盒模型和 IE 盒模型,本别是由 W3C 和 IExplore 制定的标准:
- 标准盒模型:盒子的实际尺寸 = 内容(设置的宽/高) + 内边距 + 边框
- IE 盒模型:盒子的实际尺寸 = 设置的宽/高 = 内容 + 内边距 + 边框
现在高版本的浏览器基本上默认都是使用标准盒模型,而像 IE6 这种老古董才是默认使用 IE 盒模型的。
在 CSS3 中新增了一个属性 box-sizing,允许开发者来指定盒子使用什么标准,它有 2 个值:
content-box:标准盒模型border-box:IE 盒模型
块级盒子、内联盒子
块级盒子(display: block)
- 在内联的方向上扩展并占据父容器在该方向上的所有可用空间。
- 每个盒子都会换行。
width和height属性可以发挥作用。padding,margin和border会将其他元素从当前盒子周围“推开”。
默认属于块级盒子的元素主要有:
div、p、ol、ul、li、h1-h6,form、table、hr、option,以及h5新增的header, section, footer, aside, nav, main, article, figure
内联盒子(display:inline)
- 盒子不会产生换行。
width和height属性将不起作用。- 垂直方向的
padding,margin和border会被应用但是不会把其他处于inline状态的盒子推开。 - 水平方向的
padding,margin和border会被应用且会把其他处于inline状态的盒子推开。
默认属于内联盒子的元素主要有:
span、a、lable、img、strong、b、i、sub、sup
介于两者之间的盒子(display:inline-block)
padding、margin、width、height有效, 默认宽度是内容本身的宽度- 不能自动换行
- 默认从左到右排列 (但是之间会有空白缝隙--HTML 中的换行符、空格符、制表符等合并为空白符,字体大小不为 0 的情况下,空白符自然占据一定的宽度,使用inline-block 会产生了元素间的空隙)
默认的有:
button、input、textarea、select
格式化上下文
不同类型的盒子有不同格式化上下文,有下面 4 类:
- BFC (Block Formatting Context) 块级格式化上下文;
- IFC (Inline Formatting Context) 行内格式化上下文;
- FFC (Flex Formatting Context) 弹性格式化上下文;
- GFC (Grid Formatting Context) 格栅格式化上下文;
BFC
BFC(Block Formatting Context) 块级格式化上下文,它是一个独立的渲染区域,具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素。
BFC的约束规则
- 内部的盒子会在垂直方向,一个接一个地放置
- 垂直方向上的距离由margin决定,属于同一个BFC的两个相邻Box的margin会发生重叠(塌陷)
- 每个元素的左外边距与包含块的左边界相接触(从左向右),即使浮动元素也是如此。
- BFC 的区域不会与 float 盒子重叠
- 计算BFC的高度时,浮动子元素也参与计算
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面元素,反之亦然
如何触发BFC
- 根元素:html
- overflow: 除了 visible 以外的值 (hidden、auto、scroll)
- 浮动元素:float 除 none 以外的值
- 定位:position 为 absolute 或 fixed
- display: inline-block/table-cell/table-caption/flex/inline-flex/grid/inline-grid
BFC 应用
1. 防止margin重叠(塌陷)
<div class="container">
<div class="box"></div>
<div class="wrapper">
<div class="box"></div>
</div>
</div>
.wrapper {
/** 触发 BFC */
overflow: hidden;
}
.box {
height: 100px;
width: 100px;
background-color: #f00;
margin: 20px;
}
2. 清除内部浮动
浮动造成的问题就是父元素高度坍塌,根据上诉BFC的约束规则:计算BFC的高度时,浮动子元素也参与计算, 只要触发父元素的 BFC 即可。
<div class="container">
<div class="box"></div>
</div>
.container {
background-color: #ccc;
/** 触发 BFC */
overflow: auto;
}
.box {
height: 100px;
width: 100px;
background-color: #f00;
margin: 20px;
float: left;
}
3. 自适应两栏布局
根据上述BFC的约束规则:BFC 的区域不会与 float 盒子重叠,对侧边栏固定宽度且左浮动,而对右侧内容触发 BFC,使得它的宽度自适应该行剩余宽度。
<div class="layout">
<div class="aside"></div>
<div class="main"></div>
</div>
.layout {
background-color: #ccc;
}
.aside {
height: 100px;
width: 100px;
background-color: #f00;
float: left;
}
.main {
height: 100px;
background-color: #00f;
/** 触发BFC */
overflow: hidden;
}
IFC
如何触发IFC?
- 块级元素中仅包含内联级别元素
形成条件非常简单,需要注意的是当IFC中有块级元素插入时,会产生两个匿名块将父元素分割开来,产生两个IFC。
IFC约束规则
- 在一个IFC内,子元素是水平方向横向排列的,并且垂直方向起点为元素顶部。
- 子元素只会计算横向样式空间,【padding、border、margin】,垂直方向样式空间不会被计算,【padding、border、margin】。
- 在垂直方向上,子元素会以不同形式来对齐(vertical-align)
- 能把在一行上的框都完全包含进去的一个矩形区域,被称为该行的行框(line box)。行框的宽度是由包含块(containing box)和与其中的浮动来决定。
- IFC中的
line box一般左右边贴紧其包含块,但float元素会优先排列。 - IFC中的
line box高度由 CSS 行高计算规则来确定,同个IFC下的多个line box高度可能会不同。 - 当
inline boxes的总宽度少于包含它们的line box时,其水平渲染规则由text-align属性值来决定。 - 当一个
inline box超过父元素的宽度时,它会被分割成多个boxes,这些boxes分布在多个line box中。如果子元素未设置强制换行的情况下,inline box将不可被分割,将会溢出父元素。
层叠上下文
层叠上下文(stacking context),是HTML中一个三维的概念。在CSS2.1规范中,每个盒模型的位置是三维的,分别是平面画布上的X轴,Y轴以及表示层叠的Z轴。一般情况下,元素在页面上沿X轴Y轴平铺,我们察觉不到它们在Z轴上的层叠关系。而一旦元素发生堆叠,这时就能发现某个元素可能覆盖了另一个元素或者被另一个元素覆盖。
如果一个元素含有层叠上下文,我们可以理解为这个元素在z轴上就“高人一等”。
那如何产生层叠上下文:参考MDN
- html 文档根元素
- 声明 position: absolute/relative 且 z-index 值不为 auto 的元素;
- 声明 position: fixed/sticky 的元素;
- flex 容器的子元素,且 z-index 值不为 auto;
- grid 容器的子元素,且 z-index 值不为 auto;
- opacity 属性值小于 1 的元素;
- mix-blend-mode 属性值不为 normal 的元素;
- 以下任意属性值不为 none 的元素:
- transform
- filter
- perspective
- clip-path
- mask / mask-image / mask-border
- isolation 属性值为 isolate 的元素;
- -webkit-overflow-scrolling 属性值为 touch 的元素;
- will-change 值设定了任一属性而该属性在 non-initial 值时会创建层叠上下文的元素;
- contain 属性值为 layout、paint 或包含它们其中之一的合成值(比如 contain: strict、contain: content)的元素。
层叠等级
层叠等级(stacking leve)指节点在三维空间 Z 轴上的上下顺序。它分两种情况:
- 在同一个层叠上下文中,它描述定义的是该层叠上下文中的层叠上下文元素在 Z 轴上的上下顺序;
- 在其他普通元素中,它描述定义的是这些普通元素在 Z 轴上的上下顺序; 普通节点的层叠等级优先由其所在的层叠上下文决定,层叠等级的比较只有在当前层叠上下文中才有意义,脱离当前层叠上下文的比较就变得无意义了。
层叠顺序
在同一个层叠上下文中如果有多个元素,那么他们之间的层叠顺序是怎么样的呢?
越往下层叠优先级越高,视觉上的效果就是越容易被用户看到。
CSS属性值的计算过程
某个元素从所有属性没有值,到所有CSS属性都有值的过程
- 确定声明值
- 层叠
- 继承
- 使用默认值
层叠的比较
-
比较重要性:
- 带有important的作者样式
- 带有important的默认样式
- 作者样式
- 默认样式
-
比较特殊性
| style | id | 属性 | 元素 |
|---|---|---|---|
| 内联:1 否则:0 | id选择器数量 | 属性、元素、伪类的数量 | 元素,伪元素的数量 |
- 比较源次序: 源码中靠后的覆盖靠前的