选择器
基础选择器
- 标签选择器:
h2
- 类选择器:
.checked
- ID 选择器:
#picker
- 通配选择器:
*
属性选择器
[attr]
:指定属性的元素[attr=val]
:属性等于指定值的元素[attr*=val]
:属性包含指定值的元素[attr^=val]
:属性以指定值开头的元素[attr$=val]
:属性以指定值结尾的元素[attr~=val]
:属性包含指定值(完整单词)的元素(不推荐使用)[attr|=val]
:属性以指定值(完整单词)开头的元素(不推荐使用)
组合选择器
- 相邻兄弟选择器:
A + B
- 普通兄弟选择器:
A ~ B
- 子选择器:
A > B
- 后代选择器:
A B
伪类
条件伪类
: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
:元素的首字母:first-line
:元素的首行: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
等
默认不继承的属性也可以设置下面的值控制继承行为:
inherit
:继承父元素对应属性的计算值initial
:应用该属性的默认值,比如color
的默认值是#000
unset
:如果属性是默认可以继承的,则取inherit
的效果,否则同initial
revert
:效果等同于unset
,兼容性差
文档流
CSS 文档流的排列方式:
- 块级元素默认会占满整行,多个块级盒子之间是从上到下排列的
- 内联元素默认会在一行里一列一列的排布,当一行放不下的时候,会自动切换到下一行继续按照列排布
脱离文档流
节点脱流正常文档流后,在正常文档流中的其他节点将忽略该节点并填补其原先空间。文档一旦脱流,计算其父节点高度时不会将其高度纳入,脱流节点不占据空间。有两种方式可以让元素脱离文档流:浮动和定位。
- 使用浮动(
float
)会将元素脱离文档流,移动到容器左/右侧边界或者是另一个浮动元素旁边,该浮动元素之前占用的空间将被别的元素填补,另外浮动之后所占用的区域不会和别的元素之间发生重叠 - 使用绝对定位(
position: absolute;
)或者固定定位(position: fixed;
)也会使得元素脱离文档流,且空出来的位置将自动被后续节点填补
盒模型
在 CSS 中任何元素都可以看成是一个盒子,而一个盒子是由 4 部分组成的:内容(content)、内边距(padding)、边框(border)和外边距(margin)。
两种盒模型:标准盒模型和 IE 盒模型
- 标准盒模型:盒子的实际尺寸 = 内容(设置的宽/高) + 内边距 + 边框
- IE 盒模型:盒子的实际尺寸 = 设置的宽/高 = 内容 + 内边距 + 边框
使用 CSS3 的 box-sizing
属性可以切换浏览器的盒模型:
content-box
:标准盒模型border-box
:IE 盒模型
视觉格式化模型
视觉格式化模型(Visual formatting model)是用来处理和在视觉媒体上显示文档时使用的计算规则。CSS 中一切皆盒子,而视觉格式化模型简单来理解就是规定这些盒子应该怎么样放置到页面中去,这个模型在计算的时候会依赖到很多的因素,比如:盒子尺寸、盒子类型、定位方案(是浮动还是定位)、兄弟元素或者子元素以及一些别的因素。
盒子类型由 display
决定,同时给一个元素设置 display
后,将会决定这个盒子的 2 个显示类型(display type):
- outer display type(对外显示):决定了该元素本身是如何布局的,即参与何种格式化上下文
- inner display type(对内显示):其实就相当于把该元素当成了容器,规定了其内部子元素是如何布局的,参与何种格式化上下文
outer display type
对外显示方面,盒子类型可以分成 2 类:block-level box(块级盒子) 和 inline-level box(行内级盒子)。
- 块级盒子:
display
为block
、list-item
、table
、flex
、grid
、flow-root
等 - 行内级盒子:
display
为inline
、inline-block
、inline-table
等
所有块级盒子都会参与 BFC,呈现垂直排列;而所有行内级盒子都参会 IFC,呈现水平排列。
block
- 占满一行,默认继承父元素的宽度;多个块元素将从上到下进行排列
- 设置 width/height 将会生效
- 设置 padding 和 margin 将会生效
inline
- 不会占满一行,宽度随着内容而变化;多个 inline 元素将按照从左到右的顺序在一行里排列显示,如果一行显示不下,则自动换行
- 设置 width/height 将不会生效
- 设置竖直方向上的 padding 和 margin 将不会生效
inline-block
- 是行内块元素,不单独占满一行,可以看成是能够在一行里进行左右排列的块元素
- 设置 width/height 将会生效
- 设置 padding 和 margin 将会生效
inner display type
对内方面,其实就是把元素当成了容器,里面包裹着文本或者其他子元素。container box 的类型依据 display 的值不同,分为 4 种:
- block container:建立 BFC 或者 IFC
- flex container:建立 FFC
- grid container:建立 GFC
- ruby container
格式化上下文
四种主要的格式化上下文:
- BFC (Block Formatting Context) 块级格式化上下文
- IFC (Inline Formatting Context) 行内格式化上下文
- FFC (Flex Formatting Context) 弹性格式化上下文
- GFC (Grid Formatting Context) 格栅格式化上下文
BFC
块格式化上下文,它是一个独立的渲染区域,只有块级盒子参与,它规定了内部的块级盒子如何布局,并且与这个区域外部毫不相干。
BFC 渲染规则
- 内部的盒子会在垂直方向,一个接一个地放置
- 盒子垂直方向的距离由 margin 决定,属于同一个 BFC 的两个相邻盒子的 margin 会发生重叠
- 每个元素的 margin 的左边,与包含块 border 的左边相接触(对于从左往右的格式化,否则相反),即使存在浮动也是如此
- BFC 的区域不会与 float 盒子重叠
- BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此
- 计算 BFC 的高度时,浮动元素也参与计算
如何创建 BFC
- 根元素:html
- 非溢出的可见元素:
overflow
不为visible
- 设置浮动:
float
属性不为none
- 设置定位:
position
为absolute
或fixed
- 定义成块级的非块级元素:
display
:inline-block
/table-cell
/table-caption
/flex
/inline-flex
/grid
/inline-grid
BFC 应用场景
- 清除内部浮动(父元素 overflow)
- 防止垂直 margin 合并(包裹一层并设置 overflow)
- 自适应两栏布局 (float + overflow)
IFC
IFC 块级元素中仅包含内联级别元素,当 IFC 中有块级元素插入时,会产生两个匿名块将父元素分割开并产生两个 IFC。
IFC 渲染规则
- 子元素在水平方向上一个接一个排列,在垂直方向上将以容器顶部开始向下排列
- 节点无法声明宽高,其中
margin
和padding
在水平方向有效在垂直方向无效 - 节点在垂直方向上以不同形式对齐
- 能把在一行上的框都完全包含进去的一个矩形区域,被称为该行的线盒(line box)。线盒的宽度是由包含块(containing box)和与其中的浮动来决定
- IFC 中的 line box 一般左右边贴紧其包含块,但 float 元素会优先排列
- IFC 中的 line box 高度由
line-height
计算规则来确定,同个 IFC 下的多个 line box 高度可能会不同 - 当内联级盒子的总宽度少于包含它们的 line box 时,其水平渲染规则由
text-align
属性值来决定 - 当一个内联盒子超过父元素的宽度时,它会被分割成多盒子,这些盒子分布在多个 line box 中。如果子元素未设置强制换行的情况下,inline box 将不可被分割,将会溢出父元素
IFC 应用场景
- 水平居中:当一个块要在环境中水平居中时,设置其为
inline-block
则会在外层产生 IFC,通过text-align
则可以使其水平居中 - 垂直居中:创建一个 IFC, 使用其中一个元素撑开父元素的高度,然后设置
vertical-align: middle
, 其他行内原素可以在此父元素下垂直居中
层叠上下文
会产生层叠上下文 (stacking context) 的元素:
<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
、strict
或content
层叠等级
层叠等级指节点在三维空间 Z 轴上的上下顺序。它分两种情况:
- 在同一个层叠上下文中,它描述定义的是该层叠上下文中的层叠上下文元素在 Z 轴上的上下顺序;
- 在其他普通元素中,它描述定义的是这些普通元素在 Z 轴上的上下顺序;
普通节点的层叠等级优先由其所在的层叠上下文决定,层叠等级的比较只有在当前层叠上下文中才意义,脱离当前层叠上下文的比较就变得无意义了。
层叠顺序
同一个层叠上下文中的层叠优先级如下表所示,越靠下优先级越低
z-index > 0
的子节点z-index: auto/0
的子节点- 标准流内行内非定位的子节点
- 浮动非定位的子节点
- 标准流内块级非定位的子节点
z-index < 0
的子节点- 层叠上下文的
border
和background
如何比较两个元素的层叠等级?
- 在同一个层叠上下文中,比较两个元素就是按照上面的层叠顺序进行比较
- 如果不在同一个层叠上下文中的时候,那就需要比较两个元素分别所处的层叠上下文的等级
- 如果都在同一个层叠上下文,且层叠顺序相同,则在 HTML 中定义越后面的层叠等级越高
单位
设备像素(Device Pixels)
设备屏幕的物理像素,表示屏幕有多少像素点。
设备像素比(DPR)
设备像素比表示 1 个 CSS 像素等于几个物理像素。
计算公式:DPR = 物理像素数 / 逻辑像素数;
在浏览器中可以通过 window.devicePixelRatio
来获取当前屏幕的 DPR。
像素密度(DPI/PPI)
像素密度也叫显示密度或者屏幕密度,缩写为 DPI(Dots Per Inch) 或者 PPI(Pixel Per Inch)。从技术角度说,PPI 只存在于计算机显示领域,而 DPI 只出现于打印或印刷领域。
计算公式: PPI = 屏幕对角线的像素尺寸 / 物理尺寸
设备独立像素(DIP)
DIP 是特别针对 Android 设备而衍生出来的,原因是安卓屏幕的尺寸繁多,因此为了显示能尽量和设备无关,而提出的这个概念。它是基于屏幕密度而计算的,认为当屏幕密度是 160 的时候,px = DIP。
计算公式: dip = px * 160 / dpi
px
px 表示的是 CSS 中的像素,在 CSS 中它是绝对的长度单位,也是最基础的单位,其他长度单位会自动被浏览器换算成 px。但是对于设备而言,它其实又是相对的长度单位,比如宽高都为 2px,在正常的屏幕下,其实就是 4 个像素点,而在设备像素比 (devicePixelRatio) 为 2 的 Retina 屏幕下,它就有 16 个像素点。
em
em 是相对长度单位,在 font-size
中使用是相对于父元素的 font-size
大小,比如父元素 font-size: 16px
,当给子元素指定 font-size: 2em
的时候,经过计算后它的字体大小会是 32px. 在其他属性中使用是相对于自身的字体大小,如 width
/ height
/ padding
/ margin
等。
rem
rem 也是一个相对长度单位,不过 rem 相对的是 HTML 的根元素的 font-size
来计算,所以通常用于自适应网站或者 H5 中。
vw / vh
vw 和 vh 分别是相对于屏幕视口宽度和高度而言的长度单位:
1vw
= 视口宽度均分成 100 份中 1 份的长度100vw = window.innerWidth
1vh
= 视口高度均分成 100 份中 1 份的长度100vh = window.innerHeight
相对视口的单位,除了 vw/vh 外,还有 vmin 和 vmax:
vmin
:取vw
和vh
中值较小的vmax
:取vw
和vh
中值较大的
媒体查询
媒体查询是指针对不同的设备、特定的设备特征或者参数进行定制化的修改网站的样式。
你可以通过给 <link>
加上 media 属性来指定该样式文件只能对什么设备生效:
all
:适用于所有设备print
:适用于在打印预览模式下在屏幕上查看的分页材料和文档screen
:主要用于屏幕speech
:主要用于语音合成器
不指定的话默认是 all,即对所有设备都生效:
<link rel="stylesheet" src="styles.css" media="screen" />
<link rel="stylesheet" src="styles.css" media="print" />
通过 media 指定的资源尽管不匹配它的设备类型,但是浏览器依然会加载它。
除了通过 <link>
让指定设备生效外,还可以通过 @media
让 CSS 规则在特定的条件下才能生效。响应式页面就是使用了 @media
才让一个页面能够同时适配 PC、Pad 和手机端。
/* 用户设备的最小高度为 680px 或为纵向模式的屏幕设备 */
@media (min-height: 680px),
screen and (orientation: portrait) {}
媒体查询支持的逻辑操作符:
and
:查询条件都满足的时候才生效,
或者or
:查询条件满足一项即可匹配not
:查询条件取反only
:整个查询匹配的时候才生效,常用语兼容旧浏览器,使用时候必须指定媒体类型
变量
< !-- 定义变量 -->:root {
--theme-color: red;
}
< !-- 使用变量 -->h1 {
color: var(--theme-color);
}
@ 规则
CSS 中的 @ 规则如下:
@namespace
: 告诉 CSS 引擎必须考虑 XML 命名空间@media
: 如果满足媒体查询的条件则条件规则组里的规则生效@page
: 描述打印文档时布局的变化@font-face
: 描述将下载的外部的字体@keyframes
: 描述 CSS 动画的关键帧@document
: 如果文档样式表满足给定条件则条件规则组里的规则生效(推延至 CSS Level 4 规范)@charset
指定样式表使用的字符集。它必须是样式表中的第一个元素@import
: 用于告诉 CSS 引擎引入一个外部样式表@supports
: 用于查询特定的 CSS 是否生效,可以结合 not、and 和 or 操作符进行后续的操作
/* 如果支持自定义属性,则把 body 颜色设置为变量 varName 指定的颜色 */
@supports (--foo: green) {
body {
color: var(--varName);
}
}
如果样式表中没有 @charset
规则,那么浏览器将按下面的顺序推样式表的编码:
- 文件开头的 BOM 值
- HTTP 响应头里的
content-type
字段包含的charset
所指定的值 - CSS 文件头里定义的
@charset
规则里指定的字符编码 <link>
标签里的charset
属性,该条已在 HTML5 中废除- 默认是 UTF-8。
<link>
和 @import
的区别:
- link 是 HTML 标签,除了能导入 CSS 外,还能导入别的资源,比如图片、脚本和字体等;而
@import
是 CSS 的语法,只能用来导入 CSS - link 导入的样式会在页面加载时同时加载,
@import
导入的样式需等页面加载完成后再加载 - link 没有兼容性问题,
@import
不兼容 ie5 以下 - link 可以通过 JS 操作 DOM 动态引入样式表改变样式,
@import
不可以