css
title: CSS
date: 2019-08-23 16:54:50
tags: css
categories: # 这里写的分类会自动汇集到 categories 页面上,分类可以多级
- css # 一级分类
- css3 # 二级分类
介绍
css,即层叠样式表,可以为网页添加样式.
stylesheet
应用方式
外部样式表
- 通过
<link>
引入
<link rel="stylesheet" href="index.css">
2. 通过@import
引入,注意末尾加;号,CSS 语法,只能在 CSS 内使用.
1 | <style>@import url("index.css"); @import "index.css";</style> |
- 媒体查询(响应式)
1 | <style> |
内部样式表
将 css 放到<style>
元素中,一般放到文档的<head>
中.
1 | <!doctype html> |
内联样式
<p style="background: red; font-size: 20px;">AMD yes!<p>
CSS 选择器
基本选择器 | 名称 | 含义 |
---|---|---|
* | 通用选择器 | 匹配任何元素 |
E | 标签选择器 | 匹配所有使用 E 标签的元素 |
.info | class 选择器 | 匹配所有 class 属性中包含 info 的元素 |
#footer | id 选择器 | 匹配所有 id 属性等于 footer 的元素 |
组合选择器 | 名称 | 含义 |
---|---|---|
E,F | 多元素选择器 | 同时匹配所有 E 元素或 F 元素 |
E F | 后代选择器 | 匹配所有属于 E 元素后代的 F 元素 |
E>F | 子元素选择器 | 匹配所有 E 元素的直接子元素 |
E+F | 直接相邻元素选择器 | 匹配 E 元素后的直接相邻元素 |
E~F | 兄弟元素选择器 | 匹配 E 元素后的所有兄弟元素 |
属性选择器 | 含义 |
---|---|
E[attr] | 匹配所有具有 attr 属性的 E 元素 |
E[attr=val] | 匹配所有 attr 属性等于 val 的 E 元素 |
E[attr~=val] | 匹配所有 attr 属性具有多个空格分隔的值,其中一个等于 val 的 E 元素 |
E[attr | =val] |
E[attr*=val] | 匹配所有 attr 属性中包含 val 的 E 元素 |
E[attr^=val] | 匹配所有 attr 属性中以 val 开头的 E 元素 |
E[attr$=val] | 匹配所有 attr 属性中以 val 结尾的 E 元素 |
伪类 | 含义 |
---|---|
E:first-child | 匹配父元素的第一个子元素 |
E:link | 匹配所有未被点击的链接 |
E:visited | 匹配所有已被点击的链接 |
E:active | 匹配鼠标已经按下没有释放的 E 元素 |
E:hover | 匹配鼠标悬停其上的 E 元素 |
E:focus | 匹配获得焦点的 E 元素 |
E:enabled | 匹配表单中激活的元素 |
E:disabled | 匹配表单中禁用的元素 |
E:checked | 匹配表单中被选中的 radio 或者 checkbox 元素 |
E:root | 匹配文档的根元素,对于 html 文档,就是 html 元素 |
E:nth-child(n) | 匹配其父元素的第 n 个子元素,第一个编号为 1 |
E:nth-last-child(n) | 匹配其父元素的倒数第 n 个子元素,第一个编号为 1 |
E:nth-of-type | 与 nth-child 类似,但仅匹配使用同种标签的元素 |
E:nth-last-child | 与 nth-last-child 类似,但仅匹配使用同种标签的元素 |
E:last-child | 匹配父元素的最后一个元素 |
E:first-of-type | 匹配父元素下使用同种标签的第一个子元素 |
E:last-of-type | 匹配父元素下使用同种标签的最后一个子元素 |
E:only-child | 匹配父元素下仅有的一个子元素,等同于:first-child:last-child 或 :nth-child(1):nth-last-child(1) |
E:only-of-type | 匹配父元素下使用同种标签的唯一一个子元素,等同于:first-of-type:last-of-type 或 :nth-of-type(1):nth-last-of-type(1) |
E:empty | 匹配一个不包含任何子元素的元素,注意,文本节点也被看做子元素 |
E:not(s) | 匹配不符合当前选择器的任何元素 |
E:target | 代表一个唯一的页面元素(目标元素),其 id 与当前 URL 片段匹配 |
伪元素 | 含义 |
---|---|
E::first-line | 匹配 E 元素的第一行 |
E::first-letter | 匹配 E 元素的第一个字母 |
E::before | 在 E 元素之前插入生成的内容 |
E::after | 在 E 元素之后插入生成的内容 |
E::selection | 匹配用户当前选中的元素 |
伪元素必须要有
content
伪元素和伪类的区别
- 伪元素使用两个冒号,伪类使用一个冒号
- 伪元素添加了一个页面中没有的元素(只是从视觉效果上添加了,不是在文档树中添加),伪类是给页面中已经存在的的元素添加一个类.
CSS 选择器有哪些?哪些属性可以继承?
1.id 选择器( # myid)
2.类选择器(.myclassname)
3.标签选择器(div, h1, p)
4.相邻选择器(h1 + p)
5.子选择器(ul > li)
6.后代选择器(li a)
7.通配符选择器( * )
8.属性选择器(a[rel = “external”])
9.伪类选择器(a:hover, li:nth-child)
可继承的样式: font-size
font-family
color
, ul
li
dl
dd
dt
;
不可继承的样式:border
padding
margin
width
height
;
选择器优先级
!important
优先级最高(由于 IE 不支持!important,所以也可以利用它区分不同的浏览器。)
同权重: 内联样式表(标签内部)> 嵌入样式表(当前文件中)> 外部样式表(外部文件中)
行内样式(写在 style 标签里的样式) > id 样式 > class 样式 > 标签名样式
CSS 基本样式
div(块级元素):高度是由内部文档流元素高度的总和决定的。文档流:文档内元素的流动方向,内联元素是从左往右,块级元素是从上往下
span(内联元素):高度是由其中文字高度决定的,内联元素设置 width 和 height 是无效的,上下的 margin 和 padding 也无效,要将它们设为display:inline-block
才有效。
- 常见块级元素:
div h1~h6 p hr form ul ol li table td tr th dl dt dd pre
- 常见内联元素:
em strong span a br img button input label select textarea code script
尽量不写 height 和 width,这两个属性会引出很多 bug,要宽高的时候可以用 padding,但 img 最好先写 width,因为可以先占位,因为引用图片时浏览器不知道图片大小,所有等图片下载完成,它后面的元素又要重新排位置,若先写好 width,则不用重排,知道 height 也可以先写好 height。
另外 span 元素设置 padding 的时候要将它设为 display:inline-block,因为内联元素不能设置宽高,inline-block 具有 inline 的同行特性,也具有 block 的高度特性。
对于 display:inline(内联元素)的元素,设置 width/height/上下 margin 和 padding 都是无效的
inline-block
- inline-block 之间空隙
- inline-block 之间有空格、Tab、换行符。
- 给父元素设置 font-size: 0,在 inline-block 元素上重新设置 font-size。
- inline-block 导致父元素增高若干像素
- 给 inline-block 元素设置 vertical-align: top
通用解决办法 不要设置 inline-block,使用 float 或 flex。
浏览器默认样式
浏览器对某些元素设置有默认样式,如 h1, ul, li 等。
常见处理方式
- Normalize.css
- CSS Reset
- 简单去除
1 | * { |
CSS 常见样式
边框 border
1 | .box { |
实现不使用 border 画出 1px 高的线,在不同浏览器的标准模式与怪异模式下都能保持一致的效果。
<div style="height:1px;overflow:hidden;background:red"></div>
内边距 padding
padding: 10px 20px 30px;//按照上右下左,即顺时针,缺哪个补哪个,缺左边,按20px补上.
外边距 margin
margin 可以合写,可以分开.可以是数值,可以是百分比(相对于父元素).还可以是负值.有外边距合并问题
display
- 块级: block,list-item,table
- 行内: inline,inline-table,inline-block
inherit
: 规定应该从父元素继承 display 属性的值
display:inline-block 什么时候会显示间隙
移除空格、使用 margin 负值、使用 font-size:0、letter-spacing、word-spacing
font
1 | body{ |
Chrome 默认字体是 16px,最小字体是 12px.
文本
- text-aglin: 文本对齐方式,left,right,center,justify
- text-ident: 文案第一行缩进距离
- text-decoration: 划线,none,underline,line-through,overline
- text-transform: 改变文字大小写,none,uppercase,lowercase,captialize
- word-spacing: 可以改变字(单词)之间的标准间距
- letter-spacing: 字母之间的间隔
单行文本溢出加…
1 | .box>h3 { |
颜色
- 单词: red,blue,black,pink,yellow
- 十六进制: #000000(黑),#fff(白),#eee(淡灰),#ccc(灰色),#666(深灰)
rgb
:rgb(255,255,255)白色,rgba(0,0,0,0.5)透明度为 0.5 的黑色
单位
px rpx em rem
的区别
px
是像素 pixel,相对于屏幕分辨率的单位em
是相对单位,相对于当前对象内的文本尺寸。如果没有设置,则相对浏览器默认尺寸 16px,1em=16px。
为了简化,可以将 body 里 font-size=62.5%,那么 em 就是 16px*62%=10px。1em=10px
em 特点:em 值不固定,会继承父元素字体大小 3. rem
是 root em。只相对于 html 根元素 4. rpx
是微信小程序的方案,是响应式像素,可以根据屏幕宽度进行自适应。规定屏幕为 750rpx.物理像素
1px=2rpx 5. vh vw
: 相对单位,1vw 为屏幕宽度的 1%
background
background-color
: transparent 透明背景;颜色值;半透明浮层的背景颜色建议使用 rgba() 而不是 opacity 设置透明度。background-image
: url(../images/bg.png);// 属性用于给元素设置一张或多张背景图。background-repeat
控制背景图片的重复方式。no-repeat
不重复;repeat-x
水平方向重复;repeat-y
垂直方向重复;background-position
设置背景图的位置。x y
;x% y%
;[top|center|bottom][left|center|right]
background-size
设定背景图片的大小。IE9 以下不支持;cover
缩放背景图片以完全覆盖背景区,可能背景图片部分看不见;contain
缩放背景图片以完全装入背景区,可能背景区部分空白。background-clip
: 设置元素背景区域覆盖的范围.border-box 覆盖至边框的最外围;padding-box 覆盖至内边距的最外围;content-box 仅覆盖元素内容区域
缩写:
1 | .avatar { |
隐藏 or 透明
- opacity: 0;//透明度为 0,整体
- visibility: hidden;//和 opacity: 0;类似
- display: none;//消失,不占用位置
- background-color: rgba(0,0,0,0.2);//只是背景色透明
display:none 和 visibility:hidden 的区别
display:none
:
不占据任何空间,在文档渲染时,该元素如同不存在(但依然存在文档对象模型树中).会触发 reflow(回流),进行渲染.不是继承属性,元素及其子元素都会消失
visibility
:
该元素空间依旧存在.只会触发 repaint(重绘),因为没有发现位置变化,不进行渲染.是继承属性,若子元素使用了 visibility:visible,则不继承,这个子孙元素又会显现出
box-shadow
box-shadow: -16px 0 16px 1px rgba(102,102,102,0.4);
第一个值代表阴影左右偏移,正数往右,负数往左
第二个值代表上下偏移,正往下,负往上
第三个值越大,模糊面积越大越淡
第四个值取正值时,阴影扩大,取负值时,阴影收缩
line-height
- line-height: 2;//本身字体高度的 2 倍
- line-height: 200%;//父元素高度的 2 倍,父元素没写行高就是默认 16px*2=32px
- height=line-height;//垂直居中单行文本
盒模型
- 标准盒模型: border-box,即 padding,border 不在 width,height 范围内
- IE 盒模型: content-box,即 width=content 尺寸+padding+border
css3 可以设置
box-sizing: content-box;//标准盒模型
position
CSS position 属性用于指定一个元素在文档中的定位方式。
语法: static
| relative
| absolute
| sticky
| fixed
static
: 该关键字指定元素使用正常的布局行为,即元素在文档常规流中当前的布局位置。此时top, right, bottom, left 和 z-index
属性无效。relative:
该关键字下,元素先放置在未添加定位时的位置,再在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白)。position:relative
对 table 元素无效.absolute
: 不为元素预留空间,通过指定元素相对于最近的非 static 定位父元素的偏移,来确定元素位置。绝对定位的元素可以设置外边距(margins),且不会与其他边距合并。fixed
: 不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。fixed 属性会创建新的层叠上下文。当元素祖先的 transform 属性非 none 时,容器由视口改为该祖先。sticky
: 盒位置根据正常流计算(这称为正常流动中的位置),然后相对于该元素在流中的 flow root(BFC)和 containing block(最近的块级祖先元素)定位。在所有情况下(即便被定位元素为 table 时),该元素定位均不对后续元素造成影响。当元素 B 被粘性定位时,后续元素的位置仍按照 B 未定位时的位置来确定。
相对定位(relative)
相对定位的元素是在文档中的正常位置偏移给定的值,但是不影响其他元素的偏移。
绝对定位(absolute,fixed)
相对定位的元素并未脱离文档流,而绝对定位的元素则脱离了文档流。在布置文档流中其它元素时,绝对定位元素不占据空间。绝对定位元素相对于最近的非 static 祖先元素定位。当这样的祖先元素不存在时,则相对于 ICB(inital container block, 初始包含块)。
固定定位(fixed)
固定定位与绝对定位相似,但元素的包含块为 viewport 视口。该定位方式常用于创建在滚动屏幕时仍固定在相同位置的元素。
粘性定位(sticky)
粘性定位可以被认为是相对定位和固定定位的混合。元素在跨越特定阈值前为相对定位,之后为固定定位。
#one { position: sticky; top: 10px; }
在 viewport 视口滚动到元素 top 距离小于 10px 之前,元素为相对定位。之后,元素将固定在与顶部距离 10px 的位置,直到 viewport 视口回滚到阈值以下。(理解为大于 10px 时,属于相对定位,可以在页面滚动时随之滚动,当距视口 10px 时,固定了,就像粘在那里了)
浮动
float: left;//向左浮动
- 浮动元素并不是完全意义上的脱离文档流,至少普通元素里的文本可以发现,行内元素也可以发现
- 设置浮动会让块级元素从左到右或从右到左排列.
- 块级元素设置浮动呈现 inline-block 特性,不再撑开父元素,宽度也会收缩
- 行内元素设置浮动呈现 inline-block 特性,可以设置宽高.
清除浮动
问题:
- 对后续元素位置产生影响
- 父容器高度计算出现问题
清除浮动是为了清除使用浮动元素产生的影响。浮动的元素,高度会塌陷,而高度的塌陷使我们页面后面的布局不能正常显示。
通用解决方案
1 | 父元素加clearfix |
BFC(块级格式化上下文)
决定了其子元素将如何定位,以及其他元素的关系和相互作用
在正常流中的盒子要么属于块级格式化上下文,要么属于内联格式化上下文
BFC 的产生
- 根元素
- float 不为 none;
- position: absolute/fixed;
- display: inline-block/flex/inline-flex/table-cell;
- overflow 不为 visible;
特性
- 内部的 Box 会在垂直方向,一个接一个地放置。
- Box 垂直方向的距离由 margin 决定。属于同一个 BFC 的两个相邻 Box 的 margin 会发生重叠.每个元素的 margin box 的左边,与包含块 border box 的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。(如果有多个浮动盒,因为是浮动盒,所以后面的有新的 BFC,会挨着前面的从左到右排列)
- BFC 的区域不会与 float box 重叠。(不跟外面的浮动盒重叠,会把浮动盒挤到一边)
- BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
- 计算 BFC 的高度时,浮动元素也参与计算(包裹浮动元素).
作用
- 阻止 margin 合并,因为 BFC 与外界隔离,自己的 margin 也就不再合并.
- contain float(包裹浮动元素).
边距合并
合并场景
- 相邻元素合并,间距为二者中较大值
- 父子合并
- 自己合并
取消合并
- 加 border,padding
- BFC
居中
水平居中
- 块级元素水平居中
1 | margin-left:auto; |
- 内联元素水平居中,给它们的父元素加上
1 | text-align:center; |
若不是内联元素想让它居中,可加display:inline-block
,加了之后一般还要加下面这句,不然可能会有 bug(下面可能会空出一行)
1 | vertical-align: top; |
- 让导航栏横过来,并在同一行里均匀分布
给 ul 加 css
1 | ul{ |
去掉 li 的float:left
去掉 ul 的clearfix
垂直居中
- 若父元素没有写 height,则直接在父元素写
1 | padding: 10px 0; |
子元素就可以居中,所以尽量避免父亲高度确定
以下是宽高确定(注意写宽高)
- 让一个元素在父级元素中绝对居中
方法一:
给父级元素加:
1 | position: relative; //若父级元素是body可以不用加 |
再给自己加:
1 | div{ |
方法二:(若不兼容 IE,工作中只要用这一种方法即可,最简单,Chrome,移动端都可以用)
给父元素加:
1 | display: flex; //让它变成一个弹性盒 |
- table 自带居中(兼容 IE)
1 | <html> |
文字会居中
- 用 div 假扮 table(兼容 IE)
1 | <html> |
- 用 100%高度的 before 和 after
1 | .parent{ |
- 绝对定位加上 margin-top: -自身 height 的 50%
1 | <html> |
- 使用transform
子元素加{top:50%,transform:translate(-50%)}
CSS3 有哪些新特性?
新增各种 CSS 选择器 (: not(.input):所有 class 不是“input”的节点)
圆角 (border-radius:8px)
多列布局 (multi-column layout)
阴影和反射 (box-shadow\reflect)
文字特效 (text-shadow)
文字渲染 (Text-decoration)
线性渐变 (gradient)
旋转 transform:rotate(90deg)
缩放 transform:scale(0.85,0.90)
位移 transform:translate(0px,-30px)
倾斜 transform:skew(-9deg,0deg)
动画 Animation
CSS 动画
transition(过渡)
transition
的作用在于指定状态变化所需要的时间.
1 | div{ |
指定属性
可以指定transition
使用的属性,比如只适用于 height
transition: 1s height;
delay(延迟)
transition: 1s height,1s 1s width;
width 在一秒之后在开始变化,也就是延迟一秒.delay 可以指定动画发生的顺序,使得不同 transition 可以连在一起,形成不同效果.
transition-timing-function(缓动函数)
transition 的状态变化速度,默认不是匀速的,而是逐渐放慢的,这叫做 ease.
transition: 1s ease;
除了 ease,其他模式还有:
- linear: 匀速
- ease-in: 加速
- ease-out: 减速
- cubic-bezier: 自定义速度模式(可以在 cubic-bezier.com 里设置)
语法
简写:
transition: 1s 1s height ease;
完整写法:
1 | transition-property: height; |
注意
- transition 需要明确知道,开始状态和结束状态的具体数值,才能计算出中间状态,什么 none 到 block 之类的是不行的
- transition 是一次性的,不能重复发生,除非一再触发
animation(动画)
使用 animation 首先需要定义动画过程,即关键帧
1 | @keyframes rainbow { |
写动画帧里的 css 记得加
;
号.
定义关键帧后可以给 DOM 元素绑定动画,和事件比较像.加infinite
代表无限次,改成数字就是循环多少次.
1 | div:hover { |
animation-fill-mode
动画结束后,会立即跳到结束状态,如果想让动画保持在结束状态,需要使用 animation-fill-mode 属性.
1 | div:hover{ |
animation-fill-mode 的属性:
- none: 默认值,回到动画未开始的状态.
- forwards: 让动画停留在结束状态
- backwards: 让动画回到第一帧的状态
- both: animation-direction 轮流应用 forwards 和 backwards 规则
animation-direction
动画循环播放时,每次都是从结束状态跳回到起始状态,再开始播放。animation-direction 属性,可以改变顺序
默认情况是,animation-direction 等于 normal.此外,还可以等于取 alternate(先从前往后再从后往前)、reverse(从后往前)、alternate-reverse 等值.
1 | div:hover { |
animation-play-state
有时,动画播放过程中,会突然停止。这时,默认行为是跳回到动画的开始状态,如果想让动画保持突然终止时的状态,就要使用 animation-play-state 属性。
1 | div { |
语法
简写:
1 | div:hover { |
完整:
1 | div:hover { |
0%可以用 from 代表,100%可以用 to 代表,因此上面的代码等同于下面的形式
1 | @keyframes rainbow { |
steps(分步过渡)
浏览器从一个状态向另一个状态过渡,是平滑过渡。steps 函数可以实现分步过渡。
1 | div:hover { |
歌词效果
1 | <style> |
打字机效果
1 | <style> |
如果需要手动写动画,你认为最小时间间隔是多久,为什么
多数显示器默认频率是 60Hz,即 1 秒刷新 60 次,所以理论上最小间隔为 1/60*1000ms = 16.7ms
transform(变形)
transform 属性主要包括 rotate(旋转),skew(扭曲),scale(缩放),translate(移动),matrix(矩阵变形)
transform : none | [ ]*
transform 中使用多个属性时却需要有空格隔开,可用于内联(inline)元素和块级(block)元素
rotate(旋转)
可以通过 rotate 使元素旋转一定的度数
transform: rotate(30deg)//顺时针旋转30度
- 旋转之后元素仍占据原来位置,实际上所有的 transform 都是这样,缩放、位移等都不会改变元素占据的位置
- 元素旋转的的基点默认是中心,可以通过 transform-origin 属性改变
transform:rotate(30deg); transform-origin: 0% 0%;
transform-origin 的取值可以是:
- top, bottom, left, right, center
- 百分数
translate(位移)
transform: translateY(100px)//Y轴位移100px;
scale(缩放)
scale(x,y): 使元素水平方向和垂直方向同时缩放
transform: translate(3)//相同的比例缩放两个方向
skew(扭曲)
通过 skew 使元素扭曲一定的度数
transform:skew(10deg, 20deg);//x轴扭曲10度,y轴扭曲20度
3D
元素需要设置需要设置 perspective 来激活 3D 效果
transform: perspective( 600px );
perspective: 600px;
perspective 属性的值决定了 3D 效果的强烈程度,可以认为是观察者到页面的距离。
越大距离越远,视觉上的 3D 效果就会相应的减弱。
3D 变形方法
rotateX( angle )
rotateY( angle )
rotateZ( angle )
translateZ( tz )
scaleZ( sz )
translateX()方法使元素延 X 轴移动,translateZ()使元素延 Z 轴(在 3D 空间中方向从前到后)移动。正值使元素离观察者更近,负值使元素变远。
渐进增强和优雅降级
渐进增强(Progressive Enhancement):一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验。
优雅降级(Graceful Degradation):一开始就构建站点的完整功能,然后针对浏览器测试和修复。比如一开始使用 CSS3 的特性构建了一个应用,然后逐步针对各大浏览器进行 hack 使其可以在低版本浏览器上正常浏览。
其实渐进增强和优雅降级并非什么新概念,只是旧的概念换了一个新的说法。在传统软件开发中,经常会提到向上兼容和向下兼容的概念。渐进增强相当于向上兼容,而优雅降级相当于向下兼容。
二者区别
优雅降级观点认为:
应该针对那些最高级、最完善的浏览器来设计网站。而将那些被认为“过时”或有功能缺失的浏览器下的测试工作安排在开发周期的最后阶段,并把测试对象限定为主流浏览器(如 IE、Mozilla 等)的前一个版本。在这种设计范例下,旧版的浏览器被认为仅能提供“简陋却无妨 (poor, but passable)” 的浏览体验。你可以做一些小的调整来适应某个特定的浏览器。但由于它们并非我们所关注的焦点,因此除了修复较大的错误之外,其它的差异将被直接忽略。
渐进增强观点则认为:
应关注于内容本身。请注意其中的差别:我甚至连“浏览器”三个字都没提。内容是我们建立网站的诱因。有的网站展示它,有的则收集它,有的寻求,有的操作,还有的网站甚至会包含以上的种种,但相同点是它们全都涉及到内容。这使得渐进增强成为一种更为合理的设计范例。这也是它立即被 Yahoo! 所采纳并用以构建其“分级式浏览器支持 (Graded Browser Support)”策略的原因所在。
案例分析
1 | .transition { /*渐进增强写法*/ |
前缀 CSS3(-webkit-* / -moz-* / -o-*
)和正常 CSS3 在浏览器中的支持情况是这样的:
- 很久以前:浏览器前缀 CSS3 和正常 CSS3 都不支持;
- 不久之前:浏览器只支持前缀 CSS3,不支持正常 CSS3;
- 现在:浏览器既支持前缀 CSS3,又支持正常 CSS3;
- 未来:浏览器不支持前缀 CSS3,仅支持正常 CSS3.
渐进增强的写法,优先考虑老版本浏览器的可用性,最后才考虑新版本的可用性。在时期 3 前缀 CSS3 和正常 CSS3 都可用的情况下,正常 CSS3 会覆盖前缀 CSS3。优雅降级的写法,优先考虑新版本浏览器的可用性,最后才考虑老版本的可用性。在时期 3 前缀 CSS3 和正常 CSS3 都可用的情况下,前缀 CSS3 会覆盖正常的 CSS3。
重绘和回流
前提
- 浏览器使用流式布局模型 (Flow Based Layout)。
- 浏览器会把 HTML 解析成 DOM,把 CSS 解析成 CSSOM,DOM 和 CSSOM 合并就产生了 Render Tree。
- 有了 RenderTree,我们就知道了所有节点的样式,然后计算他们在页面上的大小和位置,最后把节点绘制到页面上。
- 由于浏览器使用流式布局,对 Render Tree 的计算通常只需要遍历一次就可以完成,但 table 及其内部元素除外,他们可能需要多次计算,通常要花 3 倍于同等元素的时间,这也是为什么要避免使用 table 布局的原因之一。
回流必将引起重绘,重绘不一定会引起回流。
重绘
定义: 当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility 等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。
回流
定义: 当 Render Tree 中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。
导致回流的操作
页面首次渲染
浏览器窗口大小发生改变
元素尺寸或位置发生改变
元素内容变化(文字数量或图片大小等等)
元素字体大小变化
添加或者删除可见的 DOM 元素
激活 CSS 伪类(例如::hover)
查询某些属性或调用某些方法
导致回流的属性
clientWidth、clientHeight、clientTop、clientLeft
offsetWidth、offsetHeight、offsetTop、offsetLeft
scrollWidth、scrollHeight、scrollTop、scrollLeft
scrollIntoView()、scrollIntoViewIfNeeded()
getComputedStyle()
getBoundingClientRect()
scrollTo()
性能影响
回流比重绘的代价要更高。
有时即使仅仅回流一个单一的元素,它的父元素以及任何跟随它的元素也会产生回流。
现代浏览器会对频繁的回流或重绘操作进行优化:
浏览器会维护一个队列,把所有引起回流和重绘的操作放入队列中,如果队列中的任务数量或者时间间隔达到一个阈值的,浏览器就会将队列清空,进行一次批处理,这样可以把多次回流和重绘变成一次。
当你访问以下属性或方法时,浏览器会立刻清空队列:
1 | clientWidth、clientHeight、clientTop、clientLeft |
因为队列中可能会有影响到这些属性或方法返回值的操作,即使你希望获取的信息与队列中操作引发的改变无关,浏览器也会强行清空队列,确保你拿到的值是最精确的。
如何避免
CSS
避免使用 table 布局。
尽可能在 DOM 树的最末端改变 class。
避免设置多层内联样式。
将动画效果应用到 position 属性为 absolute 或 fixed 的元素上。
避免使用 CSS 表达式(例如:calc())。
JavaScript
避免频繁操作样式,最好一次性重写 style 属性,或者将样式列表定义为 class 并一次性更改 class 属性。
避免频繁操作 DOM,创建一个 documentFragment,在它上面应用所有 DOM 操作,最后再把它添加到文档中。
也可以先为元素设置display: none
,操作结束后再把它显示出来。因为在 display 属性为 none 的元素上进行的 DOM 操作不会引发回流和重绘。
避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。
浏览器兼容性问题
样式兼容性(css)方面
- 因为历史原因,不同的浏览器样式存在差异,可以通过 Normalize.css 抹平差异,也可以定制自己的 reset.css,例如通过通配符选择器,全局重置样式.
1 | * { |
- 在 CSS3 还没有成为真正的标准时,浏览器厂商就开始支持这些属性的使用了。CSS3 样式语法还存在波动时,浏览器厂商提供了针对浏览器的前缀,直到现在还是有部分的属性需要加上浏览器前缀。在开发过程中我们一般通过 IDE 开发插件、css 预处理器以及前端自动化构建工程帮我们处理。如 css-loader.
- 在还原设计稿的时候我们常常会需要用到透明属性,所以解决 IE9 以下浏览器不能使用 opacit。
1 | opacity: 0.5; |
浏览器 hack
1.快速判断 IE 浏览器版本
1 | <!--[if IE 8]> ie8 <![endif]--> |
2.判断是否是 Safari 浏览器
1 | /* Safari */ |
3.判断是否是 Chrome 浏览器
1 | /* Chrome */ |
js 兼容
1.事件兼容的问题,我们通常需要会封装一个适配器的方法,过滤事件句柄绑定、移除、冒泡阻止以及默认事件行为处理
1 | var helper = {}; |
2.new Date()构造函数使用,’2018-07-05’是无法被各个浏览器中,使用 new Date(str)来正确生成日期对象的。 正确的用法是’2018/07/05’.
3.获取 scrollTop 通过 document.documentElement.scrollTop 兼容非 chrome 浏览器
1 | var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; |