CSS / CSS3 篇
- 三种导入CSS的方式
- CSS盒子模型
- CSS选择器
- 伪类与伪元素
- 选择器的优先级
- 选择器权重的计算规则
- 选择器为什么是从右往左匹配的
- 可以继承的属性有哪些
- px / em / rem / vh / vw / %百分比
- background属性
- position的取值
- display的取值
- block、inline、inline-block的区别
- display:none;visibility:hidden;opacity:0
- 隐藏页面元素的方式
- 标准流、浮动流、浮动带来的影响
- 清除浮动的方式
- 两栏布局的实现
- 三栏布局的实现
- Grid布局 —— 网格布局
- Flex布局 —— 弹性布局
- margin外边距叠加
- BFC
- 层叠上下文与层叠级别
- 元素水平居中 / 垂直居中的方法
- 深入了解vertical-align
- 深入了解line-height
- CSS3新增特性
- transition和animation的区别
- 重排reflow与重绘repaint
- 响应式设计
- CSS的性能优化
- 单行或多行文本溢出省略样式
- 常见动画(CSS3)
- link和@import
- setTimeout和setInterval执行动画的缺点
- requestAnimationFrame 请求动画帧
- inline与inline-block之间的空白间隙
- 替换元素
- CSSSprites
- 物理像素、逻辑像素和像素密度
- 为什么移动端开发需要@2x或@3x的图片
- sass、less
- 预处理器、后处理器
- CSS 工程化 **
- -----------------------------------
- 实现九宫格
- 实现三角形
- 实现扇形
- 实现圆和半圆
- 实现宽高自适应的正方形
- 实现梯形
- -----------------------------------
- 画一条0.5px的线
- 设置小于12px的字
- Retina屏幕上的1px问题
勤能补拙,查缺补漏!基础不牢,地动山摇!
分点回答,全面细致!打好基础,打好基础!
三种导入CSS的方式
导入CSS的三种方式
CSS盒子模型
- 当浏览器渲染进行到了“布局”步骤的时候,会把所有的元素表示作一个一个的盒子。
- 盒子模型由四部分组成,由内到外分别是:content内容、padding内边距、border边框和margin外边距。
- 盒子模型可以分作两大类,即IE盒模型和标准盒模型。IE盒模型的width是包括content、padding和border;而标准盒模型的width只是包括content。
- CSS有box-sizing属性:box-sizing:content-box|border-box|inherit-box。分别对应的盒子模型是标准盒模型、IE盒模型和继承。
- 实际开发中,IE盒模型会更加方便。因为在IE盒模型设置width,直接控制的就是盒子的实际宽度(content+padding+border),不会因为设置padding或者border而改变盒子大小从而影响布局;倘若是标准盒模型,设置宽度width仅仅是控制content部分。再设置padding或border,会把该盒子“再撑大”,增加盒子的实际宽度,从而影响布局,不方便。
CSS选择器
CSS 基础选择器、组合选择器、属性选择器、伪类选择器、伪元素、CSS3属性选择器、优先级
一、基础选择器
- 通配符选择器 (可用于清除默认边距)
- 标签选择器
- class选择器
- id选择器
二、组合选择器
- 多元素选择器 E,F
- 后代元素选择器 E F
- 子代元素选择器 E > F
- 毗邻兄弟元素选择器 E + F (选择紧跟在F后面的E元素且E和F要有同一个父元素)
三、属性选择器 (可匹配选择多个属性)
- *[att],选择所有具有att属性的元素
- E[att] ,选择所有具有att属性的E元素
- E[att=“value”],选择所有具有att属性,且att属性的值为value的E元素
- E[att~=“value”],选择所有具有att属性,且att属性的其中一个值为value的E元
四、链接伪类
- link表示未访问时的状态
- visited表示访问过的状态
- hover表示鼠标悬停在上面时的状态
- active表示鼠标已经按下但未释放时的状态
五、:first-child伪类
六、伪元素
伪类与伪元素
区别:
- 伪类是单冒号;伪元素是双冒号
- 伪类用于选择已有元素处于某个特定状态时,给其赋予特定的样式(链接伪类);伪元素是用于创建一些不在文档树的元素,虽然可以看到,但它就是不处于文档树中(::before、::after)
伪类:
伪元素:
- ::first-line 作用于块级元素的首行
- ::first-letter 作用于块级元素的首字母
- ::before
- ::after
h1::after {
content: url(smiley.gif);
}
选择器的优先级
- !important > 行内样式>ID选择器 > 类选择器 > 标签选择器 > 通配符 > 继承 > 浏览器默认属性
- 行内样式 > style样式 > 外部链接
如果是同一级别的,后续样式将覆盖前面的样式。
选择器权重的计算规则
- ① 行内样式,1,0,0,0
- ② ID选择器,0,1,0,0
- ③ 类选择器、属性选择器、伪类选择器,0,0,1,0
- ④ 标签元素、伪元素,0,0,0,1
- ⑤ 通配符*、子代选择器>、毗邻兄弟元素选择器+,0,0,0,0
规则说明:
- 每一类只对特定的位做出贡献,譬如行内样式只对 x,0,0,0 的 x 位做贡献
- 同一位的权重可以叠加,但不可进位
- 高位数的权重一定大于低位数的
选择器为什么是从右往左匹配的
简单来说,从右往左去匹配选择器,可以一定程度上减少许多不必要的匹配,从而提升性能。
譬如 div span a
如果从左边开始,是从最不具体的规则到最具体的规则。有可能遍历到最末的子节点,发现不是a,那就又需要回溯上去重新匹配。
如果最后都不是a,何必在一开始花那么多时间匹配左边的规则呢。
所以CSS选择器是从右边往左边开始匹配的,把最终不是a的统统pass掉,最后可以减少很多不必要的匹配。
可以继承的属性有哪些
字体相关
- font
- font-family
- font-weight
- font-size
- font-style
文本相关
- text-indent
- text-align
- line-height
- word-spacing
- letter-spacing
- color
其它
注意
- a标签的字体颜色无法继承
- h1-h6的字体大小无法继承
px / em / rem / vh / vw / %百分比
px:
- px 即 pixel 像素,是屏幕上的一个个小点,是相对于屏幕的分辨率而言
em:
- em是相对单位长度,其值不是固定的
- 一般情况下,em是相对于当前对象内文本的字体尺寸
- 若行内文本的字体尺寸没有被设置,则相对于浏览器的默认字体尺寸(即1em=16px)
- 为了简化使用,一般在body里面设置font-size:62.5%,即font-size:10px。那么1em = 10px
rem:
- rem相对于root em。它直接是相对于HTML根元素的文本字体尺寸大小
vh与vw:
- vh是viewport height,vw是viewport width
- 是根据窗口的高度和宽度分成100等分:100vh就是满高,100vw就是满宽;50vh就是半宽
%百分比:
- 对于普通元素,%是相对于其父元素
- 若元素设置position:absolute,则相对的是已经定位的父元素
- 若元素设置position:fixed,则相对的是viewport
background属性
background-image 设置背景图像
background-color 背景的颜色
background-position 背景图像image的起始位置
background-size 背景图像的尺寸(length|percentage|cover|contain)
- length 设置背景图像的宽度和高度
- percentage 以父元素的百分比来设置图像的宽度和高度
- cover 让背景图像完全覆盖整个背景区域(有可能背景图像的某些部分无法显示在背景区域当中)
- contain 把背景图像扩展到最大尺寸,使得宽度和高度完全适应内容区域
background-repeat 设置背景图像的平铺方式
- repeat (default)图像在水平方向和竖直方向上重复
- repeat-x
- repeat-y
- no-repeat
- inherit
background-origin 规定background-position相对于什么参考来定位
- content-box
- padding-box
- border-box
background-clip 规定背景的绘制区域
- content-box
- padding-box
- border-box
background-attachment
- scroll 背景图像会随着页面其余部分的滚动而移动
- fixed 背景图像固定
- inherit
position的取值
- CSS的position属性有四个值:absolute、relative、static、fixed。配合设置TLBR(top、left、bottom、right)可以调整布局和元素位置。
- absolute 是绝对定位,会脱离文档流即不占据空间。它是相对与最近一个非static的父元素而进行定位的, 否则则以body为标准定位。
- relative 是相对定位,不脱离文档流。它是相对于自身静态位置而进行定位的。
- static 是静态定位,不脱离文档流。没有特别的设定,就出现在正常的文档流中
- fixed 是固定定位,会脱离文档流。 它定位的参考则是屏幕视口viewport,而不是body元素。效果即在页面滚动时,fixed定位的元素是不会移动的。
display的取值
常见的有:
- none 元素不显示,从文档流中完全移除
- block 块级元素
- inline 行内元素
- inline-block 行内块元素
还有:
- table 元素为块级表格
- list-item 生成块级列表
- inherit 从父元素继承display的值
block、inline、inline-block的区别
block 块级盒子
- 独占一行
- 可定义width,height,默认宽度100%
- 可定义四个方向上的margin和padding
- 内部可容纳其它block或inline元素
inline 行内盒子
- 不独占一行
- 不可定义width,height,默认宽度为自身内容宽度
- 只能定义margin-left,margin-right,padding-left,padding-right
- 内部只能容纳inline元素或者文本
inline-block 行内块盒子
- 不独占一行
- 可定义width,height,默认宽度为自身宽度
- 可以定义四个方向上的margin和padding
display:none;visibility:hidden;opacity:0
- display:none 不占有原来的位置,影响布局;元素所绑定的事件也不会被触发,忽略了元素的权重。相当于在渲染树中完全消失。
- visibility:hidden 占有原来的位置,不影响布局;元素所绑定的事件不能被触发。
- opacity:0 占有原来的位置,不影响布局;元素所绑定的事件还是能被触发。
隐藏页面元素的方式
主要方式有三种:
- opacity:0 即设置元素的透明度为0。特点:仍存在页面中,不影响布局,仍可触发元素所绑定的事件。
- visibility:hidden 即设置元素为不可见。特点:仍存在页面中,不影响布局,不可触发元素所绑定的事件。
- display:none 即让元素彻底消失。特点:不存在页面中,影响布局,不可触发元素所绑定的事件,
关于重排重绘,注意:
- display:none 会引起重排和重绘;
- visibility:hidden 会引起重绘,不引起重排;
- opacity:0 不一定会重绘,不引起重排
另外还可以:
- 设置position:absolute ; top:-9999px ; left:-9999px ;即让元素脱离文档流,并向外移出
- 设置margin、border、padding、width和height为0即可使元素不可见。若有子元素则再设置overflow:hidden从而隐藏子元素
- z-index 设置为负值,使层叠级别变低而被覆盖
- transform:scale(0,0),设置缩放
标准流、浮动流、浮动带来的影响
① 首先明确标准流的规则:
- 一个页面从上到下,分作一行一行。
- block块级元素独占一行
- inline行内元素和inline-block行内块元素不独占一行,在每一行中从左到右排列将该行占满
② 为什么要有浮动,浮动流是什么?
- 最初,浮动的出现只是想实现 文字环绕 这一效果。
- 后来,我们想要让 block块级元素能够在同一行显示,而不是像往常一样块级元素独占一行。
- 显然,标准流无法满足我们的需求
- 所以,需要将元素设置为浮动,成为浮动流。
③ 若某元素设置float:left或者是float:right,会页面发生以下变化:
- 元素本身脱离标准流,成为浮动流
- 剩下的元素成为新的标准流
- 设置浮动的元素,会向左向右浮动,直至碰到父元素或浮动元素
④ 浮动带来的影响
- 1、对元素自身:元素若设置了float属性,那么它就变成了block块级元素(不独占一行),可以设置width,hight,padding和margin
- 2、对父元素:子元素设置float,若其高度大于父元素的高度,或者父元素不便设置高度,那么会出现父元素塌陷
- 3、对兄弟元素:自身是浮动元素则脱离标准流,剩下的元素成为新的标准流,则会影响页面布局
清除浮动的方式
① clear:both
- 在浮动元素后面,添加一个div class='clear’元素
- 选择题设置为 clear:both,清除所有浮动
- 评价:并不推荐:添加了无意义代码,破坏html的语义性;若需要多次清除浮动,则需要多次添加无意义标签
② clear:both + ::after 伪元素
.clearfix{
*zoom:1; // 解决IE6 IE7的浮动问题
}
.clearfix::after{
display:block;
content:'';
height:0;
clear:both;
}
③ 考虑使用BFC
两栏布局的实现
两栏布局:左边定宽,右边自适应
实现一、 利用BFC
- 左边盒子设置float:left左浮动,且设置width为定宽;
- 右边盒子设置overflow:hidden,触发BFC
实现二、 利用flex布局
- 父盒子设置display:flex
- 左边盒子设置定宽width
- 右边盒子设置flex:1 (flex-grow为1)
实现三、 利用Grid布局
- display:grid 生成grid容器
- grid-template-columns: 200px auto;
三栏布局的实现
实现一、 利用flex布局
- 父盒子设置display:flex,且设置justify-content:space-between(两边对齐)
- 左盒子右盒子设置定宽
- 中间盒子设置width:100%,或者flex:1(flex-grow为1);可自动填满
实现二、 利用Grid布局
- 父盒子设置display:grid;width:100%
- 父盒子设置grid-template-columns:左定宽 auto 右定宽
Grid布局 —— 网格布局
一、几个基本容器属性:
- display:grid 或 display: inline-grid : 创建一个Grid容器
- grid-template-columns 和 gird-template-rows :在Grid容器中声明有几个列项目和有几个行项目。行项目与列项目的交集处会产生单元格。
- grid-row-gap 和 grid-column-grid 和 grid-gap :设置行间距、列间距和间距(row and column)。
基本使用:
宽度均为200px的三列、高度均为50px的两行、行间距与列间距均为5px
.wrapper{
display:grid;
grid-template-columns: 200px 200px 200px;
grid-template-rows: 50px 50px;
grid-gap:5px;
二、几个关键字:
- repeat()函数 : 用于创建相同的行或列。
- auto-fill : 自动填充,让水平方向或竖直方向尽可能容纳更多的列项目或行项目。简单来说就是尽可能创建多一些行项目或列项目。
- auto:让浏览器决定长度 (自适应,自动填充)
- fr:表示宽度或高度的比例关系
grid-template-columns:repeat(3,200px);
// 在网格容器内重复创建3个宽度为200px的列项目
grid-template-columns:repeat(auto-fill,200px);
// 在网格容器内尽可能创建多个宽度为200px的列项目
grid-template-columns:200px auto 200px;
// 左列项目和右列项目均为定宽200px。中间列项目则由浏览器决定,可做到自适应,自动填充,即用于自适应三栏布局。
grid-template-columns:200px 1fr 3fr;
// 在网格容器内创建三个列项目。第一列为200px,第二列占剩下宽度的1/4,第三列则占剩余宽度的3/4。
三、设置单元格内的内容的位置:justify-items, align-items, place-items
- justify-items设置的是单元格的内容的水平位置
- align-items设置的是单元格的内容的垂直位置
- 取值都是:start | end | center | stretch (对应的是单元格起始边缘、单元格的结束边缘、单元格内居中、拉伸占满整个单元格)
- place-items: align-items jusitfy-items
四、整个内容区域在Grid容器的位置:justify-content, align-content, place-content
.container {
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
- justify-content:center,则让整个内容区域在水平方向上处于Grid容器的中间;
- justify-content:space-between,则让列项目两边对齐,间隔相等
——————————————————————
项目属性:
指定项目的位置:grid-column和grid-row
- grid-column-start 指定项目的左边框处于哪条垂直网格线
- grid-column-end 指定项目的右边框处于哪条垂直网格线
- grid-row-start 指定项目的上边框处于哪条水平网格线
- grid-row-end 指定项目的下边框处于哪条水平网格线
.item-1 {
grid-column-start: 2;
grid-column-end: 4;
}
则1号项目的左边框压住第二条网格线,右边框压住第四条网格线。
Flex布局 —— 弹性布局
基本概念
- display:flex 或 display:inline-flex 创建一个Flex容器
- Flex容器内部的成员,叫项目 item
- Flex容器有两根轴:水平的主轴和竖直的交叉轴
- 主轴开始和结束的地方分别叫main start 和 main end;交叉轴开始和结束的地方分别叫 cross start 和 cross end
- 项目在主轴方向上占据叫主轴空间main size;项目在交叉轴方向上占据的叫交叉轴空间cross size
作用于整个flex容器 —— 容器属性:
- flex-direction: row | row-reverse | column | column-reverse (决定了主轴的方向,实际上也是决定项目在Flex容器的排布方向)
- flex-wrap: nowrap(default) | wrap | wrap-reverse (默认不换行,换行且第一行在上方,换行但第一行在下方)
- flex-flow: flex-direction | flex-wrap
- justify-content: flex-start(default) | flex-end | center | space-between | space-around (定义项目在主轴上的对齐方式:左对齐、右对齐、居中、两端对齐且间距相等、每个项目的两边距离)。默认是左对齐
- align-items:flex-start | flex-end | center | baseline | stretch(default) (定义项目在交叉轴上的对齐方式:交叉轴的起点、交叉轴的终点、交叉轴的中点、项目第一行文字基线对齐、拉伸占满整个容器的高)。默认是拉伸占满
作用于容器内的项目 —— 项目属性
- order 定义flex容器内项目的排列顺序,数字越小,排得越靠前
- flex-grow 定义项目的放大比例(若有空闲的空间),默认为0
- flex-shrink 定义项目的缩小比例(若空间不足),默认为1
- flex-basis 在分配多余的空间之前,用于定义该项目所占据的主轴空间main size,默认值为auto,即项目本身的大小。根据此属性,可以判断是否有多余的主轴空间。
- flex :flex-grow flex-shrink flex-basis
- align-self 允许项目拥有自己独特的对齐方式。可以取六个值:auto(default 继承父元素的align-items) | flex-start | flex-end | center | baseline | stretch
margin外边距叠加
官方对此现象的描述:
两个或多个毗邻的普通流的块元素的垂直方向上的margin会叠加
”两个或多个毗邻“修饰的并不是块元素,而是margin,也就是单个块元素的两条margin若是毗邻,满足条件也会叠加,没有限制非得是两个块级元素。
发生叠加的两个或多个margin外边距应该满足以下四个条件:
- 处于普通流的
- 属于块元素
- 是垂直方向上的
- 得是相邻的
margin外边距发生叠加的三种情况:
- ① 垂直方向上,相邻的margin-top与margin-bottom会发生叠加(注意:相邻指的并非相邻兄弟元素,而是相邻的margin-top和margin-bottom,是两个外边距挨在一块!)
- ② 当元素之间有包含关系时,外层的margin-top与内层的margin-top会发生叠加
- ③ 当是空元素时,其margin-top和margin-bottom会发生叠加;或者遇到另外一个元素的margin,先把自己的margin叠加合并,再与另一元素的margin叠加
外边距叠加的计算规则:
- 如果二者都是正值,则取最大值
- 如果二者一正一负,则将负值取绝对值,再用正值减去最大值
- 如果二者都是负值,则全取绝对值,再用 0 减去最大值
外边距叠加发生的解决(破坏上述四点原因):
- 不再处于普通流(设置float不为none,设置position为absolute,使元素脱离标准流)
- 不是块元素
- 不是垂直方向上永远不会叠加
- 不让margin之间直接相邻(设置一些border、padding或者其它内容使其分隔开)
BFC
概述:
- BFC 英文是 block formatting context,翻译作块级格式化上下文;
- BFC 是一个仅有块级盒子参与的独立渲染区域
- BFC 规定了其参与元素在此独立渲染区域内的布局规则
- BFC 是一个独立渲染区域,不影响外界
可以通过一定的条件触发,从而创建BFC:
- 根元素
- float不为none
- overflow不为visible
- position不为static,relative
- display为 inline-block,flex,inline-flex,table-caption,table-cell
BFC的特点:
- ① 在一个BFC内,内部元素会在垂直方向上由上而下一个个排列;
- ② 在一个BFC内,垂直方向上,相邻的外边距margin会发生叠加;
- ③ 计算BFC的高度,浮动元素也会参与计算;
- ④ 在一个BFC内,所有元素(包括浮动元素)的左外边界(margin-left)都会紧挨着容器的左边(border-left);
- ⑤ 在一个BFC内,若内部有元素是新的BFC,也有内部元素为浮动元素,该新的BFC不会与浮动元素重叠
BFC的用途:
- 消除相邻外边距叠加 —— 可以再创建BFC,使得两个相邻外边距不属于同一个BFC,则不会发生叠加现象;另外也可适当添加padding或border,使得二者外边距隔开从而非相邻。
- 清除浮动带来的影响 —— 若子元素是浮动元素,父元素又不便于设置高度时,会发生高度塌陷的情况。若是使其都在一个BFC内(给父元素设置overflow:hidden),则计算BFC高度时,浮动元素也会参与计算。则不会发生坍塌。
- 创建自适应两列布局 —— 左盒子定宽且浮动,右盒子设置overflow:hidden创建BFC。若右盒子不创建BFC,二者都会符合第四条规则紧挨着容器的左边框;当右盒子创建了BFC,则符合第五条规则,新的BFC不与浮动元素重叠。
层叠上下文与层叠级别
层叠上下文、层叠级别
元素水平居中 / 垂直居中的方法
水平居中 / 待处理元素是行内元素:
- 若父元素为块级元素,则为父元素设置 “text-align:center”
- 若父元素非块级元素,则为父元素设置 “display:block;text-align:center”
水平居中 / 待处理元素是块级元素:
-
若待处理元素定宽,则为其设置 “margin: 0 auto”
-
若待处理元素不定宽,则为其设置 “display: inline-block 或 display: inline”。父元素再设置 “text-align:center”
现在换个思路,子绝父相,使用position
-
若待处理元素(子元素)定宽,设置子元素"left:50%“,再设置"transform:translateX(-50%)” 或 “margin-left: - 子元素宽度的一半”
-
若待处理元素(子元素)不定宽,设置子元素"left:50%“,再设置"transform:translateX(-50%)”
再可以试试flex
-
父元素设置 display:flex 和 justify-content:center
垂直居中 / 待处理元素为行内元素:
-
若待处理元素为单行行内元素,则设置子元素行高与父元素高度相同即可。即 line-height:height
-
若待处理元素为多行行内元素,父元素设置"vertical-align:middle"
子绝父相也可以处理垂直居中
-
设置好position。若待处理子元素是定高度,则可设置 top:50%,再设置transform:translateY(-50%) 或 margin-top: - 子元素高度的一半
-
设置好position。若待处理子元素不定高度,可以设置 top:50%,再设置transform:translateY(-50%)
也可以用flex
-
父元素设置display:flex,再设置 align-items:center
深入了解vertical-align
深入了解line-height
CSS3新增特性
一、新增简单过渡transition
transition: property duration timing-function delay
- property:设置过渡效果CSS属性名称
- duration:设置完成过渡效果需要多久
- timing-function:指定速度曲线
- delay:指定过渡开始的延迟时间
二、新增复杂动画animation
animation: name duration timing-function delay iteration-count direction
- name:规定绑定到选择器的Keyframe名称
- duration:设置动画完成的时间
- timing-function:指定速度曲线
- delay:指定动画开始的延迟时间
- iteration-count:规定动画播放次数
- direction:规定是否应该轮流反向播放动画
三、新增元素转换transform
旋转:
- transform:rotate(90deg);
- transform:rotateX(90deg);
- transform:rotateY(90deg);
- transform:rotateZ(90deg);
- transform:rotate3d(x,y,z,angle)
倾斜:
- transform:skewX(10deg)
- transform:skewY(10deg)
缩放:
- transform:scaleX(0.5)
- transform:scaleY(0,5)
平移:
- transform:translateX(-50%)
- transform:translateY(-50%)
四、新增阴影倒影
- box-shadow
- box-reflect
- text-shadow
五、新增边框radius
六、新增颜色
- RGBA ( Red Green Blue Alpha )
- HLSA ( 色度 饱和度 亮度 Alpha)
flex弹性布局、grid栅格布局也是新增的
transition和animation的区别
- transition是简单过渡,只有开始和结束两帧;animation是复杂动画,可通过keyframes绘制每一帧
- transition需要hover或js事件触发;animation可以自主播放
- transition只能发生一次;animation可以通过设置iteration-count来设定播放次数
@keyframes animat
{
0% {background:red;}
25% {background:yellow;}
50% {background:blue;}
100% {background:green;}
}
重排reflow与重绘repaint
概述:
- 回流 / 重排 :当Rendering Tree 中部分元素的尺寸大小、布局、隐藏等属性改变时,浏览器的布局需要调整,则需要重新渲染DOM。这个过程就叫回流。回流也叫重排(对整个页面进行重新排版)。
- 重绘 : 当元素属性的改变不影响DOM Tree的结构,即不会影响浏览器的布局,只是“表象”发生变化(如background-color,visibility等),那么针对新样式对元素进行重新绘制。
- 回流一定会引起重绘,重绘不一定引起回流
- 回流需要重新计算、渲染DOM,处理Rendering Tree,其开销比重绘要大
何时发生 回流 / 重排
- 与DOM元素有关:添加或删除可见元素、元素位置发生变化、元素尺寸大小发生变化
- 访问特定属性:offsetTop/offsetLeft/offsetWidth/offsetHeight、scrollTop/scrollLeft/scrollWidth/scrollHeight、clientTop/clientLeft/clientWidth/clientHeight
- 调用特定方法:getComputedStyle()、getBoundingClientRect()、currentStyle()
- 发生特定事件:页面初始化渲染、浏览器窗口尺寸改变resize事件
如何减少
- 统一批量修改样式,避免逐次修改
- 使DOM脱离文档流
- 缓存布局属性
- position脱离文档流
- CSS3硬件加速
具体参考:回流与重绘以及减少的方案
响应式设计
响应式网站设计的概述:
- 页面的设计和开发应当根据用户行为及设备环境(系统平台、屏幕尺寸、屏幕定向等)进行相应的响应和调整。
- 能同时适配PC、平板以及手机
页面头部meta声明viewport,以支持移动端:
@media screen (min-width: 375px) and (max-width: 600px) {
body {
font-size: 18px;
}
}
二、rem
rem 是 root em,即相对于根元素html的font-size字体属性计算出大小,默认情况下浏览器的font-size为16px,即1rem=16px;
可以配合Media查询,在不同媒体类型条件下设置不同的html font-size,rem则可以因此根据不同的font-size作出调整
三、百分比单位
- 子元素的top/left和bottom/right若设置百分比,则相对于最近一个非Static父元素的高度和宽度
- 子元素的padding和margin若设置百分比,都是相对于父元素的width
- 子元素的border-radius若设置百分比,是相对于自身width计算
优点:
缺点:
- 某种程度上来说,效率偏低
- 代码累赘,针对某种类型都得编写相应的样式代码
CSS的性能优化
CSS的性能优化可以从以下几个方面考虑:
一、CSS的渲染
① 内联首屏关键CSS
- 页面首要关键内容呈现给用户的时间直接影响用户的体验
- 内联关键CSS,可以使html文档下载解析完成后,立刻渲染
- 若CSS加载解析时间较长(放在文档尾部或是引用外部CSS文件),有可能引起白屏或FOUS的不良问题
② 慎用高性能属性如:浮动、定位、box-shadow、box-radius
③ 减少页面的重排、重绘
④ 考虑使用雪碧图
二、CSS的加载
CSS的加载会阻塞对文档的解析。
① 利用媒体查询 media
- 设置link标签media属性为一个当前浏览器所不支持的值。浏览器会认为该资源的优先级较低,会在不阻塞页面解析渲染的情况下加载这份资源。
- 设置link标签的onload,使得加载完后改变media值变回all,从而开始解析
<link rel="stylesheet" href="mystyles.css" media="nonono" onload="this.media='all'">
② 提前加载资源 preload
- 使得资源的优先级最高,异步且最先加载
- 等需要时,浏览器直接从缓存中获取
- rel设置为preload
- 设置onload,使得加载完后改变rel值变回stylesheet
<link rel="preload" href="./index.css" onload="this.rel='stylesheet'">
③ 设置rel为可选样式表
- 通过rel设置为 alternate stylesheet,标记资源为可选样式表
- 设置onload,使得加载完后改变rel值变回stylesheet
<link rel="alternate stylesheet" href="mystyles.css" onload="this.rel='stylesheet'">
④ 使用link而不是@import
三、关于CSS选择器的使用
主要是避免冗杂无用的遍历匹配和避免重复书写CSS代码
减少冗杂无用的遍历:
- 避免使用通配符选择器,计算次数太多
- 如果规则中有ID选择器作为关键选择器,没有必要再添加规则
- 能用class选择器就不要通过标签选择器去匹配
- 尽量不要用后代/子代选择器。因为样式系统会遍历所有的后代/子代元素,再去判断后续规则是否满足。
- 尽量降低选择器深度,免得层层遍历(就像写太多的for循环),最高不要超过3层
避免重复书写:
- 应当了解哪些属性是可以通过继承得到的,避免重复书写相同的规则。
四、压缩
- webpack、gulp/grunt等工具进行资源压缩
单行或多行文本溢出省略样式
若是单行文本
- white-space : nowrap 设置文本不换行
- overflow:hidden 隐藏溢出的元素
- text-overflow: ellipsis 文本溢出时显示 ‘…’省略标记;若为clip则是裁剪掉溢出部分
若是多行文本,可以基于高度或基于行数:
基于高度进行截断:
.text {
position: relative;
line-height: 20px;
height: 40px;
overflow: hidden;
}
.text::after {
content: "...";
position: absolute;
}
常见动画(CSS3)
一、transition : property duration timing-function delay
- property 设置过渡效果CSS属性名称
- duration 设置完成过渡效果需要多久
- timing-function 指定速度曲线
- delay 指定过渡开始的延迟时间
二、animation : name duration timng-function delay iteration-count direction
- name 规定绑定到选择器的Keyframe名称
- duration 设置动画完成的时间
- timing-function 指定速度曲线
- delay 指定动画开始的延迟时间
- iteration-count 规定动画播放次数
- direction 规定是否应该轮流反向播放动画
三、transform
旋转
- transform:rotate(90deg);
- transform:rotateX(90deg);
- transform:rotateY(90deg);
- transform:rotateZ(90deg);
- transform:rotate3d(x,y,z,angle);
倾斜
- transform:skewX(10deg)
- transform:skewY(10deg)
缩放
- transform:scaleX(0.5)
- transform:scaleY(0,5)
平移
- transform:translateX(-50%)
- transform:translateY(-50%)
非CSS部分:
四、Canvas
五、Gif
六、原生JS
link和@import
- 二者都是引入外部CSS的方法:link是链接法,@import是导入法
- link是html元素,无兼容性问题;@import是CSS提供,IE5才能识别
- 使用link,是一边载入页面一边载入样式效果,使用体验良好;使用@import,则是加载完页面才载入样式。
- link的优先级高于@import。
- link除了引入CSS文件,还可以引入图标icon等其它信息;而@import只能引入CSS文件。
- link支持JS去控制DOM改变样式;@import不支持。
setTimeout和setInterval执行动画的缺点
setTimeout与setInterval执行动画的缺点,源于它们自身的特性;
setTimeout超时调用可能会卡顿、掉帧:
- 超过一定时间后,将待执行任务插入执行队列(宏任务)。当主线程任务执行完毕后,才会执行宏任务队列,所以即使超过一定时间,待执行任务也不是立即调用。
- setTimeout设置的时间间隔不一定与屏幕刷新间隔时间相同
setInterval卡顿掉帧,还可能会浪费CPU资源
- setInterval设置的间隔调用,若不通过clearInterval取消定时器。它将不断地执行直至页面卸载。若页面处于不可见的状态,setInterval仍继续执行动画任务,此时刷新动画完全是浪费CPU资源
- 若定时器待执行的函数func()需要执行的时间长于间隔时间t,如长到第二次触发定时器时,第一次func()还没有执行完。那么第二次func()就只能进入任务队列等待调度。这样函数的执行间隔时间就不是t了。
- 若第一个func()执行时间特别长,长到后续触发了第二个、第三个func(),都还没有处理完。那么会导致第三个func()及以后的函数被忽略。因为任务队列里不能同时有两个及以上同一个定时器的回调函数。
requestAnimationFrame 请求动画帧
HTML5提供requestAnimationFrame(请求动画帧),专用于请求动画
window.requestAnimationFrame(callback)
- 希望执行一个动画,并且在下一次重绘之前调用指定的回调函数callback更新动画
- callback属于宏任务
优点:
- CPU节能:页面处理是未激活状态时,该页面的屏幕刷新任务也会被系统暂停,跟着系统走的requestAnimationFrame也会停止渲染;当页面处理重新激活,动画会从上次停留的地方继续。()
- 函数节流:requestAnimationFrame可以保证每个刷新间隔内,函数只执行一次。一个刷新间隔内函数执行多次是没有意义的,多次绘制也不会显示出来
- 合并DOM:在每次重绘或重排中集中每一帧的所有DOM
inline与inline-block之间的空白间隙
- 当元素为inline或inline-block时,元素之间的空白字符会被浏览器处理,即代码中的回车换行转换成一个空白字符。
- 若font-size不为0,空白字符也就占据了一定的宽度,则出现了空白间隙
解决:
- 代码写在同一行,不人为留下换行回车。缺点:可读性差、稳定性差(一旦修改代码排版,效果就消失)
- 父元素设置font-size:0,子元素重新设定font-size。缺点:增加代码量
- 最优:父元素设置display:table和word-spacing
替换元素
典型的替换元素有:
CSSSprites
CSSSprites 精灵图 :将很多小图片合并到一张较大的图片,利用CSS的background-image插入,再用background-repeat、background-position进行定位等。
这样只需要加载一张大的图片,而不是一次一次请求加载小的图片
优点:
- 有效减少网页的http请求,从而提高了性能
- 减少图片的字节:三张图片合成一张图片的字节总量小于三张图片的字节总和
缺点:
- CSS精灵图的制作比较麻烦,需要借助Photoshop等工具来对每个小图片做精准测量
- CSS精灵图的维护比较麻烦,若页面背景有变动,则需要相应修改精灵图,甚至还要调整CSS样式
物理像素、逻辑像素和像素密度
物理像素: 设备屏幕实际拥有的像素点。如iPhone 6的屏幕在宽度方向有750个像素点,高度方向有1334个像素点,所以iPhone 6 总共有750*1334个物理像素。
逻辑像素: 也叫“设备独立像素”(Device Independent Pixel, DIP),可以理解为反映在CSS/JS代码里的像素点数。
像素比例: 也称设备像素比,它等于 物理像素/逻辑像素;
当像素比例越高,说明一个逻辑像素里容纳了更多的物理像素。换句话说,像素比例越高,是用更多的物理像素来渲染一个逻辑像素。
像素比例越高的结果是:更加精细
为什么移动端开发需要@2x或@3x的图片
至少要让一个位图像素对应着一个物理像素,才不会显示失真
一张图片如果是375*200 = 75000个位图像素;
如果是2倍屏,那么像素比例是2(设备像素比是2),1个逻辑像素=2个物理像素,也就是需要2个物理像素来渲染一个逻辑像素;
那么就需要准备75000*2 = 150000 位图像素的图片,才能保证一个位图像素对应着一个物理像素,才能在2倍屏上正常显示。
否则本需要15000物理像素显示的图片,却只有75000像素,那么当然会失真,模糊了。
sass、less
- sass和less都是CSS的预处理器
- 增加了一些编程特性,如:变量、混合、嵌套、函数、作用域等常用功能,无需考虑浏览器的兼容问题
好处:
- 关于编写:提高代码复用性,简化编写,提高效率
- 关于维护:可读性强、更加简洁、方便维护
变量
@width: 10px;
@height: @width + 10px;
#header {
width: @width;
height: @height;
}
混合Mixins(将一部分样式一起抽出,作为单独的模块,可供其它选择器重复使用,也可接受参数)
.bordered {
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
#menu a {
color: #111;
.bordered();
}
.post a {
color: red;
.bordered();
}
预处理器、后处理器
预处理器:
- 常见的有less、sass、stylus
- 增加了一些编程特性,如:变量、混合、嵌套、函数、作用域等常用功能,无需考虑浏览器的兼容问题
好处:
- 关于编写:提高代码复用性,简化编写,提高效率
- 关于维护:可读性强、更加简洁、方便维护
后处理器:
- 常见的有postCss
- 常用功能:为CSS属性添加浏览器私有前缀,实现跨浏览器兼容性问题
CSS 工程化 **
-----------------------------------
实现九宫格
实现三角形
通过CSS画三角形,实际上靠的是border属性
- div盒子的width和height设置为0;
- 设置四条边的border
div {
width: 0;
height: 0;
border: 100px solid;
border-color: orange blue red green;
}
逐渐调整transparent,可以得到各种三角形
- 保留border-top,不要border-bottom -> 只要上面的三角形
- 在此基础上,border-right和border-left设置为transparent,左右两半都留下。
div {
width: 0;
height: 0;
border-top: 50px solid red;
border-right: 50px solid transparent;
border-left: 50px solid transparent;
}
还有
- 同样保留border-top,没有border-bottom
- 这次只有border-right设置了transparent,只保留上块三角形的右半部分。
div {
width: 0;
height: 0;
border-top: 100px solid red;
border-right: 100px solid transparent;
}
实现扇形
扇形的绘制,是在三角形的基础上加上border-radius
div{
border: 100px solid transparent;
width: 0;
height: 0;
border-radius: 100px;
border-top-color: red;
}
实现圆和半圆
实现圆,设置border-radius:50%
div {
width: 100px;
height: 100px;
background-color: red;
border-radius: 50%;
}
实现半圆
- border-radius : border-top-left-radius border-top-right-radius border-bottom-right-radius border-bottom-left-radius
- border-radius的顺序是:左上角、右上角、右下角、左下角
- 不同于其它的“上右下左”
div {
background-color: red;
width: 100px;
height: 50px;
border-radius: 0px 0px 100px 100px;
}
实现宽高自适应的正方形
实现梯形
-----------------------------------
画一条0.5px的线
方法一、transform:scale(),设置缩放
#line{
border-bottom:1px solid black;
transform:scale(0.5,0.5);
}
方法二、meta标签,设置initial-scale等 (仅适用于移动端)
"viewport" content="width=device-width, initial-scale=0.5, minimum-scale=0.5, maximum-scale=0.5"/>
设置小于12px的字
当font-size设置小于12px时,在chrome显示都是12px
chrome浏览器内核是webkit
方法一、使用webkit内核的属性 -webkit-text-size-adjust
.smallerFont{
-webkit-text-size-adjust:none;
}
- 最新版的chrome已经不支持 -webkit-text-size-adjust 属性
方法二、CSS3的transform:scale
<p><span>我是一个小于12PX的字体span>p>
span{
display:inline-block;
-webkit-transform:scale(0.8);
}
- 需要设置span专门放文字,否则缩放会把整个p元素变小
- 缩放是对可设置宽高的元素起作用,所以需要将span转为行内块元素(可设置宽高)
Retina屏幕上的1px问题
原因:
1px问题:在一些Retina屏幕上,移动端上的1px看着比1px要粗!
其实还是关于 物理像素、逻辑像素与像素密度 的问题;
Retina屏幕都有一定的像素密度,譬如输出后为2;
即 物理像素 / 逻辑像素 = 2;
可以解读为,在这个Retina屏幕上:
- 一个逻辑像素用了2个物理像素来描绘
- 需要2个物理像素来描绘1个逻辑像素
那么设置1px逻辑像素,实际在屏幕上是用了2个物理像素来描绘这一条线,所以看着是比1px要粗的!
解决:
① 直接写0.5px
- 获得像素密度 window.devicePixelRatio
- 利用属性选择器,匹配具有data-device属性的字体,并且该属性值为2,将其设置为0.5px
<div id="container" data-device={{window.devicePixelRatio}}>div>
#container[data-device="2"] {
border:0.5px solid #333
}
② 利用meta标签,设置initial-scale等属性
<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">