CSS 选择器的优先级
内联样式 > ID 选择器 > 类选择器、属性选择器和伪类选择器(:hover,:first-child,:after 之类) > 标签(类型)选择器和伪元素选择器(::after,::first-letter,::selection等等)
CSS2用的是:after,而CSS3用的是::after。
相同则比较数量每一级的数量总和。
当出现优先级相等的情况时,最晚出现的样式规则会被采纳。
重置(resetting)CSS 和 标准化(normalizing)CSS 的区别
- 重置(Resetting): 重置意味着除去所有的浏览器默认样式。对于页面所有的元素,像
margin、padding、font-size这些样式全部置成一样。你将必须重新定义各种元素的样式。 - 标准化(Normalizing): 标准化没有去掉所有的默认样式,而是保留了有用的一部分,同时还纠正了一些常见错误。
Float 定位
浮动(float)是 CSS 定位属性。浮动元素从网页的正常流动中移出,但是保持了部分的流动性,会影响其他元素的定位(比如文字会围绕着浮动元素)。这一点与绝对定位不同,绝对定位的元素完全从文档流中脱离。
文字所在的行框并不会忽略已经脱离文档流的
float元素,甚至会调整自己的行框宽度,给其让出空间,表现形式就是文字充满float元素的周围
CSS 的 clear 属性通过使用 left、right、both,让该元素向下移动(清除浮动)到浮动元素下面。
如果父元素只包含浮动元素,那么该父元素的高度将塌缩为 0。我们可以通过清除(clear)从浮动元素后到父元素关闭前之间的浮动来修复这个问题。一般方法是给父元素一个 clearfix 的类,内容如下:
1 | .clearfix::after { |
值得一提的是,把父元素属性设置为 overflow: auto 或 overflow: hidden,会使其内部的子元素形成块格式化上下文(Block Formatting Context),并且父元素会扩张自己,使其能够包围它的子元素。
z-index
CSS 中的 z-index 属性控制重叠元素的垂直叠加顺序。z-index 只能影响 position 值不是 static 的元素。
没有定义 z-index 的值时,元素按照它们出现在 DOM 中的顺序堆叠(层级越低,出现位置越靠上)。非静态定位的元素(及其子元素)将始终覆盖静态定位(static)的元素,而不管 HTML 层次结构如何。
层叠上下文元素有如下特性:
- 层叠上下文的层叠水平要比普通元素高;
- 层叠上下文可以阻断元素的混合模式;
- 层叠上下文可以嵌套,内部层叠上下文及其所有子元素均受制于外部的层叠上下文。
- 每个层叠上下文和兄弟元素独立,也就是当进行层叠变化或渲染的时候,只需要考虑后代元素。
- 每个层叠上下文是自成体系的,当元素发生层叠的时候,整个元素被认为是在父层叠上下文的层叠顺序中。
普通元素的层叠水平优先由层叠上下文决定,因此,层叠水平的比较只有在当前层叠上下文元素中才有意义。
层叠顺序:

层叠上下文的创建:
- 页面根元素
- 对于包含有
position:relative/position:absolute/position:fixed/position:sticky的定位元素,且z-index不是auto z-index值不为auto的flex项(父元素display:flex|inline-flex),是flex布局的子元素- 元素的
opacity值不是 1 - 元素的
transform值不是none - 元素
mix-blend-mode值不是normal - 元素的
filter值不是none - 元素的
isolation值是isolate will-change指定的属性值为上面任意一个- 元素的
-webkit-overflow-scrolling设为touch
具体的一些比较可查看 深入理解 CSS 中的层叠上下文和层叠顺序
格式化上下文(Block Formatting Context)
一个 HTML 盒(Box)满足以下任意一条,会创建块格式化上下文:
float的值不是none.position的值不是static或relative.display的值是table-cell、table-caption、inline-block、flex、或inline-flex。overflow的值不是visible。
BFC 特性:
- 内部的
Box会在垂直方向,从顶部开始一个接一个地放置。 Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生叠加。(用来解决边距叠加问题,给会重叠的元素加一个BFC的父元素,那么这个BFC块就不会和下一个元素的边距重叠了,水平方向的margin是不会叠加的)- 每个元素的
margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。 BFC的区域不会与float box叠加,就算这个float box不是和它同级的。(解决布局问题,一个块元素与浮动块重叠了的问题)BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然。- 计算
BFC的高度时,浮动元素也参与计算。(经常用来解决浮动元素导致父元素坍塌的问题)
不同浏览器的样式兼容性问题
- 在确定问题原因和有问题的浏览器后,使用单独的样式表,仅供出现问题的浏览器加载。这种方法需要使用服务器端渲染。
- 使用已经处理好此类问题的库,比如
Bootstrap。 - 使用
autoprefixer自动生成CSS属性前缀。(webpack打包工具可使用postcss来完成) - 使用
Reset.css或Normalize.css。
如何为功能受限的浏览器提供页面
- 优雅的降级:为现代浏览器构建应用,同时确保它在旧版浏览器中正常运行。
- 渐进式增强:构建基于用户体验的应用,但在浏览器支持时添加新增功能。
- 利用 caniuse.com 检查特性支持。
- 使用
autoprefixer自动生成CSS属性前缀。 - 使用 Modernizr 进行特性检测。
用 CSS 隐藏页面元素
opacity设为 0。visibility设为hidden。display设为none。position设为absolute,然后移动到不可见区域,left: -99999px。width: 0; height: 0; overflow: hidden:使元素不占用屏幕上的任何空间,导致不显示它。text-indent: -9999px:这只适用于block元素中的文本。clip(clip-path):rect()/inset()/polygon(),注意只对position值为absolute或fixed的元素有效。transform: scale(0,0)。- 利用
z-index来隐藏。
媒体查询
1 | <!-- link元素中的CSS媒体查询 --> |
and 关键字用于合并多个媒体属性或合并媒体属性与媒体类型。
媒体查询中使用逗号分隔效果等同于 or 逻辑操作符。
not 关键字应用于整个媒体查询,在媒体查询为假时返回真
更多的设置查看 CSS 媒体查询
解释浏览器如何确定哪些元素与 CSS 选择器匹配
浏览器从最右边的选择器(关键选择器)根据关键选择器,浏览器从 DOM 中筛选出元素,然后向上遍历被选元素的父元素,判断是否匹配。选择器匹配语句链越短,浏览器的匹配速度越快。
例如,对于形如 p span 的选择器,浏览器首先找到所有 <span> 元素,并遍历它的父元素直到根元素以找到 <p> 元素。对于特定的 <span>,只要找到一个 <p>,就知道已经匹配并停止继续匹配
box-sizing
改变计算元素 height 与 width 的方法。
元素默认应用了 box-sizing: content-box,元素的宽高只会决定内容(content)的大小。
box-sizing: border-box 改变计算元素 width 和 height 的方式,border 和 padding 的大小也将计算在内。
block、inline 与 inline-block 区别
| block | inline-block | inline | |
|---|---|---|---|
| 大小 | 填充其父容器的宽度。 | 取决于内容。 | 取决于内容。 |
| 定位 | 从新的一行开始,并且不允许旁边有 HTML 元素(除非是float) |
与其他内容一起流动,并允许旁边有其他元素。 | 与其他内容一起流动,并允许旁边有其他元素。 |
能否设置 width 和 height |
能 | 能 | 不能。设置会被忽略。 |
可以使用 vertical-align 对齐 |
不可以 | 可以 | 可以 |
边距(margin)和填充(padding) |
各个方向都存在 | 各个方向都存在 | 只有水平方向存在。垂直方向会被忽略。 尽管 border 和 padding 在 content 周围,但垂直方向上的空间取决于’line-height’ |
浮动(float) |
- | - | 就像一个 block 元素,可以设置垂直边距和填充。 |
relative、fixed、absolute 和 static
经过定位的元素,其 position 属性值必然是 relative、absolute、fixed 或 sticky。
static:默认定位属性值。该关键字指定元素使用正常的布局行为,即元素在文档常规流中当前的布局位置。此时top,right,bottom,left和z-index属性无效。relative:该关键字下,元素先放置在未添加定位时的位置,再在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白)。absolute:不为元素预留空间,通过指定元素相对于最近的非static定位祖先元素的偏移,来确定元素位置。绝对定位的元素可以设置外边距(margins),且不会与其他边距合并。fixed:不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。打印时,元素会出现在的每页的固定位置。fixed属性会创建新的层叠上下文。当元素祖先的transform属性非none时,容器由视口改为该祖先。sticky:盒位置根据正常流计算(这称为正常流动中的位置),然后相对于该元素在流中的flow root(BFC)和containing block(最近的块级祖先元素)定位。在所有情况下(即便被定位元素为table时),该元素定位均不对后续元素造成影响。当元素 B 被粘性定位时,后续元素的位置仍按照 B 未定位时的位置来确定。position: sticky对table元素的效果与position: relative相同。须指定top,right,bottom或left四个阈值其中之一,才可使粘性定位生效。否则其行为与相对定位相同。
详情以及例子可查看 position。
响应式设计与自适应设计不同
用一张图片来描述更合适:
上面是响应式设计,下面是自适应设计 
响应式设计和自适应设计都以提高不同设备间的用户体验为目标,根据视窗大小、分辨率、使用环境和控制方式等参数进行优化调整。
响应式设计的适应性原则:网站应该凭借一份代码,在各种设备上都有良好的显示和使用效果。响应式网站通过使用媒体查询,自适应栅格和响应式图片,基于多种因素进行变化,创造出优良的用户体验。就像一个球通过膨胀和收缩,来适应不同大小的篮圈。
自适应设计更像是渐进式增强的现代解释。与响应式设计单一地去适配不同,自适应设计通过检测设备和其他特征,从早已定义好的一系列视窗大小和其他特性中,选出最恰当的功能和布局。与使用一个球去穿过各种的篮筐不同,自适应设计允许使用多个球,然后根据不同的篮筐大小,去选择最合适的一个。
视网膜分辨率处理
使用媒体查询,像 @media only screen and (min-device-pixel-ratio: 2) { ... },然后改变 background-image。
对于图标类的图形,尽可能使用 svg 和图标字体,因为它们在任何分辨率下,都能被渲染得十分清晰。
还有一种方法是,在检查了 window.devicePixelRatio 的值后,利用 JavaScript 将 <img> 的 src 属性修改,用更高分辨率的版本进行替换。注意:IE 和 FireFox 是不支持 devicePixelRatio 属性的。
translate vs postion absolute
translate(x, y) 是 transform 的一个值。改变 transform 或 opacity 不会触发浏览器重新布局(reflow)或重绘(repaint),只会触发组合(composite)。而改变绝对定位会触发重新布局,进而触发重绘和复合。因此 translate() 更高效,可以缩短平滑动画的绘制时间。
当使用 translate() 时,元素仍然占据其原始空间(有点像 position:relative),这与改变绝对定位不同。
translate3d vs translate
只有 Z 轴上的变化才会产生新的合成层,Z 轴上设置 0 也是可以的,同时也会启用 GPU 加速,使用 GPU 来渲染该层。
也就是说 translate3d 才会触发 GPU 加速,二维的 translate 是不会的。同理,rotate3d 与 rotate,scale3d 与 scale 等等也都是一样的,3d 会启用 GPU 加速。
但是需要注意的是,虽然 2d 不会触发 GUP 硬件加速也就是增加新的合成层,但是它和 3d 一样能跳过浏览器渲染的 Layout 和 Paint 步骤,而直接到 Composite(合成) 步骤,实际上是新增了一层渲染层,所以一定程度上渲染性能也有提升。渲染步骤:JS -> Style -> Layout -> Paint -> Composite,关于 CSS 属性会触发哪个步骤可以查看 CSS Triggers。
先有的渲染层才有合成层。
关于合成层与渲染层、GPU 硬件加速可以看 无线性能优化:Composite。
GPU是使用浮点数运算的,故而如果对文字加速可能会导致文字模糊,故而慎用!启动GPU加速自然也会加大电能的消耗,所以只在必要的时候再启用。
如何查看是否多了一层合成层(注意不是渲染层),可以使用
Chrome的Devtools来查看,选中更多种的Rendering选项,下面就有几个属性了:
Paint flashing:需要重绘的部分会高亮显示。Layer borders:显示层的边界,可以用来查看是否启用了GPU加速。FPS meter:启用FPS计量,可以在右上角看到当前页面的刷新帧率。Scrolling performance issues:会高亮可能影响滚动性能的元素。Emulate CSS media:强制使用打印或普通屏效果。
更加详细的信息可以通过Layers来查看,还会告诉你产生合成层的原因。以前的Chrome版本还可以在Timeline中看到每一帧的合成层情况,现在被移动到Performance中了,需要点击到某一个具体帧,再show layers才能出现Layers的选项卡。
垂直水平居中
水平居中
- 行内元素居中
行内元素居中是只针对行内元素的,比如文本(text)、图片(img)、按钮等行内元素,可通过给父元素设置text-align:center来实现。 - 块状元素居中
定宽块状元素居中:设置“左右 margin”值为“auto”来实现居中。
不定宽块状元素居中:a.dispaly:table再设置“左右 margin”为”auto”。b.position: relative; left: 50%; transform: tranlateX(-50%)。 - 通用:
flex布局。
垂直居中
- 父元素高度确定,且子元素只有单行文本
设置子元素的line-height等于父元素的height值。 - 父元素高度确定,子元素有多行
设置父元素dispaly:table-cell,再设置父元素的vertical-align:middle。 - 绝对定位 +
translate:position: absolute; top: 50%; transform: translateY(-50%)。 - 绝对定位 +
margin: auto:子元素设置position: absolute,把要垂直居中的元素相对于父元素绝对定位,top和bottom设为相等的值,再设置margin: 0 auto。 padding: 父元素没有高度,且只有一个子元素,那么设置父元素上下padding相等就可以了。flex布局。vertical-align: 让行内元素在块级元素中垂直居中可以使用vertical-align:middle来近似居中,如果需要绝对居中同时需要设置父元素的font-size为 0。
vertical-align注意事项:默认情况图片是与父元素的基线对齐的,基线可以认为是英文 4 行线的第 3 行线,解决图片下方空白问题可以设置对齐方式除baseline之外的值,或者设置line-height或font-size为 0。字符有下沉特性(字符的中心比块的绝对中心稍微下移),进行居中对齐时需要注意,居中元素的中线会与文字中线对齐,所以会稍微下移。
一个没有内容的
inline-block元素的基线是margin边的下边缘(是包含了margin空间的)。
直接使用 vertical-align:middle 来居中(父元素不设置行高或者字体大小)的问题可以看下面这张图:

