css


title: CSS

date: 2019-08-23 16:54:50

tags: css

categories:  # 这里写的分类会自动汇集到 categories 页面上,分类可以多级

  • css # 一级分类
  • css3 # 二级分类

介绍

css,即层叠样式表,可以为网页添加样式.

stylesheet

应用方式

外部样式表

  1. 通过<link>引入

<link rel="stylesheet" href="index.css"> 2. 通过@import引入,注意末尾加;号,CSS 语法,只能在 CSS 内使用.

1
<style>@import url("index.css"); @import "index.css";</style>
  1. 媒体查询(响应式)
1
2
3
4
5
6
7
8
<style>
@media (min-width: 801px) {
body {
margin: 0 auto;
width: 800px;
}
}
</style>

内部样式表

将 css 放到<style>元素中,一般放到文档的<head>中.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>CSS</title>
<style>
h1 {
background: red;
}
</style>

</head>
<body>
<h1>AMD yes!</h1>
</body>
</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

伪元素和伪类的区别

  1. 伪元素使用两个冒号,伪类使用一个冒号
  2. 伪元素添加了一个页面中没有的元素(只是从视觉效果上添加了,不是在文档树中添加),伪类是给页面中已经存在的的元素添加一个类.

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

  1. inline-block 之间空隙
  • inline-block 之间有空格、Tab、换行符。
  • 给父元素设置 font-size: 0,在 inline-block 元素上重新设置 font-size。
  1. inline-block 导致父元素增高若干像素
  • 给 inline-block 元素设置 vertical-align: top

通用解决办法 不要设置 inline-block,使用 float 或 flex。

浏览器默认样式

浏览器对某些元素设置有默认样式,如 h1, ul, li 等。

常见处理方式

  1. Normalize.css
  2. CSS Reset
  3. 简单去除
1
2
3
4
* {
margin: 0;
padding: 0;
}

CSS 常见样式

边框 border

1
2
3
4
5
6
7
8
9
10
11
.box {
border-width: 1px;
border-color: red;
border-style: solid;
border-bottom: none;//下边框消失
border-radius: 50%;//圆角
}
//简写
.box2 {
border: 1px red solid;
}

实现不使用 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
2
3
4
5
6
7
8
9
body{
font: 12px/1.5 Arial;
}
p{
line-height: 1.5;//行高是字体的1.5倍
font-size: 14px;//字体大小
font-family: Arial;//字体
font-weight: bold;//文字粗度,粗体
}

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
2
3
4
5
.box>h3 {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

颜色

  • 单词: 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的区别

  1. px是像素 pixel,相对于屏幕分辨率的单位
  2. 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
2
3
.avatar {
background: #fff url(avatar.svg) no-repeat left center;
}

隐藏 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

  1. static: 该关键字指定元素使用正常的布局行为,即元素在文档常规流中当前的布局位置。此时 top, right, bottom, left 和 z-index 属性无效。
  2. relative: 该关键字下,元素先放置在未添加定位时的位置,再在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白)。position:relative 对 table 元素无效.
  3. absolute: 不为元素预留空间,通过指定元素相对于最近的非 static 定位父元素的偏移,来确定元素位置。绝对定位的元素可以设置外边距(margins),且不会与其他边距合并。
  4. fixed: 不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。fixed 属性会创建新的层叠上下文。当元素祖先的 transform   属性非 none 时,容器由视口改为该祖先。
  5. 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
2
3
4
5
6
7
8
9
10
父元素加clearfix
.clearfix::after{
content:'';
display: block;
clear: both;
}
.clearfix{
*zoom: 1
//兼容IE6,7
}

BFC(块级格式化上下文)

决定了其子元素将如何定位,以及其他元素的关系和相互作用

在正常流中的盒子要么属于块级格式化上下文,要么属于内联格式化上下文

BFC 的产生

  1. 根元素
  2. float 不为 none;
  3. position: absolute/fixed;
  4. display: inline-block/flex/inline-flex/table-cell;
  5. overflow 不为 visible;

特性

  1. 内部的 Box 会在垂直方向,一个接一个地放置。
  2. Box 垂直方向的距离由 margin 决定。属于同一个 BFC 的两个相邻 Box 的 margin 会发生重叠.每个元素的 margin box 的左边,与包含块 border box 的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。(如果有多个浮动盒,因为是浮动盒,所以后面的有新的 BFC,会挨着前面的从左到右排列)
  3. BFC 的区域不会与 float box 重叠。(不跟外面的浮动盒重叠,会把浮动盒挤到一边)
  4. BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
  5. 计算 BFC 的高度时,浮动元素也参与计算(包裹浮动元素).

