CSS
CSS3新特性(布局、图片、文字、颜色、动画)
选择器:nth-child(n)、nth-of-type(n)(伪类选择器,结构伪类)、attribute^=value(属性选择器)、
边框border:border-radius、box-shadow、border-image
背景: background-clip(用于确定背景画区: border-box(背景从border开始显示))、background-origin(用于确定背景图片的左上角对齐方式:border-box从border开始计算background-position)、background-size调整背景图片的大小、background-break(元素可以被分成几个盒子,此属性用于控制背景在这些不同盒子中的显示。continuous:忽略盒之间的距离;)
颜色渐变:线性渐变background-image: linear-gradient(direction, color-stop1, color-stop2, …);径向渐变radial-gradient
文本效果:word-wrap(换行)、text-overflow(文本超过容器边界的显示效果:clip裁剪文本、:ellipsis省略号代表)
字体@font-face规则
transform转换
过渡:transition属性可以被指定为一个或多个
CSS
属性的过渡效果,多个属性之间用逗号进行分隔,必须指定过渡效果和持续时间。1
transition: CSS属性,花费时间,效果曲线(默认ease),延迟时间(默认0)
动画:@keyframes规则、animation属性
多列
盒模型
布局:flex、grid
多媒体查询(@media)
颜色表示方式:rgba、hsla(h为色相、s为饱和度、l为亮度、a为透明度)
currentColor:是color属性的值。具体意思是指:currentColor关键字的使用值是color属性值的计算值。如果currentColor关键字被应用在color属性自身,则相当于是color:inherit。
CSS三大特性–优先级、层叠级、继承级
导入方式
- 外联(外部样式表):通过link标签引入外部CSS
- 内联(内嵌样式表):在head标签中使用style标签
- 嵌入(行内样式表):在标签中使用style属性
隐藏页面元素的方式及区别
- display: none指元素完全不陈列出来,不占据空间,涉及到DOM结构,故产生重绘和重排。
- visibility:hidden指元素不可见但存在,保留空间,不影响结构,故只产生重绘。若元素绑定了事件,则不可以触发绑定的事件。
- opacity: 0指元素不可见但存在,保留空间,不影响结构。若元素绑定了事件,可以触发事件。
- height、width设置为0。如果元素内有子元素或内容,还应该设置其
overflow:hidden
来隐藏其子元素。特点:元素不可见,不占据页面空间,无法响应点击事件。
重绘(repaint)与重排(reflow,也叫回流)的例子
- font-size改变会产生重排
- 当HTML标签使用fixed或absolute的position时,修改它们的CSS不会回流的,因为它们已经脱流了。
最小化重绘和重排
- 批量修改元素样式 elem.className 和 ele.style.cssText 代替 elem.style.xxx
- 尽量使用 CSS 属性简写:比如 border、 font、 background等
- 避免使用 CSS 表达式(expression),因为每次调用都会重新计算值(包括加载页面)
- 尽量避免用 table 布局(table 元素一旦触发回流就会导致 table 里的所有其他元素回流)
- 需要对元素进行复杂操作时,可以先隐藏(display:none),操作完成后再显示
- 需要创造多个 DOM 节点时,使用 DocumentFramgment 创建完后一次性加入 document 缓存 Layout属性值,如:let left = elem.offsetLeft ; 这样多次使用 left 只产生一次回流。
属性继承
- 默认情况下,能被继承的一般都是文本属性。
- 不可继承:
display margin border padding height width background position
CSS层叠样式表的权重值
style: 1000
#ID: 100
.class: 10
element: 1
内联样式>ID选择器>class选择器=伪类选择器=属性选择器(后面的样式会覆盖前面的样式)>标签选择器>通配符选择器>浏览器自定义样式
选择器
基础选择器
1 | - 标签选择器:h1 |
属性选择器
1 | -[attr]: 指定属性的元素 |
组合选择器
1 | -相邻兄弟选择器:A+B |
伪类
1 | 1 条件伪类 |
伪元素
1 | -::before: 在元素前插入内容 |
外边距塌陷问题
1 | 表现: |
inline-block与inline的区别
- inline-block可以设置高度,inline不可以设置高度
- block会独占一行,但inline-block不会
- inline-block兼备了块元素和行元素的性质,所以padding和margin在inline-block上都有作用。而inline只能使用padding、margin-left和margin-right
relative与absolute
- 当元素的position属性设置为relative时,设置的top、right、bottom、left偏移值是相对于其自身的
- 当元素的position属性设置为absolute时,设置的top、right、bottom、left偏移值是相对于其上一级有定位的祖先元素的。不占据空间。
- 当元素的position属性设置为fixed时,设置的top、right、bottom、left偏移值是相对于viewport(视窗)的。即使窗口滚动它也不会移动。不在标准流中占据位置。
- 当元素的position属性设置为static时,表示保留在原本应该在的位置,不会重新定位。top、left、right、bottom属性失效。static为position属性的默认值。
- 网页中,rem作为元素尺寸单位时,是相对文档根节点的font-size进行计算的
属性
border的规范写法为:border-width、border-style、border-color
position可以设置的值:absolute、fixed、relative、static、inherit
display
- display:block。将元素显示为块级元素,一般是其他元素的容器,可容纳内联元素和其他块级元素。块级元素排斥其他元素,自成一行,宽度高度起作用。常见为div和p.
- display:inline。将元素显示为内联元素,内联元素只能容纳文本或者其他内联元素。可以与其他内联元素位于同一行,宽度高度不起作用。常见为a。
- display:inline-block。将元素显示为内联元素,但对象内容作为块对象呈递。也就是周围元素能保持在同一行,宽度和高度均起作用。
overflow(规定内容溢出时发生的事情)
- overflow:scroll。必出现滚动条.
- overflow:auto。当子元素大于父元素时会出现滚动条。
- overflow:visible。溢出的内容出现在父元素之外。
- overflow:hidden。溢出隐藏。
outline轮廓(用于绘制元素周围的一条线)
- 位于边框边缘的外围,可起到突出元素的作用
- 可以设置元素轮廓的颜色和宽度
- 与border属性类似,但是outline不占据空间
CSS标准单位
- px
- em
- rem:根据页面的根节点的字体大小进行转变
CSS预编译工具
- Sass
- Less
- Stylus
BFC(块级格式上下文)
概念
- 是一个隔离的容器,容器里的子元素不会影响外面的元素
创建BFC的方式
- display: inline-block | table-cell | table-caption | flex | inline-flex
- float: left | right
- position: absolute | fixed
- overflow: hidden
特性
- BFC的区域与float的元素区域不会产生重叠
- 计算BFC高度时,浮动子元素也会参与计算
- 只要元素可以触发BFC,就无须使用clear:both来清除浮动的影响
令child垂直居中
<parent><child>content</child></parent>
1 | <style> |
1 | <style> |
1 | <style> |
CSS百分比参照
- 参照父元素宽度的元素:padding、margin、width、text-indent
- 参照父元素高度的元素:height
- 参照父元素属性:font-size、line-height
- 相对定位的时候,top(bottom)、left(right)参照的是父元素的内容区域的高度与宽度;而绝对定位的时候,参照的是最近的定位元素包括padding的高度与宽度
父元素高度塌陷
子元素都为浮动时的解决方案
- 给父元素添加overflow:hidden
- 在浮动元素下方添加空div,并添加样式clear:both;(clear:both;属性定义了元素的哪边的上方不允许出现浮动元素).clear属性指明该元素周围不可出现浮动元素。
- 设置父元素 :after{content:’’;clear:both;display:block;overflow:hidden;}
浮动元素
- 如果有多个浮动元素,浮动元素会按顺序排下来而不会发生重叠的现象
- 浮动元素会尽可能地向顶端对齐、向左或向右对齐
- 行内元素与浮动元素发生重叠,边框、背景、内容都会显示在浮动元素之上
- 块级元素与浮动元素发生重叠,边框、背景会显示在浮动元素之下,内容会显示在浮动元素之上
屏幕适配
屏幕大小
- 超小屏幕:col-xs(<768像素)
- 小屏幕:col-sm(>=768像素)
- 中等屏幕:col-md(>=992像素)
- 大屏幕:col-lg(>1200像素)
background-position
- 该属性可以有两个取值,第一个取值为背景图像与其容器在水平方向上的距离,第二个取值为背景图像与其容器在垂直方向上的距离
- 若只有一个取值,则第二个取值默认为50%
- 若取值用百分数表示,则表示此背景图像离其容器左边的距离为x=(对象的宽度-图像的宽度)*x%; 离其容器上边的距离为y=(对象的高度-图像的高度)*y%.
动画
Animation-timing-function
- linear规定以相同速度开始至结束的过渡效果
- ease规定慢速开始,然后变快,然后慢速结束的过渡效果。这是默认效果。
- ease-in规定以慢速开始的过渡效果
- ease-out规定以慢速结束的过渡效果
- ease-in-out规定以慢速开始和结束的过渡效果
优化CSS图片加载
- CSSSprite:允许将一个页面涉及到的零星图片都包含到一张大图中,当访问页面时,载入的图片不会像之前那样一幅一幅地慢慢显示出来。能降低网页的HTTP请求,从而大大提高页面的性能。
- SVG sprite:与CSS sprite类似,只是属于另外一种实现思路
<symbol>+<use>
。其中,<symbol>
用于定义可复用的形状,定义的形状不会展示出来,而是通过<use>
元素引用来显示。 - icon font:图标字体,就是字体做的图标。能自由变化大小,且不会模糊。比图片小,加载快,可以任意修改颜色。
- base64:可以将图片编码成一串字符串,使用该字符串代替图像地址,能有效减少HTTP请求次数。
伪类和伪元素
- 特性与区别
- 伪类本质上是为了弥补常规CSS选择器的不足,以便获取到更多信息
- 伪元素本质上是为了创建一个有内容的虚拟容器
- CSS3中伪类和伪元素的语法不同,伪类:link:hover, 伪元素::before::after
- 可以同时使用多个伪类,但只能同时使用一个伪元素。伪类类似于添加类所以可以是多个,而伪元素在一个选择器中只能出现一次,而且只能出现在末尾。
- 伪类和伪元素的根本区别在于是否创建了新的元素。伪元素/伪对象不存在DOM文档中,是虚拟的元素,是创建的新元素。这个新元素是某个元素的子元素,这个子元素虽然在逻辑上存在,但却并不实际存在于文档树中。伪类存在于DOM文档中(无标签,找不到,只有符合触发条件时才能看到),逻辑上存在但在文档树中却无需标识。
- 例:当鼠标移到span上时,span前插入”duang”
1 | <style> |
浏览器私有属性前缀
- mozilla:-moz
- webkit:-webkit
- opera:-o
- trident:-ms
盒模型
是什么?
当对一个文档进行布局的时候,浏览器的渲染引擎会根据CSS 基础框盒模型,将所有元素表示为一个个矩形的盒子。一个盒子由四个部分组成:content
、padding
、border
、margin
。
分类
标准盒模型(W3C)
- 盒子总宽度 = width + padding + border + margin;
- 盒子总高度 = height + padding + border + margin
也就是,width/height
只是内容高度,不包含 padding
和 border
值。也就是给盒模型设置width和height后,它显示出来的content的width和height就是设置的值。
怪异盒模型(IE)
- 盒子总宽度 = width + margin;
- 盒子总高度 = height + margin;
也就是,width/height
包含了 padding
和 border
值
box-sizing
CSS 中的 box-sizing 属性定义了引擎应该如何计算一个元素的总宽度和总高度
box-sizing: content-box|border-box|inherit
content-box 默认值,与标准盒子模型表现一致
border-box 与怪异盒子模型表现一致
inherit 指定 box-sizing 属性的值,应该从父元素继承
使用场景
如果想让两个盒子的宽度都为50%,有一定的padding,且在同一行,content-box很难达到这个要求。因为一个盒子的宽度+padding会超过50%,另一个盒子就会显示到下一行去。在这个场景中可以使用border-box解决,因为padding 和 content都算在50%内了。
当前流行的CSS框架都采用border-box,因为框架要想具备栅格系统,必须使用border-box。
选择器
常见的选择器
选择器的优先级
属性继承
em/px/rem/vh/vw的区别
- px:绝对单位,页面按精确像素展示
- em:相对单位,基准点为父节点字体的大小,如果自身定义了font-size按自身来计算,整个页面内1em不是一个固定的值
- rem:相对单位,可理解为root em,相对根节点html的字体大小来计算
- vh、vw:主要用于页面视口(viewport)大小布局
设备像素、CSS像素、设备独立像素、dpr、ppi的区别
- 无缩放的情况下,一个CSS像素=一个设备独立像素
- 设备像素由屏幕生产之后就不发生变化,设备独立像素是一个虚拟单位会发生改变
- PC端,未缩放,1个设备独立像素=1个设备像素
- 移动端,标准屏,1个设备独立像素=1个设备像素
- 设备像素比dpr = 设备像素/设备独立像素
- 每英寸像素ppi,值越大,图像越清晰
1 | 屏幕分辨率:X * Y |
BFC
是什么?
BFC
(Block Formatting Context),即块级格式化上下文。BFC
目的是形成一个相对于外界完全独立的空间,让内部的子元素不会影响到外部的元素。它是页面中的一块渲染区域,并且有一套属于自己的渲染规则:
- 内部的盒子会在垂直方向上一个接一个的放置
- 对于同一个BFC的俩个相邻的盒子的margin会发生重叠,与方向无关。
- 每个元素的左外边距与包含块的左边界相接触(从左到右),即使浮动元素也是如此
- BFC的区域不会与float的元素区域重叠
- 计算BFC的高度时,浮动子元素也参与计算
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然
常见触发条件
- 根元素,即html
- 浮动元素:float=left || right
- position=absolute || fixed
- overflow值不为 visible,为 auto、scroll、hidden
- display的值为inline-block、inltable-cell、table-caption、table、inline-table、flex、inline-flex、grid、inline-grid
应用场景
防止margin重叠:同一个BFC中两个相邻的盒子的margin会发生重叠,但是如果给其中一个盒子再套上一个BFC时margin就不会发生重叠了。
清除内部浮动:当父元素中子元素均为浮动元素时会产生高度塌陷问题。由于BFC计算高度时会计算浮动元素的高度,故可以给父元素添加overflow:hidden;变成BFC。
自适应多栏布局
两栏布局,右侧自适应
实现思路1:左float,右margin-left
- 使用 float 左浮左边栏
- 右边模块使用 margin-left 撑出内容块做内容展示
- 为父级元素添加BFC,防止下方元素飞到上方内容
1 | <style> |
实现思路2
- 使用flex布局
1 | <style> |
三栏布局,中间自适应
方案:
- 两边使用 float,中间使用 margin
- 两边使用 absolute,中间使用 margin
- 两边使用 float 和负 margin
- display: table 实现
- flex实现
- grid网格布局
两边使用 float,中间使用 margin: 浮动+margin
1 | <style> |
- 需要将中间的内容放在
html
结构最后,否则右侧会在中间内容的下方
原理:
- 两边固定宽度,中间宽度自适应。
- 利用中间元素的margin值控制两边的间距
- 宽度小于左右部分宽度之和时,右侧部分会被挤下去
这种实现方式存在缺陷:
- 主体内容是最后加载的。
- 右边在主体内容之前,如果是响应式设计,不能简单的换行展示
两边使用absolute,中间使用margin: 定位+margin
1 | <style> |
- 基于绝对定位的三栏布局:注意绝对定位的元素脱离文档流,相对于最近的已经定位的祖先元素进行定位。无需考虑HTML中结构的顺序.
原理:
- 左右两边使用绝对定位,固定在两侧。
- 中间占满一行,但通过 margin和左右两边留出10px的间隔
两边使用float和负margin
1 | <style> |
实现过程:
- 中间使用了双层标签,外层是浮动的,以便左中右能在同一行展示
- 左边通过使用负 margin-left:-100%,相当于中间的宽度,所以向上偏移到左侧
- 右边通过使用负 margin-left:-100px,相当于自身宽度,所以向上偏移到最右侧
缺点:
- 增加了 .main-wrapper 一层,结构变复杂
- 使用负 margin,调试也相对麻烦
使用display:table实现
1 | <style> |
原理:
- 通过 display: table设置为表格,设置 table-layout: fixed;表示列宽自身宽度决定,而不是自动计算。
- 内层的左中右通过 display: table-cell设置为表格单元。
- 左右设置固定宽度,中间设置 width: 100% 填充剩下的宽度
flex
1 | <style> |
实现过程:
- 仅需将容器设置为
display:flex;
, - 盒内元素两端对其,将中间元素设置为
100%
宽度,或者设为flex:1
,即可填充空白 - 盒内元素的高度撑开容器的高度
优点:
- 结构简单直观
- 可以结合 flex的其他功能实现更多效果,例如使用 order属性调整显示顺序,让主体内容优先加载,但展示在中间
grid
1 | <style> |
元素水平垂直居中(如果是不定高的情况呢?)五种
思路1:定位+margin: auto(让浏览器自己选择一个合适的外边距)
1 | <style> |
思路2:定位+transform
1 | <style> |
思路3:table布局
父元素display: table-cell,子元素display: inline-block。
1 | <style> |
思路4:flex布局
1 | <style> |
思路5:网格布局
1 | <style> |
垂直居中、水平居中、垂直且水平居中
- 水平居中:text-align: center。行内内容如何相对它的块父元素对齐。也可以在块元素中使用,来将其中的行内元素对齐。
- 垂直居中:vertical-align: middle。只对行内、行内块元素生效,块级元素不行。
- flex布局:设置justify-content: center水平居中;align-items: center垂直居中。
- 垂直水平居中:
- 父元素relative, 子元素absolute,并且top:0, left:0, margin: auto;
- 绝对定位+transform: 父relative,子absolute, 并且top: 50%, left: 50%, translate(-50%, -50%);
grid网格布局
是什么?
Grid
布局即网格布局,是一个二维的布局方式,由纵横相交的两组网格线形成的框架性布局结构,能够同时处理行与列。擅长将一个页面划分为几个主要区域,以及定义这些区域的大小、位置、层次等关系。
网格线:如下为2*3网格,有3根水平网格线和4根垂直网格线