vertical-align的值查看 我对 css-vertical-align 的一些理解与认识(一)
长宽比固定
- 垂直方向的
padding
高度设置为 0,然后padding-top或者padding-bottom设置百分比(这个百分比是宽度的百分比)来达到长宽比固定的效果,不过子元素需要绝对定位,不然会被padding挤出容器外。 - 视窗单位
CSS新特性中提供了一种新的单位vw。了解过这个单位的同学都知道,浏览器100vw表示的就是浏览器的视窗宽度(Viewport)。那么只要宽高设置好比例的vw就可以了。 grid布局
不常用。
强制同步布局
将一帧送到屏幕会采用如下顺序:
JavaScript -> Style -> Layout -> Paint -> Composite
首先 JavaScript 运行,然后计算样式,然后布局。但是,可以使用 JavaScript 强制浏览器提前执行布局。这被称为强制同步布局。
典型的情况就是,在读操作之前进行了写操作:
1 | function logBoxHeight() { |
为了回答高度问题,浏览器必须先应用样式更改(由于增加了 super-big 类),然后运行布局。这时它才能返回正确的高度。这是不必要的,并且可能是开销很大的工作。
这里有个强制同步布局的例子:演示
1 | // animation loop |
上面的代码中,在 requestAnimationFrame 的回调函数中,每个 mover 都触发了一次强制同步布局,所以本该在一帧内只布局一次,却在上面代码中布局了 movers.length 次,造成了卡顿。
在
Chrome DevTools中还可以诊断 强制同步布局。打开Performance面板(老版本是Timeline面板),开始记录,结束之后可以查看FPS较低的帧,看问题在哪,可以看到在调用栈中,某个函数耗时较长,而且如果触发了强制同步布局,鼠标移动到上面去会有个Forced reflow提示,可能存在性能瓶颈,接在点击该执行函数就可以看到在哪触发的强制同步布局。具体Chrome DevTools如何操作查看 Get Started With Analyzing Runtime Performance。