作用

  1. 阻止 margin 合并,因为 BFC 与外界隔离,自己的 margin 也就不再合并.
  2. contain float(包裹浮动元素).

边距合并

合并场景

  1. 相邻元素合并,间距为二者中较大值
  2. 父子合并
  3. 自己合并

取消合并

  1. 加 border,padding
  2. BFC

居中

水平居中

  1. 块级元素水平居中
1
2
margin-left:auto;
margin-right:auto;
  1. 内联元素水平居中,给它们的父元素加上
1
text-align:center;

若不是内联元素想让它居中,可加display:inline-block,加了之后一般还要加下面这句,不然可能会有 bug(下面可能会空出一行)

1
vertical-align: top;
  1. 让导航栏横过来,并在同一行里均匀分布

给 ul 加 css

1
2
3
4
ul{
display:flex;
justyfy-content:space-between;
}

去掉 li 的float:left

去掉 ul 的clearfix

垂直居中

  1. 若父元素没有写 height,则直接在父元素写
1
padding: 10px 0;

子元素就可以居中,所以尽量避免父亲高度确定

以下是宽高确定(注意写宽高)

  1. 让一个元素在父级元素中绝对居中

方法一:

给父级元素加:

1
2
position: relative; //若父级元素是body可以不用加
//注意父元素需要宽高

再给自己加:

1
2
3
4
5
6
7
8
9
div{
//注意子元素也需要宽高
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
}

方法二:(若不兼容 IE,工作中只要用这一种方法即可,最简单,Chrome,移动端都可以用)

给父元素加:

1
2
3
display: flex;               //让它变成一个弹性盒
justify-content: center; //水平居中
align-items: center; //垂直居中
  1. table 自带居中(兼容 IE)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<html>
<style>
.parent{
border: 1px solid red;
height: 600px;
}
.child{
border: 1px solid green;
}
</style>
<body>
<table class="parent">
<tr>
<td class="child">
文字
</td>
</tr>
</table>
</body>
</html>

文字会居中

  1. 用 div 假扮 table(兼容 IE)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<html>
<style>
div.table{
display: table;
border: 1px solid red;
height: 600px;
}

div.tr{
display: table-row;
border: 1px solid green;
}

div.td{
display: table-cell;
border: 1px solid blue;
vertical-align: middle;
}

</style>
<body>
<div class="table">
<div class="tr">
<div class="td">
文字
</div>
</div>
</div>
</body>
</html>
  1. 用 100%高度的 before 和 after
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
.parent{
border: 3px solid red;
height: 600px;
text-align: center;
}

.child{
border: 3px solid black;
display: inline-block;
width: 300px;
vertical-align: middle;
}

.parent:before{
content:'';
display: inline-block;
height: 100%;
vertical-align: middle;
}
.parent:after{
content:'';
display: inline-block;
height: 100%;
vertical-align: middle;
}
  1. 绝对定位加上 margin-top: -自身 height 的 50%
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<html>
<style>
.parent{
height: 600px;
border: 1px solid red;
position: relative;
}
.child{
border: 1px solid green;
width: 300px;
position: absolute;
top: 50%;
left: 50%;
margin-left: -150px;
height: 20px;
margin-top: -10px;
text-align: center;
}
</style>
<body>
<div class="parent">
<div class="child">
文字
</div>
</div>
</body>
</html>
  1. 使用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
2
3
div{
transition: 1s;
}

指定属性

可以指定transition使用的属性,比如只适用于 height

transition: 1s height;

delay(延迟)

transition: 1s height,1s 1s width;

width 在一秒之后在开始变化,也就是延迟一秒.delay 可以指定动画发生的顺序,使得不同 transition 可以连在一起,形成不同效果.

transition-timing-function(缓动函数)

transition 的状态变化速度,默认不是匀速的,而是逐渐放慢的,这叫做 ease.

transition: 1s ease;

除了 ease,其他模式还有:

  1. linear: 匀速
  2. ease-in: 加速
  3. ease-out: 减速
  4. cubic-bezier: 自定义速度模式(可以在 cubic-bezier.com 里设置)

语法

简写:

transition: 1s 1s height ease;

完整写法:

1
2
3
4
transition-property: height;
transition-duration: 1s;
transition-delay: 1s;
transition-timing-function: ease;

注意

  1. transition 需要明确知道,开始状态和结束状态的具体数值,才能计算出中间状态,什么 none 到 block 之类的是不行的
  2. transition 是一次性的,不能重复发生,除非一再触发

animation(动画)

使用 animation 首先需要定义动画过程,即关键帧