属性
属性可以分为
- 容器属性
- 项目属性
display属性
在元素上设置display:grid
或 display:inline-grid
来创建一个网格容器
grid-template-columns属性,grid-template-rows属性
grid-template-columns
属性设置列宽,grid-template-rows
属性设置行高
1 | .wrapper { |
还能写成如下形式:
1 | /*auto-fill自动填充*/ |
grid-row-gap、grid-column-gap、grid-gap属性
grid-row-gap
属性、grid-column-gap
属性分别设置行间距和列间距。grid-gap
属性是两者的简写形式
grid-template-areas属性
用于定义区域,一个区域由一个或者多个单元格组成。以下代码先划分出9个单元格,然后将其定名为a
到i
的九个区域,分别对应这九个单元格。
1 | .container { |
grid-auto-flow属性
划分网格以后,容器的子元素会按照顺序,自动放置在每一个网格。顺序就是由grid-auto-flow
决定,默认为行,代表”先行后列”,即先填满第一行,再开始放入第二行。
justify-items、align-items、place-items属性
justify-items
属性设置单元格内容的水平位置(左中右),align-items
属性设置单元格的垂直位置(上中下)。place-items
属性是align-items
属性和justify-items
属性的合并简写形式。
justify-content、align-content、place-content属性
justify-content
属性是整个内容区域在容器里面的水平位置(左中右),align-content
属性是整个内容区域的垂直位置(上中下)。
grid-column-start、grid-column-end、grid-row-start、grid-row-end属性
指定网格项目所在的四个边框,分别定位在哪根网格线,从而指定项目的位置,grid布局的重点属性
如下代码为示例:
1 | <style> |

grid-area属性
指定项目放在哪一个区域
justify-self 属性、align-self 属性以及 place-self 属性
用于设置单个单元格的格式
兼容性
总体兼容性还不错,但在 IE 10 以下不支持。目前,Grid
布局在手机端支持还不算太友好。
CSS动画
是什么?
元素从一种样式逐渐过渡为另一种样式的过程。
CSS中动画实现方式
- transition实现渐变动画
- transform实现转变动画
- animation实现自定义动画
transition
transition
的属性如下:
- property:填写需要变化的css属性
- duration:完成过渡效果需要的时间单位(s或者ms)
- timing-function:完成效果的速度曲线
- delay: 动画效果的延迟触发时间
timing-function的取值如下:
值 | 描述 |
---|---|
linear | 匀速(等于 cubic-bezier(0,0,1,1)) |
ease | 从慢到快再到慢(cubic-bezier(0.25,0.1,0.25,1)) |
ease-in | 慢慢变快(等于 cubic-bezier(0.42,0,1,1)) |
ease-out | 慢慢变慢(等于 cubic-bezier(0,0,0.58,1)) |
ease-in-out | 先变快再到慢(等于 cubic-bezier(0.42,0,0.58,1)),渐显渐隐效果 |
cubic-bezier(n,n,n,n) | 在 cubic-bezier 函数中定义自己的值。可能的值是 0 至 1 之间的数值 |
例如,实现鼠标移动到元素上发生变化的动画效果:
1 | <style> |
transform
一般配合transition
使用,包含四个常用的功能:
- translate:位移
- scale:缩放
- rotate:旋转
- skew:倾斜
1 | <style> |
transform的缺点:进行3D变换的时候,可能会增加内存使用量,需要更多的计算能力,从而导致动画卡顿或者页面响应变慢。
animation实现自由动画
animation
是由 8 个属性的简写,分别如下:
属性 | 描述 | 属性值 |
---|---|---|
animation-duration | 指定动画完成一个周期所需要时间,单位秒(s)或毫秒(ms),默认是 0 | |
animation-timing-function | 指定动画计时函数,即动画的速度曲线,默认是 “ease” | linear、ease、ease-in、ease-out、ease-in-out |
animation-delay | 指定动画延迟时间,即动画何时开始,默认是 0 | |
animation-iteration-count | 指定动画播放的次数,默认是 1 | |
animation-direction | 指定动画播放的方向,默认是 normal | normal、reverse、alternate、alternate-reverse |
animation-fill-mode | 指定动画填充模式。默认是 none | forwards、backwards、both |
animation-play-state | 指定动画播放状态,正在运行或暂停。默认是 running | running、pauser |
animation-name | 指定 @keyframes 动画的名称 |
CSS
动画只需要定义一些关键的帧,而其余的帧,浏览器会根据计时函数插值计算出来,通过 @keyframes
来定义关键帧。
因此,如果想要让元素旋转一圈,只需要定义开始和结束两帧即可:
1 | @keyframes rotate{ |
重绘与重排
是什么?
重排:布局引擎会根据各种样式计算每个盒子在页面上的大小与位置
重绘:当计算好盒模型的位置、大小及其他属性后,绘制引擎根据每个盒子特性进行绘制
触发时机
重排触发时机
回流这一阶段主要是计算节点的位置和几何信息,那么当页面布局和几何信息发生变化的时候,就需要回流,如下面情况:
- 添加或删除可见的DOM元素
- 元素的位置发生变化
- 元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
- 内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代
- 页面一开始渲染的时候(这避免不了)
- 浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)
还有一些容易被忽略的操作:获取一些特定属性的值
offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight
这些属性有一个共性,就是需要通过即时计算得到。因此浏览器为了获取这些值,也会进行回流
重绘触发时机
触发回流一定会触发重绘。此外:颜色改变、文本方向改变、阴影改变也会触发重绘。
浏览器自身优化机制
由于每次重排都会造成额外的计算消耗,因此大多数浏览器都会通过队列化修改并批量执行来优化重排过程。浏览器会将修改操作放入到队列里,直到过了一段时间或者操作达到了一个阈值,才清空队列。当你获取布局信息的操作的时候,会强制队列刷新,包括前面讲到的offsetTop
等方法都会返回最新的数据。因此浏览器不得不清空队列,触发回流重绘来返回正确的值。
减少重排的方式(table、动画、fragment、离线操作)
- 如果想设定元素的样式,通过改变元素的
class
类名 (尽可能在 DOM 树的最里层) - 避免设置多项内联样式
- 应用元素的动画,使用
position
属性的fixed
值或absolute
值 - 避免使用
table
布局,table
中每个元素的大小以及内容的改动,都会导致整个table
的重新计算 - 对于那些复杂的动画,对其设置
position: fixed/absolute
,尽可能地使元素脱离文档流,从而减少对其他元素的影响 - 使用css3硬件加速,可以让
transform
、opacity
、filters
这些动画不会引起回流重绘 - 避免使用 CSS 的
JavaScript
表达式 - 使用
JavaScript
动态插入多个节点时, 可以使用DocumentFragment
. 创建后一次插入. 就能避免多次的渲染性能 - 离线操作。通过通过设置元素属性
display: none
,将其从页面上去掉,然后再进行后续操作,这些后续操作也不会触发回流与重绘,这个过程称为离线操作
1 | // 离线前 |
响应式设计
是什么?
响应式网站设计(Responsive Web design)是一种网络页面设计布局,页面的设计与开发可以根据用户行为以及设备环境(系统平台、屏幕尺寸、屏幕定向等)进行相应的响应和调整。
响应式网站常见特点:
- 同时适配PC + 平板 + 手机等
- 标签导航在接近手持终端设备时改变为经典的抽屉式导航
- 网站的布局会根据视口来调整模块的大小和位置
实现响应式布局的方式有如下:
- 媒体查询
- 百分比
- vw/vh
- rem
媒体查询
通过媒体查询检测不同的设备屏幕尺寸做处理,为了处理移动端,页面头部必须有meta
声明viewport
1 | <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no”> |
属性对应如下:
- width=device-width: 是自适应手机屏幕的尺寸宽度
- maximum-scale:是缩放比例的最大值
- initial-scale:是缩放的初始化
- user-scalable:是用户的可以缩放的操作
通过媒体查询,可以通过给不同分辨率的设备编写不同的样式来实现响应式的布局,比如我们为不同分辨率的屏幕,设置不同的背景图片。CSS中使用@media
查询,可以针对不同的媒体类型定义不同的样式,如:
1 | @media screen and (max-width: 1920px) { ... } |
百分比
height
、width
属性的百分比依托于父标签的宽高,但是其他盒子属性则不完全依赖父元素:
- 子元素的top/left和bottom/right如果设置百分比,则相对于直接非static定位(默认定位)的父元素的高度/宽度
- 子元素的padding如果设置百分比,不论是垂直方向或者是水平方向,都相对于直接父亲元素的width,而与父元素的height无关。
- 子元素的margin如果设置成百分比,不论是垂直方向还是水平方向,都相对于直接父元素的width
- border-radius不一样,如果设置border-radius为百分比,则是相对于自身的宽度
可以看到每个属性都使用百分比,会照成布局的复杂度,所以不建议使用百分比来实现响应式
vw/vh
vw
表示相对于视图窗口的宽度,vh
表示相对于视图窗口高度。 任意层级元素,在使用vw
单位的情况下,1vw
都等于视图宽度的百分之一
rem
rem
是相对于根元素html
的font-size
属性,默认情况下浏览器字体大小为16px
,此时1rem = 16px
为了更准确监听设备可视窗口变化,我们可以在css
之前插入script
标签,内容如下:
1 | //动态为根元素设置字体大小 |
无论设备可视窗口如何变化,始终设置rem
为width
的1/10,实现了百分比布局。
响应式布局的优缺点
优点:
- 面对不同分辨率设备灵活性强
- 能够快捷解决多设备显示适应问题
缺点:
- 仅适用布局、信息、框架并不复杂的部门类型网站
- 兼容各种设备工作量大,效率低下
- 代码累赘,会出现隐藏无用的元素,加载时间加长
- 其实这是一种折中性质的设计解决方案,多方面因素影响而达不到最佳效果
- 一定程度上改变了网站原有的布局结构,会出现用户混淆的情况
优化CSS(提高CSS性能的方法)
实现方式
- 内联首屏关键CSS
- 异步加载CSS
- 资源压缩
- 合理使用选择器
- 减少使用昂贵的属性
- 不要使用@import
内联首屏关键CSS
在打开一个页面,页面首要内容出现在屏幕的时间影响着用户的体验,而通过内联css
关键代码能够使浏览器在下载完html
后就能立刻渲染。而如果外部引用css
代码,在解析html
结构过程中遇到外部css
文件,才会开始下载css
代码,再渲染。所以,CSS
内联使用使渲染时间提前。
注意:但是较大的css
代码并不合适内联(初始拥塞窗口、没有缓存),而其余代码则采取外部引用方式。
异步加载CSS
在CSS
文件请求、下载、解析完成之前,CSS
会阻塞渲染,浏览器将不会渲染任何已处理的内容。前面加载内联代码后,后面的外部引用css
则没必要阻塞浏览器渲染。这时候就可以采取异步加载的方案,主要有如下:
- 使用javascript将link标签插到head标签最后
1 | // 创建link标签 |
资源压缩
利用webpack
、gulp/grunt
、rollup
等模块化工具,将css
代码进行压缩,使文件变小,大大降低了浏览器的加载时间
合理使用选择器
css
匹配的规则是从右往左开始匹配,例如#markdown .content h3
匹配规则如下:
- 先找到h3标签元素
- 然后去除祖先不是.content的元素
- 最后去除祖先不是#markdown的元素
如果嵌套的层级更多,页面中的元素更多,那么匹配所要花费的时间代价自然更高。
所以我们在编写选择器的时候,可以遵循以下规则:
- 不要嵌套使用过多复杂选择器,最好不要三层以上
- 使用id选择器就没必要再进行嵌套
- 通配符和属性选择器效率最低,避免使用
减少使用昂贵的属性
在页面发生重绘的时候,昂贵属性如box-shadow
/border-radius
/filter
/透明度/:nth-child
等,会降低浏览器的渲染性能。
不要使用import
css样式文件有两种引入方式,一种是link
元素,另一种是@import
。@import
会影响浏览器的并行下载,使得页面在加载时增加额外的延迟,增添了额外的往返耗时。而且多个@import
可能会导致下载顺序紊乱。比如一个css文件index.css
包含了以下内容:@import url("reset.css")
。那么浏览器就必须先把index.css
下载、解析和执行后,才下载、解析和执行第二个文件reset.css
。
实现单行/多行文本溢出的省略样式
单行文本溢出省略
1 | p{ |
多行文本溢出省略
基于高度截断:伪元素+定位
1 | <style> |
实现原理就是通过伪元素绝对定位到行尾并遮住文字,再通过 overflow: hidden
隐藏多余文字
这种实现具有以下优点:
- 兼容性好,对各大主流浏览器有好的支持
- 响应式截断,根据不同宽度做出调整
基于行数截断: 移动端大多数是使用webkit
, 所以移动端常用该形式
1 | <style> |
CSS完成视差滚动效果
是什么?
视差滚动(Parallax Scrolling)是指多层背景以不同的速度移动,形成立体的运动效果,带来非常出色的视觉体验。多层指背景层、内容层、悬浮层。
实现方式
使用css
形式实现视觉差滚动效果的方式有:
- background-attachment
- transform:translate3D
background-attachment
作用是设置背景图像是否固定或者随着页面的其余部分滚动。
值分别有如下:
- scroll:默认值,背景图像会随着页面其余部分的滚动而移动
- fixed:当页面的其余部分滚动时,背景图像不会移动
- inherit:继承父元素background-attachment属性的值
**完成滚动视觉差就需要将background-attachment
属性设置为fixed
**,让背景相对于视口固定。即使一个元素有滚动机制,背景也不会随着元素的内容而滚动。也就是说,背景一开始就已经被固定在初始的位置。
1 | .g-img { |
transform: translate3D
transform与perspective:
- transform: css3 属性,可以对元素进行变换(2d/3d),包括平移 translate,旋转 rotate,缩放 scale,等等
- perspective: css3 属性,当元素涉及 3d 变换时,perspective 可以定义我们眼睛看到的 3d 立体效果,即空间感
1 | <style> |
而这种方式实现视觉差动的原理如下:
- 容器设置上 transform-style: preserve-3d 和 perspective: 1px,那么处于这个容器的子元素就将位于3D空间中,
- 子元素设置不同的 transform: translateZ(),这个时候,不同元素在 3D Z轴方向距离屏幕(我们的眼睛)的距离也就不一样
- 滚动滚动条,由于子元素设置了不同的 transform: translateZ(),那么他们滚动的上下距离 translateY 相对屏幕(我们的眼睛),也是不一样的,这就达到了滚动视差的效果
CSS画一个三角形

实心三角形
1 | .border { |
添加伪元素画空心三角形
1 | .border { |
为什么伪元素一定要指定一个content呢?
W3C上的描述:content的初始值为’normal’,在::before、::after上如果指定了content的初始值为’normal’,则等同于’none’,也就是不生成伪元素。
所以为了生成伪元素,至少需要指定一个看似无意义的content:’’来初始化content的值。
取消某条边框时,可能出现的情况:
- 取消一条边的时候,与这条边相邻的两条边的接触部分会变成直的
- 当仅有邻边时, 两个边会变成对分的三角
- 当保留边没有其他接触时,极限情况所有东西都会消失
可以通过以上原理来设置直角三角形
1 | .box { |
CSS预编语言
CSS存在的问题
CSS需要书写大量看似没有逻辑的代码,不方便维护及扩展,不利于复用。Css
预处理器便是针对上述问题的解决方案。
CSS预处理语言
扩充了 Css
语言,增加了诸如变量、混合(mixin)、函数等功能,让 Css
更易维护、方便。CSS预处理语言包含一套自定义的语法及一个解析器,根据这些语法定义自己的样式规则,这些规则最终会通过解析器,编译生成对应的 Css
文件。
主流的CSS预处理语言
- sass
- less
- stylus:主要用来给
Node
项目进行Css
预处理支持
区别
使用的主要特性:
- 变量(variables)
- 作用域(scope)
- 代码混合( mixins)
- 嵌套(nested rules)
- 代码模块化(Modules)
变量
less
声明的变量必须以@
开头,后面紧跟变量名和变量值,而且变量名和变量值需要使用冒号:
分隔开。
1 | @red: #c00; |
sass
声明的变量必须以$
开头
作用域
sass
中不存在全局变量。
1 | $color: black; |
编译后:
1 | .scoped { |
less
与stylus
的作用域跟javascript
十分的相似,首先会查找局部定义的变量,如果没有找到,会像冒泡一样,一级一级往上查找.
1 | @color: black; |
编译后:
1 | .scoped { |
混入
混入(mixin)是预处理器最精髓的功能之一了,简单点来说,**Mixins
可以将一部分样式抽出,作为单独定义的模块,被很多选择器重复使用。**可以在Mixins
中定义变量或者默认参数。
1 | .alert { |
编译后:
1 | .alert { |
模块化
模块化就是将Css
代码分成一个个模块。scss
、less
、stylus
三者的使用方法都如下所示:
1 | @import './common'; |
让chrome支持小于12px的文字
- zoom:改变页面上元素的尺寸
1 | <style type="text/css"> |
- -webkit-transform: scale()【缩放】
1 | <style type="text/css"> |
- -webkit-text-size-adjust: none
1 | html{ |
浮动
为什么要浮动?
块级元素往往独占一行,如果想要多个块级元素在一行上显示就要用到浮动。浮动后块级元素之间是紧紧挨着的,不存在间距。而inline-block虽然也能在一行显示,但是中间会存在间距且不好去除。
浮动产生的最根本的原因是实现文字环绕效果。
清除浮动的本质是
清除浮动主要是为了解决父级元素因为子元素浮动而引起内部高度为0 的问题。清除浮动后,父元素根据浮动的盒子自动检测高度,父级有了高度就不会影响下面的标准流了。
清除浮动的方法
- 给父元素设置一个高度。只适合高度固定的布局。
- clear: both;这个属性用于表示框的哪边不应该挨着浮动框。这个规则只能影响使用清除的元素本身,不能影响其他元素。
- overflow: hidden;BFC。BFC中会计算浮动元素的高度。给浮动元素的父元素添加此属性,这个属性能清除子元素浮动给页面的影响,必须定义width或zoom:1,同时不能设定height,浏览器会自动检查浮动区域的高度。
使用rem适配不同屏幕
- 在header中设置meta标签
1 | <meta name="viewport" content="initial-scale=1,maximum-scale=1,minimum-scale=1"></meta> |
- 在header中写上script标签
1 | <!-- 此处是设置html标签的font-size,因为使用rem的时候是相对于html标签中的font-size为基础的 --> |
- 场景:设计稿是640px,有一个红色盒子宽高是320px,里面的文字是32px
1 |
|
渲染层与合成层
渲染层
处于相同坐标空间(Z轴空间)的渲染对象,都将归并到同一个渲染层中,因此根据层叠上下文,不同坐标空间的渲染对象将形成多个渲染层,以体现它们的层叠关系。
合成层
满足某些特殊条件的渲染层,会被浏览器提升为合成层,交由GPU处理。
常见的合成层
i. transforms
ii. 通过CSS动画实现的opacity动画转换
iii.video、canvas等元素
iv. position: fixed
合成层元素特点
- 合成层的位图会交由GPU合成,比CPU处理快得多
- 当需要重绘时,只需要重绘本身,不会影响其他层
- 元素提升为合成层后,transform和opacity才不会出发重绘,如果不是合成层,则依然会触发chong
calc函数布局
- 基本理论:calc可以作用于任何具有大小的东西,比如border、margin、padding、font-size等属性设置动态值。支持的计算单位:rem、em、%、px。
- 注意点:calc内部的表达式,在使用运算符号时,两边必须加上空格。
1 | width: calc(10 * 10px); |
requestAnimation
优点
- 更平滑的动画效果:requestAnimation可以在浏览器下一次重绘之前调用动画函数,从而避免了抖动和卡顿问题,使动画效果更加平滑。
- 更好的性能:requestAnimation可以避免在不必要的时候进行重绘。如果动画某一帧没有发生任何变化,那么浏览器就无需重绘,则会跳过这一帧,等到下一帧再进行绘制。而普通JS编写的函数无法做到。
- 更少的代码:requestAnimation无需手动计算动画的时间间隔,而是使用浏览器提供的帧率来计算动画的时间间隔。
有一个动画,分别使用requestAnimation包裹和使用原生JS写,当页面切换到后台时,动画是否还会继续执行呢?
均不会。当页面被切换到后台后,浏览器会将页面的渲染和JS执行暂停,不论是requestAnimation还是普通的JS动画,都会被暂停。