1
2
3
4
5
@keyframes rainbow {
0% { background: #c00; }
50% { background: orange; }
100% { background: yellowgreen; }
}

写动画帧里的 css 记得加;号.

定义关键帧后可以给 DOM 元素绑定动画,和事件比较像.加infinite代表无限次,改成数字就是循环多少次.

1
2
3
div:hover {
animation: 1s rainbow infinite;
}

animation-fill-mode

动画结束后,会立即跳到结束状态,如果想让动画保持在结束状态,需要使用 animation-fill-mode 属性.

1
2
3
div:hover{
animation: 1s rainbow forwards;
}

animation-fill-mode 的属性:

  1. none: 默认值,回到动画未开始的状态.
  2. forwards: 让动画停留在结束状态
  3. backwards: 让动画回到第一帧的状态
  4. both: animation-direction 轮流应用 forwards 和 backwards 规则

animation-direction

动画循环播放时,每次都是从结束状态跳回到起始状态,再开始播放。animation-direction 属性,可以改变顺序

默认情况是,animation-direction 等于 normal.此外,还可以等于取 alternate(先从前往后再从后往前)、reverse(从后往前)、alternate-reverse 等值.

1
2
3
div:hover {
animation: 1s rainbow 3 normal;
}

animation-play-state

有时,动画播放过程中,会突然停止。这时,默认行为是跳回到动画的开始状态,如果想让动画保持突然终止时的状态,就要使用 animation-play-state 属性。

1
2
3
4
5
6
7
8
div {
animation: spin 1s linear infinite;
animation-play-state: paused;
}

div:hover {
animation-play-state: running;
}

语法

简写:

1
2
3
div:hover {
animation: 1s 1s rainbow linear 3 forwards normal;
}

完整:

1
2
3
4
5
6
7
8
9
div:hover {
animation-name: rainbow;
animation-duration: 1s;
animation-timing-function: linear;
animation-delay: 1s;
animation-fill-mode:forwards;
animation-direction: normal;
animation-iteration-count: 3;
}

0%可以用 from 代表,100%可以用 to 代表,因此上面的代码等同于下面的形式

1
2
3
4
5
@keyframes rainbow {
from { background: #c00 }
50% { background: orange }
to { background: yellowgreen }
}

steps(分步过渡)

浏览器从一个状态向另一个状态过渡,是平滑过渡。steps 函数可以实现分步过渡。

1
2
3
div:hover {
animation: 1s rainbow infinite steps(10);
}

歌词效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<style>
@keyframes moving {
from {
width: 0;
}
}
.line {
position: relative;
}
p {
width: 600px;
font-size: 40px;
white-space: nowrap;
overflow: hidden;
position: absolute;
top: 0;
z-index: 2;
}

p:nth-child(1) {
color: red;
animation: moving 20s
}
p:nth-child(2) {
z-index: -1;
color: #666;
}
</style>
<body>
<div class="line">
<p>To my days change my ways为生活我试着不断改变</p>
<p>This sudden end to my days这生命的终点突如其来</p>
</div>
</body>

打字机效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<style>
@keyframes typing {from { width: 0 } }
@keyframes blink-caret { 50% { border-clolr: transparent } }
h1 {
border-right: 0.1em solid;
color: #fff;
width: 352px;
height: 30px;
white-space: nowrap;
overflow: hidden;
animation: typing 5s steps(11, end),//变11次变成最终状态
blink-caret .5s infinite alternate;
}
body {
background: #000;
height: 100vh;
}
</style>

<body>
<h1>躺在你的学校操场看星空</h1>
</body>

如果需要手动写动画,你认为最小时间间隔是多久,为什么

多数显示器默认频率是 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度

  1. 旋转之后元素仍占据原来位置,实际上所有的 transform 都是这样,缩放、位移等都不会改变元素占据的位置
  2. 元素旋转的的基点默认是中心,可以通过 transform-origin 属性改变

transform:rotate(30deg); transform-origin: 0% 0%;

transform-origin 的取值可以是:

  1. top, bottom, left, right, center
  2. 百分数

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 效果

  1. transform: perspective( 600px );
  2. 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
2
3
4
5
6
7
8
9
10
11
12
.transition { /*渐进增强写法*/
-webkit-transition: all .5s;
-moz-transition: all .5s;
-o-transition: all .5s;
transition: all .5s;
}
.transition { /*优雅降级写法*/
transition: all .5s;
-o-transition: all .5s;
-moz-transition: all .5s;
-webkit-transition: all .5s;
}

前缀 CSS3(-webkit-* / -moz-* / -o-*)和正常 CSS3 在浏览器中的支持情况是这样的:

  1. 很久以前:浏览器前缀 CSS3 和正常 CSS3 都不支持;
  2. 不久之前:浏览器只支持前缀 CSS3,不支持正常 CSS3;
  3. 现在:浏览器既支持前缀 CSS3,又支持正常 CSS3;
  4. 未来:浏览器不支持前缀 CSS3,仅支持正常 CSS3.

渐进增强的写法,优先考虑老版本浏览器的可用性,最后才考虑新版本的可用性。在时期 3 前缀 CSS3 和正常 CSS3 都可用的情况下,正常 CSS3 会覆盖前缀 CSS3。优雅降级的写法,优先考虑新版本浏览器的可用性,最后才考虑老版本的可用性。在时期 3 前缀 CSS3 和正常 CSS3 都可用的情况下,前缀 CSS3 会覆盖正常的 CSS3。

重绘和回流

前提

  1. 浏览器使用流式布局模型 (Flow Based Layout)。
  2. 浏览器会把 HTML 解析成 DOM,把 CSS 解析成 CSSOM,DOM 和 CSSOM 合并就产生了 Render Tree。
  3. 有了 RenderTree,我们就知道了所有节点的样式,然后计算他们在页面上的大小和位置,最后把节点绘制到页面上。
  4. 由于浏览器使用流式布局,对 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
2
3
4
5
6
clientWidth、clientHeight、clientTop、clientLeft
offsetWidth、offsetHeight、offsetTop、offsetLeft
scrollWidth、scrollHeight、scrollTop、scrollLeft
width、height
getComputedStyle()
getBoundingClientRect()

因为队列中可能会有影响到这些属性或方法返回值的操作,即使你希望获取的信息与队列中操作引发的改变无关,浏览器也会强行清空队列,确保你拿到的值是最精确的。

如何避免

CSS

避免使用 table 布局。

尽可能在 DOM 树的最末端改变 class。

避免设置多层内联样式。

将动画效果应用到 position 属性为 absolute 或 fixed 的元素上。

避免使用 CSS 表达式(例如:calc())。

JavaScript

避免频繁操作样式,最好一次性重写 style 属性,或者将样式列表定义为 class 并一次性更改 class 属性。

避免频繁操作 DOM,创建一个 documentFragment,在它上面应用所有 DOM 操作,最后再把它添加到文档中。

也可以先为元素设置display: none,操作结束后再把它显示出来。因为在 display 属性为 none 的元素上进行的 DOM 操作不会引发回流和重绘。

避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。

对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。

浏览器兼容性问题

样式兼容性(css)方面

  1. 因为历史原因,不同的浏览器样式存在差异,可以通过 Normalize.css 抹平差异,也可以定制自己的 reset.css,例如通过通配符选择器,全局重置样式.
1
2
3
* {
margin: 0; padding: 0;
}
  1. 在 CSS3 还没有成为真正的标准时,浏览器厂商就开始支持这些属性的使用了。CSS3 样式语法还存在波动时,浏览器厂商提供了针对浏览器的前缀,直到现在还是有部分的属性需要加上浏览器前缀。在开发过程中我们一般通过 IDE 开发插件、css 预处理器以及前端自动化构建工程帮我们处理。如 css-loader.
  2. 在还原设计稿的时候我们常常会需要用到透明属性,所以解决 IE9 以下浏览器不能使用 opacit。
1
2
3
opacity: 0.5;
filter: alpha((opacity = 50)); //IE6-IE8我们习惯使用filter滤镜属性来进行实现
filter: progid: DXImageTransform.Microsoft.Alpha((style = 0), (opacity = 50)); //IE4-IE9都支持滤镜写法progid:DXImageTransform.Microsoft.Alpha(Opacity=xx)

浏览器 hack

1.快速判断 IE 浏览器版本

1
2
3
<!--[if IE 8]> ie8 <![endif]-->

<!--[if IE 9]> ie9 浏览器 <![endif]-->

2.判断是否是 Safari 浏览器

1
2
/* Safari */
var isSafari = /a/.__proto__ == "//";

3.判断是否是 Chrome 浏览器

1
2
/* Chrome */
var isChrome = Boolean(window.chrome);

js 兼容

1.事件兼容的问题,我们通常需要会封装一个适配器的方法,过滤事件句柄绑定、移除、冒泡阻止以及默认事件行为处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var helper = {};

//绑定事件
helper.on = function (target, type, handler) {
if (target.addEventListener) {
target.addEventListener(type, handler, false);
} else {
target.attachEvent(
"on" + type,
function (event) {
return handler.call(target, event);
},
false
);
}
};

//取消事件监听
helper.remove = function (target, type, handler) {
if (target.removeEventListener) {
target.removeEventListener(type, handler);
} else {
target.detachEvent(
"on" + type,
function (event) {
return handler.call(target, event);
},
true
);
}
};

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;