三、CSS相关面试题讲解

郁子大约 75 分钟约 22369 字笔记渡一教育笔面试题甄选谢杰

(一)CSS 单位总结

1.经典真题

  • px 和 em 的区别

2.CSS 中的单位

1)绝对长度单位

  • 常见的长度单位有米(m)、厘米(cm)、毫米(mm)
  • 每一种单位的长度都是固定的
  • 如:5cm,走到任何地方 5cm 的长度都是一致的
<div class="container"></div>
.container {
  width: 5cm;
  height: 5cm;
  background-color: pink;
}

  • 这些值大多数用于打印
  • px(像素)是绝对单位中具有相对性的单位

2)相对长度单位

  • 相对于其他东西的单位长度
  • 如:父元素的字体大小、视图端口的大小
  • 使用相对单位的好处是,经过一些仔细的规划,可以使文本或其他元素的大小与页面上的其他内容相对应

  • 常用的有 em、rem、vw、vh

3.vw 和 vh

  • vw 和 vh 代表的是视口的宽度和高度
<div class="container"></div>
* {
  margin: 0;
  padding: 0;
}
.container {
  width: 50vw;
  height: 100vh;
  background-color: pink;
}

4.em 和 rem

  • em 和 rem 相对于 px 更具有灵活性,更适用于响应式布局
  • em 相对于父元素,rem 相对于根元素

1)em

<div>
  我是父元素div
  <p>
    我是子元素p
    <span>我是孙元素span</span>
  </p>
</div>
* {
  margin: 0;
  padding: 0;
}
div {
  font-size: 40px;
  width: 10em;
  /* 400px */
  height: 10em;
  outline: solid 1px black;
  margin: 10px;
}
p {
  font-size: 0.5em;
  /* 20px */
  width: 10em;
  /* 200px */
  height: 10em;
  outline: solid 1px red;
}
span {
  font-size: 0.5em;
  width: 10em;
  height: 10em;
  outline: solid 1px blue;
  display: block;
}

2)rem

  • rem 是全部的长度都相对于根元素
  • 根元素是 html 元素
  • 通常做法是给 html 元素设置一个字体大小,然后其他元素的长度单位就为 rem
<div>
  我是父元素div
  <p>
    我是子元素p
    <span>我是孙元素span</span>
  </p>
</div>
* {
  margin: 0;
  padding: 0;
}
html {
  font-size: 10px;
}
div {
  font-size: 4rem;
  /* 40px */
  width: 30rem;
  /* 300px */
  height: 30rem;
  /* 300px */
  outline: solid 1px black;
  margin: 10px;
}
p {
  font-size: 2rem;
  /* 20px */
  width: 15rem;
  /* 150px */
  height: 15rem;
  /* 150px */
  outline: solid 1px red;
}
span {
  font-size: 1.5rem;
  width: 10rem;
  height: 10rem;
  outline: solid 1px blue;
  display: block;
}
  • 当用 rem 做响应式时,直接在媒体中改变 html 的 font-size,此时用 rem 作为单位的元素的大小都会相应改变,很方便

5.真题解答

1)px 和 em 的区别

px 即 pixel 像素,是相对于屏幕分辨率而言的,是一个绝对单位,但是具有一定的相对性。因为在同一设备上每个设备像素所代表的物理长度是固定不变的(绝对性),但在不同设备间每个设备像素所代表的物理长度是可以变化的(相对性)


em 是相对长度单位,具体的大小要相对于父元素来计算,例如父元素的字体大小为 40px,那么子元素 1em 就代表字体大小和父元素一样为 40px,0.5em 就代表字体大小为父元素的一半即 20px

(二)居中方式总结

1.经典真题

  • 怎么让一个 div 水平垂直居中

2.盒子居中

  • 居中分 2 个方向,一个是水平方向,一个是垂直方向

3.水平方向居中

1)设置盒子 margin: 0 auto;

  • 原理在于设置 margin-left 为 auto 时,margin-left 就会被设置为有多大就设置多大,所以盒子会跑到最右边
  • 而设置 margin-right 为 auto 时,同理盒子就会跑到最左边
  • 所以,当设置左右的 margin 都是 auto 时,盒子就跑到了中间,从而形成了水平居中

2)设置为弹性盒子

  • 通过 display: flex; 设置盒子的外层盒子为弹性盒
  • 通过 justify-content: center; 使得内部的盒子居中

4.垂直方向居中

1)vertical-align: middle

  • 是最常使用的方法
  • 生效的前提是元素的 display:inline-block;
  • 且需要一个兄弟元素做参照物,垂直于兄弟元素的中心点
  • vertical-align 对齐的方法是寻找 兄弟元素中最高的元素 作为参考
<div class="container">
  <div class="item"></div>
  <div class="brotherBox"></div>
</div>
.container {
  width: 500px;
  height: 300px;
  background-color: pink;
  text-align: center;
}
.item {
  width: 100px;
  height: 100px;
  background-color: skyblue;
  vertical-align: middle;
  margin: 0 auto;
  display: inline-block;
}
.brotherBox {
  height: 100%;
  /* width: 2px; */
  background: red;
  display: inline-block;
  vertical-align: middle;
}

2)伪元素 :before

  • 去除作为参考的兄弟元素
  • 转为给父元素添加一个伪元素
<div class="container">
  <div class="item"></div>
</div>
.container {
  width: 500px;
  height: 300px;
  background-color: pink;
  text-align: center;
}
.container::before {
  content: "";
  display: inline-block;
  vertical-align: middle;
  height: 100%;
}
.item {
  width: 100px;
  height: 100px;
  background-color: skyblue;
  vertical-align: middle;
  margin: 0 auto;
  display: inline-block;
}

3)绝对定位

  • 需要设置父元素为相对定位,子元素为绝对定位
  • 然后配合 margin-left 为负的盒子高度一半来实现垂直居中
<div class="container">
  <div class="item"></div>
</div>
.container {
  width: 500px;
  height: 300px;
  background-color: pink;
  position: relative;
}
.item {
  width: 100px;
  height: 100px;
  background-color: skyblue;
  position: absolute;
  left: 50%;
  top: 50%;
  margin-left: -50px;
  margin-top: -50px;
}

4)transform

  • 通过定位配合 transform
<div class="container">
  <div class="item"></div>
</div>
.container {
  width: 500px;
  height: 300px;
  background-color: pink;
  position: relative;
}
.item {
  width: 100px;
  height: 100px;
  background-color: skyblue;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translateX(-50px) translateY(-50px);
}

5)使用弹性盒子【常用且推荐】

  • 设置父元素为弹性盒子
  • 使用 justify-content: center;align-items: center; 来设置内部盒子水平垂直居中
<div class="container">
  <div class="item"></div>
</div>
.container {
  width: 500px;
  height: 300px;
  background-color: pink;
  display: flex;
  justify-content: center;
  align-items: center;
}
.item {
  width: 100px;
  height: 100px;
  background-color: skyblue;
}

5.真题解答

1)怎么让一个 div 水平垂直居中

  1. 通过 vertical-align: middle; 实现垂直居中
  2. 通过父元素设置伪元素 :before ,然后设置子元素 vertical-align: middle; 实现垂直居中
  3. 通过绝对定位实现垂直居中
  4. 通过 transform 实现垂直居中
  5. 使用弹性盒子居中

(三)隐藏元素方式总结

1.经典真题

  • 隐藏页面中的某个元素的方法有哪些?

2.隐藏元素

  • 完全隐藏:元素从渲染树中消失,不占据空间
  • 视觉上的隐藏:屏幕中不可见,占据空间
  • 语义上的隐藏:读屏软件不可读,但正常占据空间

3.完全隐藏

1)display 属性

  • 设置 display: none;
  • 元素被隐藏了,并且不占据空间

2)hidden 属性

  • HTML5 新增属性
  • 相当于 display: none;
  • 直接写在元素上面
<div hidden></div>

4.视觉隐藏

  • 元素还占据位置,只是视觉上不可见而已

1)opacity 属性

  • 将透明度设置为 0
div {
  opacity: 0;
}

2)visibility: hidden

  • 仍然会占位
div {
  visibility: hidden;
}

3)绝对定位

  • 设置 position: absolute;position: fixed
  • 通过设置 top、left 等值,将其移出可视区域
div {
  position: absolute;
  left: -999px;
  top: -999px;
}

4)设置 margin

  • 将其移出可视区域范围(可视区域占位)
div {
  margin-left: -99999px;
}

5)设置宽高为 0

  • 将元素的 margin、border、padding、height、width 等影响元素盒模型的属性设置成 0
  • 如果元素内有子元素或内容,还应该设置 overflow: hidden; 来隐藏
div {
  width: 0px;
  height: 0px;
  overflow: hidden;
}

6)裁剪元素

  • 通过 clip-path 属性
  • 这个属性比较新,浏览器兼容性也会比较差
div {
  clip-path: polygon(0px 0px, 0px 0px, 0px 0px, 0px 0px);
}

5.语义上隐藏

1)aria-hidden 属性

  • 使读屏软件不可读,但是元素仍然占据空间并且可见
<div aria-hidden="true"></div>

6.真题解答

1)隐藏页面中的某个元素的方法有哪些?

隐藏元素可以分为 3 大类:

  1. 完全隐藏:元素从渲染树中消失,不占据空间
  2. 视觉上的隐藏:屏幕中不可见,占据空间
  3. 语义上的隐藏:读屏软件不可读,但正常占据空间

完全隐藏的方式有:设置 display: none、为元素设置 hidden 属性

视觉上隐藏的方式有:设置 opacity 属性为 0、绝对定位的 left 和 top 值设置为 -999px、设置 margin-left 值为 -999px、设置宽高为 0、裁剪元素

语义上的隐藏方式为将 aria-hidden 属性设置为 true 使读屏软件不可读

(四)浮动

1.经典真题

  • 清除浮动的方法
  • 以下选项能够清除浮动的是( )

A. 空 div

B. hover 伪选择器

C. clear 属性

D. overflow 属性

2.浮动出现的背景

  • 浮动属性产生之初是为了实现“文字环绕”的效果,让文字环绕图片
  • 从而使网页实现类似 word 中“图文混排”的效果

3.浮动实现布局

到了后面,浮动渐渐被应用到了页面布局上

因为 HTML 里面的元素,要么是行内元素,要么是块级元素,这种方式是没办法做页面布局的

此时开发人员就想到了浮动,因为任何东西都可以浮动,而不仅仅是图像

所以浮动的使用范围扩大了,能够用来进行布局

1)两列布局

2)三列布局

4.浮动的特性

1)脱离标准流

<div class="one"></div>
<div class="two"></div>
.one {
  width: 80px;
  height: 80px;
  background-color: red;
  float: left;
}
.two {
  width: 150px;
  height: 150px;
  background-color: blue;
}

  • 由于红色的 div 浮动脱离了标准流
  • 所以蓝色的 div 自然而然就往上走了

2)浮动的元素互相贴靠

  • 如果有多个浮动的元素,那么会相互贴靠
  • 如果宽度不够,会重启一行
.two {
  width: 150px;
  height: 150px;
  background-color: blue;
  float: left;
}

  • 如果宽度不足以让后面的盒子贴靠,那么后面浮动的元素会被排列到下一行
.two {
  width: 850px;
  height: 150px;
  background-color: blue;
  float: left;
}

3)宽度收缩

  • 在没有设置宽度的情况下,块级元素在标准流中独占一行,宽度也会占满整个容器
  • 但是一旦被设置为浮动后,宽度就会收缩

5.清除浮动

  • 有些时候,浮动会带来副作用
  • 所以需要清除浮动带来的副作用
<ul>
  <li>导航1</li>
  <li>导航2</li>
  <li>导航3</li>
</ul>
<ul>
  <li>游戏</li>
  <li>动漫</li>
  <li>音乐</li>
</ul>
li {
  float: left;
  width: 100px;
  height: 20px;
  background-color: pink;
}

  • 本来是打算做两个导航栏的
  • 但是由于浮动的贴靠性质,导致所有的 li 都在一行了

1)给父元素设置高度

  • 由于 li 的父元素 ul 没有高度
  • 所以导致明明不是同一个父元素下的浮动子元素,也会相互贴靠
ul {
  height: 50px;
}
li {
  float: left;
  width: 100px;
  height: 20px;
  background-color: pink;
}

  • 给父元素设置高度时,高度值一定要大于浮动子元素的高度
  • 这样才能关住浮动
ul {
  height: 30px;
}
li {
  float: left;
  width: 100px;
  height: 70px;
  background-color: pink;
}

  • 虽然给父元素 ul 设置了高度,但是这个高度值是小于浮动元素 li 的高度的,此时仍然有贴靠的现象
  • 只要浮动在一个有高度的盒子中,那么这个浮动就不会影响后面的浮动元素

2)clear 属性

  • 由于盒子的高度能够被内容撑开,所以很多时候不会设置高度
  • clear 的属性定义了元素在哪边不允许出现浮动元素
  • 在 CSS1 和 CSS2 中,这是通过自动为清除元素(即设置了 clear 属性的元素) 增加上外边距 实现的
  • 在 CSS2.1 中,会在元素上外边距之上增加清除空间,而外边距本身并不改变
  • 不论哪一种改变,最终结果都一样,如果声明为左边或右边清除,会使元素的上外边框边界刚好在该边上浮动元素的下外边距边界之下

<ul>
  <li>导航1</li>
  <li>导航2</li>
  <li>导航3</li>
</ul>
<ul class="two">
  <li>游戏</li>
  <li>动漫</li>
  <li>音乐</li>
</ul>
.two {
  clear: left;
}
li {
  float: left;
  width: 100px;
  height: 20px;
  background-color: pink;
}

  • 浮动的副作用确实是清除了
  • 但是 margin 属性失效了

3)隔墙法

  • 核心思想就是在两个浮动的元素之间添加一个空的 div 作为一堵“墙”
  • 从而让后面的浮动元素,不去追前面的浮动元素
<ul>
  <li>导航1</li>
  <li>导航2</li>
  <li>导航3</li>
</ul>
<div class="clearfix"></div>
<ul class="two">
  <li>游戏</li>
  <li>动漫</li>
  <li>音乐</li>
</ul>
.two {
  margin-top: 10px;
}
.clearfix {
  clear: both;
}
li {
  float: left;
  width: 100px;
  height: 20px;
  background-color: pink;
}

4)内墙法

  • 可以让浮动的元素也能撑开父元素的高度
<div>
  <ul>
    <li>导航1</li>
    <li>导航2</li>
    <li>导航3</li>
  </ul>
  <div class="clearfix"></div>
</div>
<ul class="two">
  <li>游戏</li>
  <li>动漫</li>
  <li>音乐</li>
</ul>
.two {
  margin-top: 10px;
}
.clearfix {
  clear: both;
}
li {
  float: left;
  width: 100px;
  height: 20px;
  background-color: pink;
}

5)overflow 属性

  • 本来是用作处理溢出内容的显示方式
  • 当给父元素添加 overflow: hidden; 后,父元素就会形成一个 BFC
  • 一块独立的显示区域,不受外界影响
  • 所以通过这种方式也能够去除浮动的副作用
<ul>
  <li>导航1</li>
  <li>导航2</li>
  <li>导航3</li>
</ul>
<ul class="two">
  <li>游戏</li>
  <li>动漫</li>
  <li>音乐</li>
</ul>
.two {
  margin-top: 10px;
}
ul {
  overflow: hidden;
}
li {
  float: left;
  width: 100px;
  height: 20px;
  background-color: pink;
}

6)伪类清除法

  • 核心思想就是为父元素设置一个伪元素
  • 其实就是无形的添加了一堵墙
  • 然后在伪元素中设置一系列的属性
<ul class="one">
  <li>导航1</li>
  <li>导航2</li>
  <li>导航3</li>
</ul>
<ul class="two">
  <li>游戏</li>
  <li>动漫</li>
  <li>音乐</li>
</ul>
.two {
  margin-top: 10px;
}
.one::after {
  content: "";
  display: block;
  height: 0;
  clear: both;
  visibility: hidden;
}
li {
  float: left;
  width: 100px;
  height: 20px;
  background-color: pink;
}

6.浮动的现状

  • 除非要考虑古老的 IE6/IE7,否则布局根本不会考虑浮动
    • 可以使用更好的弹性盒模型和网格布局
  • 浮动目前仅仅也只能用于制作文字环绕效果

7.真题解答

1)清除浮动的方法

  1. clear 清除浮动(添加空 div 法)在浮动元素下方添加空 div,并给该元素写 css 样式 { clear: both; height: 0; overflow: hidden; }
  2. 给浮动元素父级设置高度
  3. 父级同时浮动(需要给父级同级元素添加浮动)
  4. 父级设置成 inline-block,其 margin: 0 auto 居中方式失效
  5. 给父级添加 overflow:hidden 清除浮动方法
  6. 万能清除法 after 伪类清浮动(现在主流方法,推荐使用)

2)以下选项能够清除浮动的是( B )

A. 空 div

B. hover 伪选择器

C. clear 属性

D. overflow 属性

(五)定位总结

1.经典真题

  • 介绍下 position 属性
  • position 有哪些值,各自的用法如何?
  • 相对定位、绝对定位、固定定位的区别

2.CSS 中的定位

  • 布局是针对整个页面来讲的,采用什么布局的目标是整个页面
  • 定位是针对某一个元素来讲的,把这个元素定位到什么位置

3.static 静态定位

  • 即标准流
  • 在标准流中,块级元素独占一行,内嵌元素共享一行
  • 静态定位是 HTML 元素的默认值
  • 静态定位的元素不会受到 top、bottom、left、right 的影响

4.relative 相对定位

  • 相对自己原来的位置进行定位
  • 最大特点就是 不脱离标准流,相对于自己原来的位置上进行一定的偏移
<div class="one">one</div>
<div class="two">two</div>
<div class="three">three</div>
* {
  margin: 0;
  padding: 0;
}
div {
  width: 100px;
  height: 100px;
  outline: 1px solid;
  line-height: 100px;
  text-align: center;
}
.two {
  position: relative;
  left: 50px;
  top: 50px;
}

  • 使用相对定位的作用
    • 微调元素
    • 做绝对定位的参考【子绝父相】

5.absolute 绝对定位

  • 相对于离自己最近的,并且定了位的元素进行偏移

1)特点

  • 使用了绝对定位后的盒子,会脱离标准流
  • 如果设置了 margin 值为 auto,则会失效
<div class="one">one</div>
<div class="two">two</div>
<div class="three">three</div>
* {
  margin: 0;
  padding: 0;
}
div {
  width: 100px;
  height: 100px;
  outline: 1px solid;
  line-height: 100px;
  text-align: center;
}
.two {
  position: absolute;
  left: 50px;
  top: 50px;
}

<a href="#">百度一下</a>
* {
  margin: 0;
  padding: 0;
}
a {
  outline: 1px solid;
  width: 100px;
  height: 100px;
  position: absolute;
  top: 50px;
  left: 50px;
}
  • 原本不能设置宽高的行内元素,在进行了绝对定位后
  • display 属性变为了 block,所以可以设置宽高了

2)默认情况下的定位参考点【较少用】

  • top 是 页面的左上角,而不是浏览器的左上角

  • bottom 是 浏览器首屏窗口尺寸,对应的页面左下角

3)面试题

4)子绝父相的定位参考点

  • 对一个元素设置绝对定位时,往往会将其父级元素设置为相对定位
  • 好处在于该元素的父级元素没有脱离标准流
  • 该元素将会以这个父元素作为参考点,在父元素的范围内进行移动

  • 在该图中,容器盒子设置为相对定位,红色盒子为绝对定位
  • 红色盒子将无视父元素的 padding 区域,以父元素的 border 内侧 作为自己定位的参考点
  • 当父级元素出现有定位时,绝对定位的参考点永远都是 离自己最近的,并且定了位的祖先元素的左上角
<div class="one">
  <div class="two">
    <div class="three"></div>
  </div>
</div>
* {
  margin: 0;
  padding: 0;
}
.one {
  width: 200px;
  height: 200px;
  outline: 1px solid;
  position: absolute;
  top: 100px;
  left: 100px;
}
.two {
  width: 100px;
  height: 100px;
  outline: 1px solid red;
  position: absolute;
  top: 50px;
  left: 50px;
}
.three {
  width: 50px;
  height: 50px;
  background-color: pink;
  position: absolute;
  top: 0;
  left: 0;
}
  • three 盒子以 two 盒子的左上角作为参考点

  • 如果取消 two 盒子的定位,那么 three 盒子就会以 one 盒子的左上角作为参考点

6.fixed 固定定位

  • 一种特殊的绝对定位,也会脱离标准流
  • 特点是相对于 浏览器窗口 进行定位
  • 在 PC 端中常用于显示在页面中位置固定不变的页面 header
  • 在 移动端中常用于显示位置固定不变的 header 和 footer

7.sticky 粘性定位

  • CSS3 新增了一种定位方式 sticky,粘性定位
  • 需要将 position 属性设置为 sticky
  • 父元素的 overflow 必须是 visible
    • 不能是 hidden 或者 auto
    • 否则父容器无法进行滚动
  • 父元素的高度不能低于 sticky 元素的高度
  • 如果父元素没有设置定位则相对于 viewport 进行定位,否则以定位的父元素为参考点
  • 设置阀值
    • 需要指定 top、right、bottom 或 left 四个阈值其中之一,才可使粘性定位生效
    • 否则其行为与相对定位相同
    • top 和 bottom 同时设置时,top 生效的优先级高
    • left 和 right 同时设置时,left 的优先级高
<h1>我是标题,题题,题,...</h1>
<nav>
  <h3>导航A</h3>
  <h3>导航B</h3>
  <h3>导航C</h3>
</nav>
<article>
  <p>
    今晚的爱奇艺尖叫之夜中,唐嫣上台领取年度戏剧女艺人奖,主持人朱丹希望她分享婚后甜蜜,可唐嫣已经下台,引发网友质疑场面尴尬。刚刚,朱丹发文回应,表示唐嫣没有不礼貌,自己也没有尴尬。随后,唐嫣也评论:“美丽的误会”
  </p>
  <p>
    韩寒:我的生活有两个节点,一个是出书,另一个就是写博客。出书让我有了收入,博客让我有了跟读者的连接。我从小就被贴过很多标签,每多一个标签就更接近真实的我。微博也一样,每一次更新都跟随着时代的风向,与时代同行。
  </p>
  <p>
    《游戏人生》作者榎宫祐 表示,近日有朋友想成为漫画家,过来找他商量。
    <br />
    他:“漫画家相当于无职啊,月收入又低,如果请助手花费更大。”(为了让朋友知道现实,又不否定梦想的小心翼翼的说法)
    <br />
    朋友:“可是我有一栋公寓用来收租唉......”
    <br />
    他:“那你想怎么活就怎么活吧!” ​​​​
  </p>
  <p>
    【湖北一小学三年级才教数学,校长回应争议:实验班的成绩远高于对比班】湖北赤壁一小学施行三年级才上数学课的教学设置,引起关注。该校校长表示,数学是一个抽象思维的功课,6岁的小孩是形象思维发展的最佳期,应该把数学往后移,按照知识发展规律。从三年级开始学数学,用3年时间学完原本5年的课程是可行的,并且经过3年的实验,实验班的成绩都要远高于对比班。
  </p>
  <p>
    刘国梁:暮然回首这一路走来⋯⋯感恩国家队30年的培养,把我从一个13岁的孩子,培养成大满贯、总教练、再到乒协主席🏓️[心]感谢这么多年跟我一起努力征战国际赛场的教练员和运动员,是你们辛勤的付出取得的荣耀造就了今天的自己[抱抱][心]感动的是亿万国人和球迷粉丝,这么多年不离不弃的支持,才有了今日国乒的新辉煌。赢不狂.输不慌.陪国乒.战东京!
  </p>
</article>
body {
  height: 5000px;
  /* 为了让页面可以滑动 */
}
nav {
  display: flex;
  justify-content: start;
  width: 100%;
  position: sticky;
  /* 设置定位方式为粘性定位 */
  top: 20px;
  /* 设置阀值,滚动到 top 值为 20px 的时候不再能够滚动*/
}
nav h3 {
  outline: 1px solid #fff;
  background-color: #333;
  color: #fff;
  text-align: center;
  padding: 10px;
}

8.真题解答

1)position 有哪些值,各自的用法如何?

目前在 CSS 中,有 5 种定位方案,分别是:

  1. static:该关键字指定元素使用正常的布局行为,即元素在文档常规流中当前的布局位置
  2. relative:相对定位的元素是在文档中的正常位置偏移给定的值,但是不影响其他元素的偏移
  3. absolute:相对定位的元素并未脱离文档流,而绝对定位的元素则脱离了文档流。在布置文档流中其它元素时,绝对定位元素不占据空间。绝对定位元素相对于最近的非 static 祖先元素定位
  4. fixed:固定定位与绝对定位相似,但元素的包含块为 viewport 视口。该定位方式常用于创建在滚动屏幕时仍固定在相同位置的元素
  5. sticky:粘性定位可以被认为是相对定位和固定定位的混合。元素在跨越特定阈值前为相对定位,之后为固定定位

(六)BFC

1.经典真题

  • 介绍下 BFC 及其应用
  • 介绍下 BFC、IFC、GFC 和 FFC

2.BFC

  • BFC,Block Formatting Contexts,块级格式化上下文
  • 就是页面中的一块渲染区域,并且有一套属于自己的渲染规则
  • 决定了元素如何对齐内容进行布局,以及与其他元素的关系和相互作用
  • 当涉及到可视化布局的时候,BFC 提供了一个环境,HTML 元素在这个环境中按照一定规则进行布局
  • 即:BFC 是一个独立的布局环境,内部的元素布局与外部互不影响

3.BFC 的布局规则

  • 内部的 Box 会在垂直方向一个接着一个地放置
  • Box 垂直方向上的距离由 margin 决定
    • 属于同一个 BFC 的两个相邻的 Box 的 margin 会发生重叠
  • 每个盒子的左外边框紧挨着包含块的左边框,即使浮动元素也是如此
  • BFC 的区域不会与浮动 Box 重叠
  • BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然
  • 计算 BFC 的高度时,浮动子元素也参与计算

4.设置 BFC

  • 实际上在一个标准流中,body 元素就是一个天然的 BFC
元素或属性属性值
根元素
floatleft、right
positionabsolute、fixed
overflowauto、scroll、hidden
displayinline-block、table-cell

上面只记录了一些常见的方式,完整的 BFC 触发方式可以参阅:https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Block_formatting_contextopen in new window

5.BFC 用处

1)解决浮动元素令父元素高度坍塌的问题

<div class="father">
  <div class="son"></div>
</div>
.father {
  border: 5px solid;
}
.son {
  width: 100px;
  height: 100px;
  background-color: blue;
  float: left;
}
  • 父元素的高度是靠子元素撑起来的
  • 一旦给子元素设置了浮动,那么父元素的高度就塌陷了

.father {
  border: 5px solid;
  overflow: hidden;
  /* 将父元素设置为一个 BFC */
}
.son {
  width: 100px;
  height: 100px;
  background-color: blue;
  float: left;
}
  • 由于父元素变成 BFC,高度并没有产生塌陷
  • 其原因是在计算 BFC 的高度时,浮动子元素也参与计算

2)非浮动元素被浮动元素覆盖

<div class="box1"></div>
<div class="box2"></div>
.box1 {
  width: 100px;
  height: 50px;
  background-color: red;
  float: left;
}
.box2 {
  width: 50px;
  height: 50px;
  background-color: blue;
}
  • 由于 box1 设置了浮动效果,所以会脱离标准流
  • box2 会上移,结果就被高度和自己一样的 box1 给挡住了

.box1 {
  width: 100px;
  height: 50px;
  background-color: red;
  float: left;
}
.box2 {
  width: 50px;
  height: 50px;
  background-color: blue;
  overflow: hidden;
}
  • 由于 BFC 的区域不会与浮动 box 重叠
  • 所以即使 box1 因为浮动脱离了标准流,box2 也不会被 box1 遮挡

  • 可以制作两栏自适应布局
  • 给固定栏设置固定宽度,给不固定栏开启 BFC
<div class="left">导航栏</div>
<div class="right">这是右侧</div>
* {
  margin: 0;
  padding: 0;
}
.left {
  width: 200px;
  height: 100vh;
  background-color: skyblue;
  float: left;
}
.right {
  width: calc(100% - 200px);
  height: 100vh;
  background-color: yellowgreen;
  overflow: hidden; /* 成为 BFC */
}

3)外边距垂直方向重合的问题

  • BFC 还能够解决 margin 折叠的问题
<div class="box1"></div>
<div class="box2"></div>
* {
  margin: 0;
  padding: 0;
}
.box1 {
  width: 100px;
  height: 100px;
  background-color: red;
  margin-bottom: 10px;
}
.box2 {
  width: 100px;
  height: 100px;
  background-color: blue;
  margin-top: 10px;
}

  • 可以在 box2 外部再包含一个 div,并且将这个 div 设置为 BFC
<div class="box1"></div>
<div class="container">
  <div class="box2"></div>
</div>
* {
  margin: 0;
  padding: 0;
}
.box1 {
  width: 100px;
  height: 100px;
  background-color: red;
  margin-bottom: 10px;
}
.box2 {
  width: 100px;
  height: 100px;
  background-color: blue;
  margin-top: 10px;
}
.container {
  overflow: hidden;
}

6.其它 FC

  • IFC,Inline Formatting Context,行内格式化上下文
    • 将一块区域以行内元素的形式来格式化
  • GFC,GrideLayout Formatting Contexts,网格布局格式化上下文
    • 将一块区域以 grid 网格的形式来格式化
  • FFC,Flex Formatting Contexts,弹性格式化上下文
    • 将一块区域以弹性盒的形式来格式化

更多关于格式化上下文的内容,可以参阅 MDN:

BFCopen in new window

IFCopen in new window

7.真题解答

1)介绍下 BFC 及其应用

所谓 BFC,指的是一个独立的布局环境,BFC 内部的元素布局与外部互不影响


触发 BFC 的方式有很多,常见的有:

  1. 设置浮动
  2. overflow 设置为 auto、scroll、hidden
  3. position 设置为 absolute、fixed

常见的 BFC 应用有:

  1. 解决浮动元素令父元素高度坍塌的问题
  2. 解决非浮动元素被浮动元素覆盖问题
  3. 解决外边距垂直方向重合的问题

2)介绍下 BFC、IFC、GFC 和 FFC

  1. BFC:块级格式上下文,指的是一个独立的布局环境,BFC 内部的元素布局与外部互不影响
  2. IFC:行内格式化上下文,将一块区域以行内元素的形式来格式化
  3. GFC:网格布局格式化上下文,将一块区域以 grid 网格的形式来格式化
  4. FFC:弹性格式化上下文,将一块区域以弹性盒的形式来格式化

(七)CSS 属性的计算过程

1.经典真题

  • 请简述 CSS 中属性的计算过程是怎样的

2.CSS 属性的计算过程

<p>this is a test</p>
p {
  color: red;
}
  • 这个元素所有的属性都拥有,只不过有一组默认的属性值

  • 确定声明值
  • 层叠冲突
  • 使用继承
  • 使用默认值

3.确定声明值

  • 没有书写任何 CSS 样式时,就采用浏览器的默认样式
  • 在样式表中对某一个元素书写样式声明时,这个声明就会被当作 CSS 的属性值
    • 这就是作者样式
  • 当作者样式和浏览器默认样式中的声明值有冲突时,会优先把 作者样式 中的声明值当作 CSS 的属性值

4.层叠冲突

  • 当样式表声明值有冲突时,就会使用层叠规则来确定 CSS 的属性值
<div class="test">
  <h1>test</h1>
</div>
.test h1 {
  font-size: 50px;
}
h1 {
  font-size: 20px;
}
  • 两个选择器都选中了 h1,并且都设置了 font-size 属性值
    • 同属于作者样式,属于层叠冲突
  • 根据 选择器的权重值 来计算究竟运用哪一条作者样式

5.使用继承

  • 如果属性没有设置作者样式,不会直接使用默认值,而是判断能否继承到该属性值
<div class="test">
  <p>this is a test</p>
</div>
.test {
  color: red;
}
  • 虽然没有在 p 段落上书写 color 属性,但是该属性能够从 div 上面继承而来,所以最终计算出来的值就是 red

6.使用默认值

  • 如果没有作者样式,该属性值也无法继承而来,则会使用浏览器的默认样式

7.真题解答

1)请简述 CSS 中属性的计算过程是怎样的

  1. 确定声明值:参考样式表中没有冲突的声明,作为 CSS 属性值
  2. 层叠冲突:对样式表有冲突的声明使用层叠规则,确定 CSS 属性值
  3. 使用继承:对仍然没有值的属性,若可以继承则继承父元素的值
  4. 使用默认值:对仍然没有值得属性,全部使用默认属性值

(八)CSS 层叠继承规则总结

1.经典真题

  • 请简述一下 CSS 中的层叠规则

2.CSS 中的层叠继承规则

  • 确定声明值
  • 层叠冲突
  • 使用继承
  • 使用默认值

3.层叠规则(Cascade)

  • CSS,Cascading Style Sheets
  • 什么选择器在层叠中胜出取决于三个因素
    • 这些都是按重量级顺序排列的
    • 前面的的一种会否决后一种
  • 重要性(Importance)
  • 专用性(Specificity)
  • 源代码次序(Source Order)

4.重要性

  • 在 CSS 中,有一个特别的语法可以让一条规则总是优先于其他规则: !important
  • 建议千万不要使用它,除非绝对必须使用
    • 当修改某个组件样式时,不能编辑该组件核心的 CSS 模块
    • 确实想要重写一种不能以其他方式覆盖的样式
  • !important 改变了层叠正常工作的方式,因此调试 CSS 问题,尤其是在大型样式表中,会变得非常困难

5.专用性/权重

  • 基本上是衡量选择器的具体程度的一种方法,主要是指能匹配多少元素

警告

元素选择器 < 类选择器 < ID 选择器 < style 中的样式或 !important

  • 专用性的量可以用四种不同的值(或组件)来衡量
    • 可以被认为是千位,百位,十位和个位,在四个列中的四个简单数字
  • 千位:如果声明是在 style 属性 中,该列加 1 分,否则为 0
    • 这样的声明没有选择器,所以专用性总是 1000
  • 百位:在整个选择器中每包含一个 ID 选择器 ,该列加 1 分
  • 十位:在整个选择器中每包含一个 类选择器、属性选择器、或者伪类 ,该列加 1 分
  • 个位:在整个选择器中每包含一个 元素选择器或伪元素,该列加 1 分

注意

通用选择器(*), 复合选择器(+、>、~、空格)和否定伪类(:not)在专用性中无影响

选择器千位百位十位个位合计值
h100010001
#identifier01000100
h1 + p::first-letter00030003
li > a[href*="zh-CN"] > .inline-warning00220022
没有选择器, 规则在一个元素的 style 属性里10001000

6.源代码次序

  • 如果多个相互竞争的选择器具有相同的重要性和专用性那么第三个因素将帮助决定哪一个规则获胜
  • 即:选择哪一个选择器取决于源码顺序
p {
  color: red;
}
p {
  color: blue;
}
  • 当多个 CSS 规则匹配相同的元素时,都被应用到该元素中
  • 只不过后面因为层叠规则被层叠掉了

7.继承规则

  • 继承就是应用于某个元素的一些属性值将由该元素的子元素继承,而有些则不会

能够被子元素继承的属性可以参阅:https://developer.mozilla.org/zh-CN/docs/Web/CSS/Referenceopen in new window

  • CSS 为处理继承提供了四种特殊的通用属性值
  • inherit:该值将应用到选定元素的属性值设置为与其 父元素 一样
  • initial:该值将应用到选定元素的属性值设置为与 浏览器默认样式表 中该元素设置的值一样
    • 如果浏览器默认样式表中没有设置值,并且该属性是自然继承的,那么该属性值就被设置为 inherit
  • unset:该值将属性重置为其 自然值
    • 如果属性是自然继承的,表现得像 inherit
    • 否则表现得像 initial
  • revert:如果当前的节点没有应用任何样式,则将该属性恢复到它 所拥有的值
    • 属性值被设置成自定义样式所定义的属性(如果被设置)
    • 否则属性值被设置成用户代理的默认样式

注意

initial 和 unset 不被 IE 支持

8.继承的就近原则

  • 属性值会继承离自己近的那个元素的属性
<div class="one">
  <div class="two">
    <p>Lorem ipsum dolor sit amet.</p>
  </div>
</div>
.two {
  color: blue;
}
.one {
  color: red;
}
  • two 比 one 更加接近 p
  • 最终采用的是 two 的 color 值,段落呈现蓝色

9.真题解答

1)请简述一下 CSS 中的层叠规则

CSS 中当属性值发生冲突时,通过层叠规则来计算出最终的属性值,层叠规则可以分为 3 块:

  1. 重要性(Importance):!important 设置该条属性值最重要,但是一般不推荐使用
  2. 专用性(Specificity):专用性主要是指它能匹配多少元素,匹配得越少专用性越高
  3. 源代码次序(Source order):在重要性和专用性都一致的情况下,属性值取决于源代码的先后顺序

(九)import 指令

1.经典真题

  • CSS 引用的方式有哪些?link 和 @import 的区别?

2.import 指令

  • 用于导入外部 CSS 样式
  • 类似于 link 标签

1)在 HTML 文件中导入外部样式

<style>
  @import url("./index.css");
</style>

2)在 CSS 文件中引入另一个 CSS 文件

@import url("./index.css");
/* 后面书写其他样式 */

3)@import 规则支持媒体查询

  • 可以允许依赖媒体的导入
@import "printstyle.css" print;
/* 只在媒体为 print 时导入 "printstyle.css" 样式表 */
@import "mobstyle.css" screen and (max-width: 768px);
/* 只在媒体为 screen 且视口最大宽度 768 像素时导入 "mobstyle.css" 样式表 */
  • link 标签除了可以加载 CSS 外,还可以做很多其它的事情
    • 比如定义 RSS,定义 rel 连接属性等
  • @import 就只能加载 CSS

2)加载顺序的差别

  • 只有当使用 @import 命令的宿主 css 文件被下载、解析之后,浏览器才会知道还有另外一个 css 需要下载
  • 这时才去下载,然后开始解析、构建 render tree 等一系列操作

3)兼容性的差别

  • 由于 @import 是 CSS2.1 提出的,所以旧浏览器不支持
  • 只有在 IE5 以上的才能识别
  • link 标签无此问题
  • 因为 @import 不是 DOM 可以控制的
  • 网站换皮肤可以通过改变 link 标签的 href 值来应用其它外部样式表
  • 但是无法操作 import,毕竟不是标签

5)从性能优化的角度来讲,要尽量避免使用 @import

  • 使用 @import 引入 CSS 会影响浏览器的并行下载
  • 多个 @import 会导致下载顺序紊乱
    • 在 IE 中,@import 会打乱资源文件的下载顺序
    • 即:排列在 @import 后面的 JS 文件先于 @import 下载
    • 并且打乱甚至破坏 @import 自身的并行下载

4.真题解答

CSS 引用的方式有:

  1. 外联,通过 link 标签外部链接样式表
  2. 内联,在 head 标记中使用 style 标记定义样式
  3. 嵌入,在元素的开始标记里通过 style 属性定义样式

link 和 @import 的区别:

  1. link 属于 HTML 标签,而 @import 完全是 CSS 提供的一种方式

link 标签除了可以加载 CSS 外,还可以做很多其它的事情,比如定义 RSS,定义 rel 连接属性等,@import 就只能加载 CSS 了


  1. 加载顺序的差别

比如,在 a.css 中使用 import 引用 b.css,只有当使用当使用 import 命令的宿主 css 文件 a.css 被下载、解析之后,浏览器才会知道还有另外一个 b.css 需要下载,这时才去下载,然后下载后开始解析、构建 render tree 等一系列操作


  1. 兼容性的差别

由于 @import 是 CSS2.1 提出的所以老的浏览器不支持,@import 只有在 IE5 以上的才能识别,而 link 标签无此问题


  1. 当使用 JS 控制 DOM 去改变样式的时候,只能使用 link 标签,因为 @import 不是 DOM 可以控制的

对于可换皮肤的网站而言,可以通过改变 link 便签这两个的 href 值来改变应用不用的外部样式表,但是对于 import 是无法操作的,毕竟不是标签。

(十)CSS3 的 calc 函数

1.经典真题

  • CSS 的计算属性知道吗?

2.CSS3 中的 calc 函数

  • calc,calculate,计算,是 CSS3 的一个新增的功能
  • MDN 的解释为可以用在任何长度、数值、时间、角度、频率等处
div {
  /* property: calc(expression) */
  width: calc(100% - 80px);
}
  • 可以用常见的 +-*/ 符号来进行运算
  • 需要注意的是 +- 必须用空格隔开
    • 如果和计算的数字挨在一起,则浏览器在解析时会认为这可能是一个正负值

更多关于 calc 函数信息可以参阅:https://developer.mozilla.org/zh-CN/docs/Web/CSS/calc()open in new window

3.真题解答

1)CSS 的计算属性知道吗?

即 calc() 函数,主要用于指定元素的长度,支持所有 CSS 长度单位,运算符前后都需要保留一个空格


比如:width: calc(100% - 50px);

(十一)CSS3 的媒体查询(media)

1.经典真题

  • 如何使用媒体查询实现视口宽度大于 320px 小于 640px 时,div 元素宽度变成 30%?

2.媒体查询

  • Media Query,会查询用户所使用的媒体或者媒介
  • 用于让一个页面适应不同的终端

3.Media Type 设备类型

  • 在 CSS2 中常碰到的就是 all(全部)、screen(屏幕)和 print(页面打印或打印预览模式)
  • 在 W3C 中共列出了 10 种媒体类型
设备类型
All所有设备
Braille盲人用点字法触觉回馈设备
Embossed盲文打印机
Handheld便携设备
Print打印用纸或打印预览视图
Projection各种投影设备
Screen电脑显示器
Speech语音或音频合成器
Tv电视机类型设备
Tty使用固定密度字母栅格的媒介,比如电传打字机和终端

4.媒体类型引用方法

  • 引用媒体类型的方法有和很多,常见的媒体类型引用方法有:link 标签、xml 方式、@import 和 CSS3 新增的 @media
  • 在 link 标签引用样式时,通过 link 标签中的 media 属性来指定不同的媒体类型
<link rel="stylesheet" href="index.css" media="screen" />
<link rel="stylesheet" href="print.css" media="print" />

2)xml 方式

  • xml 方式也是通过 media 属性来指定
<? xml-stylesheet rel="stylesheet" media="screen" href="style.css" ?>

3)@import

  • 主要有两种方式
  • 在 CSS 样式表中通过 @import 调用另一个样式文件
@import url("./index.css") screen;
  • 在 style 标签中引入
<style>
  @import url("./index.css") screen;;
</style>

注意

IE6 和 IE7 中不支持该方式

4)@media 的方式【常用】

  • 是 CSS3 中新引进的一个特性
  • 也有两种方式
  • 在样式文件中引入
@media screen {
  /* 具体样式 */
}
  • 在 style 标签中引入
<style>
  @media screen {
    /* 具体样式 */
  }
</style>

5.媒体查询具体语法

Media Type(判断条件)+ CSS(符合条件的样式规则)
  • link 的方式
<link rel="stylesheet" media="screen and (max-width:600px)" href="style.css" />
  • @media 的方式
@meida screen and (max-width:600px) {
  /* 具体样式 */
}

  • 语法模板
@media 媒体类型 and (媒体特性) {
  /* 具体样式 */
}

1)最大宽度 max-width

  • 该特性指媒体类型小于或等于指定宽度时,样式生效
@media screen and (max-width: 480px) {
  /* 具体样式 */
}

2)最小宽度 min-width

  • 该特性指媒体类型大于或等于指定宽度时,样式生效
@media screen and (min-width: 480px) {
  /* 具体样式 */
}

3)多个媒体特性混合使用

  • 当需要多个媒体特性时,使用 and 关键字将媒体特性结合在一起
@media screen and (min-width: 480px) and (max-width: 900px) {
  /* 具体样式 */
}

4)设备屏幕的输出宽度 Device Width

  • 在智能设备上,如:iphone、ipad 等,可以通过 min-device-width 和 max-device-width 来设置媒体特性
@media screen and (max-device-height: 480px) {
  /* 具体样式 */
}

5)not 关键字

  • 可以用来排除某种制定的媒体特性
@media not print and (max-width: 900px) {
  /* 具体样式 */
}

6)未指明 Media Type

  • 如果在媒体查询中没有明确的指定 Media Type,那么其默认值为 all
@media (max-width: 900px) {
  /* 具体样式 */
}

更多关于媒体查询的内容可以参阅 MDN:https://developer.mozilla.org/zh-CN/docs/Web/CSS/Media_Queries/Using_media_queriesopen in new window

6.真题解答

1)如何使用媒体查询实现视口宽度大于 320px 小于 640px 时,div 元素宽度变成 30%?

@media screen and (min-width: 320px) and (max-width: 640px) {
  div {
    width: 30%;
  }
}

(十二)过渡和动画事件

1.经典真题

  • CSS3 中 transition 和 animation 的属性分别有哪些(哔哩哔哩)
  • CSS 动画如何实现?

2.CSS3 过渡

  • 可以使从一个状态变化到另一个状态时的变化更加平滑

CSS3 的过渡功能像是一种黄油,W3C 标准中是这样描述 transition 的:

CSS3 的 transition 允许 CSS 的属性值在一定的时间区间内平滑的过渡

这种效果可以在鼠标单击,获得焦点,对元素任何改变中触发,并平滑地以动画效果改变 CSS 的属性值

3.transition 的具体语法

  • transition 属性是 transition-property,transition-duration,transition-timing-function 和 transition-delay 的一个简写属性
    • transition-property:指定过渡的 CSS 属性
    • transition-duration:指定过渡所需的完成时间
    • transition-timing-function:指定过渡函数
    • transition-delay:指定过渡的延迟时间

1)transition-property

  • 该属性用来指定过渡动画 CSS 属性名称
transition-property: none | all | property;

  • 不是所有的属性都可以进行过渡
  • 只有属性是 具有一个中点值 的属性才能够进行过渡效果
    • 因为这样才能通过不停的修改中间值从而实现过渡效果
    • 如:display:none|block;就没有中间值,所以无法应用过渡
  • 能够过渡的属性类型有颜色属性、具有长度值或百分比的属性、阴影、变形系列属性
background-colorbackground-positionborder-bottom-colorborder-bottom-width
border-left-colorborder-left-widthborder-right-colorborder-right-width
border-spacingborder-top-colorborder-top-widthbottom
clipcolorfont-sizefont-weight
heightleftletter-spacingline-height
margin-bottommargin-leftmargin-rightmargin-top
max-heightmax-widthmin-heightmin-width
opacityoutline-coloroutline-widthpadding-bottom
padding-leftpadding-rightpadding-topright
text-indenttext-shadowvertical-alignvisibility
widthword-spacingz-index

2)transition-duration

  • 该属性主要用于设置一个属性过渡到另一个属性所需要的时间
  • 单位为秒 s 或毫秒 ms
  • 默认值为 0,代表变换是即时的

3)transition-timing-function

  • 该属性用于设置过渡的速度

4)transition-delay

  • 过渡延迟多久触发
  • 单位为秒或毫秒
  • 值可以是正整数、负整数和 0
    • 负整数的计算会从整体过渡时间中去做减法运算
    • 相当于已经执行了几秒的过渡
div {
  width: 100px;
  height: 100px;
  background-color: skyblue;
  transition: all 5s -2s;
  /* 设置为 -2s,相当于已经执行了 2s */
}
div:hover {
  height: 300px;
}

4.多个元素过渡

  • 直接用逗号分离开即可
  • 主要是针对每个属性过渡的时间不同的情况
div {
  width: 100px;
  height: 100px;
  background-color: skyblue;
  transition:
    background-color 2s,
    height 5s;
}
div:hover {
  height: 300px;
  background-color: pink;
}

5.hover 时期不同的过渡设置

div {
  width: 100px;
  height: 100px;
  background-color: skyblue;
  transition: all 5s;
  /* 鼠标移走时的过渡 */
}
div:hover {
  height: 300px;
  background-color: pink;
  transition: all 2s;
  /* 鼠标 hover 时状态变化的过渡 */
}

6.过渡事件

  • 在 JS 中的某些操作需要过渡效果结束后再执行
  • 事件类型提供了一个 transitionend 事件监听过渡效果是否结束
<div id="oDiv"></div>
div {
  width: 100px;
  height: 100px;
  background-color: skyblue;
  transition: all 3s;
}
var div = document.getElementById("oDiv");
div.onclick = function () {
  div.style.height = "400px";
};
div.ontransitionend = function () {
  console.log("过渡结束后触发");
};

7.CSS3 动画

  • 在 CSS3 中新增了 animation 模块,可以制作出类似于 flash 一样的动画出来
  • 先用关键帧声明一个动画
  • 其次是在 animation 中调用关键帧声明的动画

1)声明动画

  • 使用 @keyframes 来声明一个动画
@keyframes animationname {
  keyframes-selector {
    css-styles;
  }
}

2)使用动画

  • @keyframes 只是用来声明一个动画
  • 如果一个声明的动画不被调用,那么这个动画不会被应用
animation: name duration timing-function delay iteration-count direction fill-mode play-state;
  • animation-name:指定要绑定到选择器的关键帧的名称
  • animation-duration:动画指定需要多少秒或毫秒完成
  • animation-timing-function:设置动画将如何完成一个周期
  • animation-delay:设置动画在启动前的延迟间隔
  • animation-iteration-count:定义动画的播放次数
  • animation-direction:指定是否应该轮流反向播放动画
  • animation-fill-mode:规定当动画不播放时(当动画完成时,或当动画有一个延迟未开始播放时),要应用到元素的样式
  • animation-play-state:指定动画是否正在运行或已暂停

3)animation-iteration-count

  • 定义动画应该播放多少次
  • 如果想要一直播放,那么次数就是无限次 infinite

4)animation-direction

  • 正常情况下,动画播放完毕以后,会立刻回到起始的状态
  • 该属性可以设置动画是否要反向播放回去
animation-direction: normal|reverse|alternate|alternate-reverse|initial|inherit;

  • 如果动画被设置为只播放一次,该属性将不起作用
  • 无论动画正向播放还是反向播放,都会算一次次数
div {
  width: 100px;
  height: 100px;
  background-color: skyblue;
  position: absolute;
  animation: test 5s 5 alternate;
}
@keyframes test {
  0% {
    left: 0;
    top: 0;
  }
  50% {
    left: 400px;
    top: 0;
  }
  100% {
    left: 400px;
    top: 200px;
  }
}
  • 在上面的代码中,一共播放 5 次,那么整个动画就会正向播放 3 次,反向播放 2 次

5)animation-fill-mode

  • 规定当动画不播放时(当动画完成时,或当动画有一个延迟未开始播放时),要应用到元素的样式
  • 一般主要用于设置动画播放完毕后的状态
animation-fill-mode: none|forwards|backwards|both|initial|inherit;

  • 用得最多的值就是 forwards,定义动画播放完后 保持结束帧
  • 默认值为 none,表示动画将按预期进行和结束,在动画完成其最后一帧时,动画会 反转到初始帧
  • 当取值为 backwards 时,会在动画结束时 迅速应用动画的初始帧

6)animation-play-state

  • 规定动画正在运行还是暂停
animation-play-state: paused|running;

  • 一般配合 JS 一起使用,从而达到对动画播放状态的一个控制
<button id="playAnimate">播放动画</button>
<button id="pauseAnimate">暂停动画</button>
<div id="oDiv"></div>
* {
  margin: 0;
  padding: 0;
}
div {
  width: 100px;
  height: 100px;
  background-color: skyblue;
  position: absolute;
  animation: test 2s 5 alternate paused;
}
@keyframes test {
  0% {
    left: 0;
    top: 30px;
  }
  50% {
    left: 400px;
    top: 30px;
  }
  100% {
    left: 400px;
    top: 200px;
  }
}
var oDiv = document.getElementById("oDiv");
var playAnimate = document.getElementById("playAnimate");
var pauseAnimate = document.getElementById("pauseAnimate");
playAnimate.onclick = function () {
  oDiv.style.animationPlayState = "running";
};
pauseAnimate.onclick = function () {
  oDiv.style.animationPlayState = "paused";
};

8.动画对应事件

  • animationstart:CSS 动画开始后触发
  • animationiteration:CSS 动画重复播放时触发
  • animationend:CSS 动画完成后触发

9.真题解答

1)CSS3 中 transition 和 animation 的属性分别有哪些(哔哩哔哩)

transition 过渡动画:

  1. transition-property:指定过渡的 CSS 属性
  2. transition-duration:指定过渡所需的完成时间
  3. transition-timing-function:指定过渡函数
  4. transition-delay:指定过渡的延迟时间

animation 关键帧动画:

  1. animation-name:指定要绑定到选择器的关键帧的名称
  2. animation-duration:动画指定需要多少秒或毫秒完成
  3. animation-timing-function:设置动画将如何完成一个周期
  4. animation-delay:设置动画在启动前的延迟间隔
  5. animation-iteration-count:定义动画的播放次数
  6. animation-direction:指定是否应该轮流反向播放动画
  7. animation-fill-mode:规定当动画不播放时(当动画完成时,或当动画有一个延迟未开始播放时),要应用到元素的样式
  8. animation-play-state:指定动画是否正在运行或已暂停

2)CSS 动画如何实现?

即 animation 属性,对元素某个或多个属性的变化进行控制,可以设置多个关键帧

属性包含了动画的名称、完成时间(以毫秒计算)、周期、间隔、播放次数、是否反复播放、不播放时应用的样式、动画暂停或运行

不需要触发任何事件就可以随着时间变化来改变元素的样式

使用 CSS 做动画:

  1. @keyframes:规定动画
  2. animation:所有动画属性的简写属性
  3. animation-name:规定 @keyframes 动画的名称
  4. animation-duration:规定动画完成一个周期所花费的秒或毫秒,默认是 0
  5. animation-timing-function:规定动画的速度曲线,默认是 ease
  6. animation-fill-mode:规定当动画不播放时(当动画完成时,或当动画有一个延迟未开始播放时),要应用到元素的样式
  7. animation-delay:规定动画何时开始,默认是 0
  8. animation-iteration-count:规定动画被播放的次数,默认是 1
  9. animation-direction:规定动画是否在下一周期逆向地播放,默认是 normal
  10. animation-play-state:规定动画是否正在运行或暂停,默认是 running

(十三)渐进增强和优雅降级

1.经典真题

  • 说说渐进增强和优雅降级?
  • 你能描述一下渐进增强和优雅降级之间的不同吗?

2.渐进增强

  • progressive enhancement
  • 指的是针对低版本浏览器进行构建页面,保证最基本的功能
  • 然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验
  • 相当于向上兼容

3.优雅降级

  • graceful degradation
  • 一开始就构建完整的功能
  • 然后再针对低版本浏览器进行兼容
  • 相当于向下兼容
    • 指的是高版本支持低版本
    • 或者说后期开发的版本能兼容早期开发的版本

4.区别

  • 优雅降级是从复杂的现状开始并试图减少用户体验的供给
    • 优先考虑新版本浏览器的可用性 ,最后才考虑老版本的可用性
    • 在前缀 CSS3 和正常 CSS3 都可用的情况下,前缀 CSS3 会覆盖正常的 CSS3
  • 渐进增强则是从一个基础的、能够起到作用的版本开始再不断扩充,以适应未来环境的需要
    • 优先考虑老版本浏览器的可用性 ,最后才考虑新版本的可用性
    • 在前缀 CSS3 和正常 CSS3 都可用的情况下,正常 CSS3 会覆盖前缀 CSS3

1)前缀 CSS3 和正常 CSS3 的支持情况

  • 前缀 CSS3:-webkit-、-moz-、-o-
  • 很久以前:浏览器前缀 CSS3 和正常 CSS3 都不支持
  • 不久之前:浏览器只支持前缀 CSS3,不支持正常 CSS3
  • 现在:浏览器既支持前缀 CSS3,又支持正常 CSS3
  • 未来:浏览器不支持前缀 CSS3,仅支持正常 CSS3

2)适用场景

  • 绝大多少的大公司都是采用渐进增强的方式
    • 因为业务优先,提升用户体验永远不会排在最前面
  • 如:新浪微博网站这样亿级用户的网站,前端的更新绝不可能追求某个特效而不考虑低版本用户是否可用
    • 一定是确保低版本到高版本的可访问性再渐进增强
  • 如果开发的是面向青少年的软件或网站,明确这个群体的人总是喜欢尝试新鲜事物,喜欢炫酷的特效,喜欢把软件更新至最新版本,再考虑优雅降级
.transition {
  /* 渐进增强写法 */
  -webkit-transition: all 0.5s;
  -moz-transition: all 0.5s;
  -o-transition: all 0.5s;
  transition: all 0.5s;
}
.transition {
  /* 优雅降级写法 */
  transition: all 0.5s;
  -o-transition: all 0.5s;
  -moz-transition: all 0.5s;
  -webkit-transition: all 0.5s;
}

5.真题解答

1)说说渐进增强和优雅降级?

渐进增强,英语全称 progressive enhancement,指的是针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验


优雅降级,英语全称 graceful degradation,一开始就构建完整的功能,然后再针对低版本浏览器进行兼容

(十四)CSS3 变形

1.经典真题

  • 请简述一下 CSS3 中新增的变形如何使用?

2.变形

CSS2.1 中的页面都是静态的,多年来,Web 设计师依赖于图片、Flash 或者 JavaScript 才能完成修改页面的外观

CSS3 改变了设计师这种思维,借助 CSS3 可以轻松的倾斜、缩放、移动以及翻转元素


2012 年 9 月,W3C 组织发布了 CSS3 变形工作草案

允许 CSS 把元素变成 2D 或者 3D 空间,这其实就是 CSS3 的 2D 变形和 3D 变形


CSS3 变形是一些效果的集合,比如平移、旋转、缩放和倾斜效果,每个效果通过变形函数(transform function)来实现

在此之前,要想实现这些效果,必须依赖图片、Flash 或者 JavaScript 才能完成,而现在仅仅使用纯 CSS 就能够实现,大大的提高了开发效率以及页面的执行效率

  • 变形效果要通过变形函数来实现
transform: none|transform-functions;
  • 具有 X/Y 的函数:translateX、translateY、scaleX、scaleY、skewX、skewY
  • 2D 变形函数:translate、scale、rotate、skew、matrix
  • 3D 变形函数:rotateX、rotateY、rotate3d、translateZ、translate3d、scaleZ、scale3d、matrix3d

3.变形属性

1)transform 属性

  • 该属性所对应的属性值就是一系列的变形函数
transform: scale(1.5);

2)transform-origin 属性

  • 该属性用于设置元素的中心点位置
  • 可以设置关键词,也可以是百分比、em、px 等具体的值
transform-origin: x-axis y-axis z-axis;

3)transform-style 属性

  • 是 3D 空间一个重要属性,指定了嵌套元素如何在 3D 空间中呈现
transform-style: flat | preserve-3d;

  • flat 为默认值
  • 需要设置在 父元素 上面,使其变成一个真正的 3D 图形
<div class="box">
  <div class="up"></div>
  <div class="down"></div>
  <div class="left"></div>
  <div class="right"></div>
  <div class="forward"></div>
  <div class="back"></div>
</div>
.box {
  width: 250px;
  height: 250px;
  border: 1px dashed red;
  margin: 100px auto;
  position: relative;
  border-radius: 50%;
  transform-style: preserve-3d;
  animation: gun 8s linear infinite;
}
.box > div {
  width: 100%;
  height: 100%;
  position: absolute;
  text-align: center;
  line-height: 250px;
  font-size: 60px;
  color: #daa520;
}
.left {
  background-color: rgba(255, 0, 0, 0.3);
  transform-origin: left;
  transform: rotateY(90deg) translateX(-125px);
}
.right {
  background: rgba(0, 0, 255, 0.3);
  transform-origin: right;
  /* 变换*/
  transform: rotateY(90deg) translateX(125px);
}
.forward {
  background: rgba(255, 255, 0, 0.3);
  transform: translateZ(125px);
}
.back {
  background: rgba(0, 255, 255, 0.3);
  transform: translateZ(-125px);
}
.up {
  background: rgba(255, 0, 255, 0.3);
  transform: rotateX(90deg) translateZ(125px);
}
.down {
  background: rgba(99, 66, 33, 0.3);
  transform: rotateX(-90deg) translateZ(125px);
}
@keyframes gun {
  0% {
    transform: rotateX(0deg) rotateY(0deg);
  }

  100% {
    transform: rotateX(360deg) rotateY(360deg);
  }
}

  • 在 box 元素上添加了 transform-style: preserve-3d;,表示 box 里面的子元素都以 3D 的形式呈现
  • 修改为 flat

4.perspective 属性

  • 用于设置查看者的位置,可以将可视内容映射到一个视锥上,继而投到一个 2D 视平面上
    • 如果不指定该属性,则 Z 轴空间中所有点将平铺到同一个 2D 视平面中,并且在变换结果中将不存在景深概念
  • 简单理解就是视距,用来设置用户和元素 3D 空间 Z 平面之间的距离
    • 而其效应由值来决定,值越小,用户与 3D 空间 Z 平面距离越近,视觉效果更令人印象深刻
    • 反之,值越大,用户与 3D 空间 Z 平面距离越远,视觉效果就很小

注意

当为元素定义 perspective 属性时,其子元素会获得透视效果,而不是元素本身

<div class="container">
  <div class="item"></div>
</div>
.container {
  width: 500px;
  height: 500px;
  border: 1px solid;
  margin: 100px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.item {
  width: 150px;
  height: 150px;
  background-color: red;
  animation: rotateAnimation 5s infinite;
}
@keyframes rotateAnimation {
  0% {
    transform: rotateY(0deg);
  }
  100% {
    transform: rotateY(360deg);
  }
}

  • 在上面的代码中,虽然设置了 div.item 沿着 Y 轴进行旋转
  • 但是由于没有设置 perspective 视距,所以看上去就像是 div 盒子在宽度伸缩一样,3D 效果并不明显
  • 此时可以给父元素 div.container 设置 perspective 视距
.container {
  /* ... */
  perspective: 1200px;
}

1)perspective 取值

  • 接受一个长度单位大于 0,且不能为百分比的值
    • none 或者不设置:没有 3D 空间
    • 取值越小:3D 效果越明显,也就是眼睛越靠近真 3D
    • 取值无穷大或者为 0:与取值为 none 的效果一样

2)perspective-origin 属性

  • 用于决定 perspective 属性的源点角度
perspective-origin: x-axis y-axis;

.container {
  /* ... */
  perspective: 600px;
  perspective-origin: top; /* 俯视效果 */
}

  • 如果修改为 bottom,则会是仰视的效果

5.backface-visibility 属性

  • 决定元素旋转时背面是否可见
  • 对于未旋转的元素,该元素的正面面向观看者
  • 当其旋转 180 度时会导致元素的背面面向观看者
  • 该属性设置在旋转的元素上面
backface-visibility: visible|hidden;

6.2D 变形

1)2D 位移

  • 对应有 3 个变形函数,分别是 translate、translateX、translateY
  • 从其当前位置移动元素(根据为 X 轴和 Y 轴指定的参数)
div {
  transform: translate(50px, 100px);
}

2)2D 缩放

  • 对应有 3 个变形函数,分别是 scale、scaleX、scaleY
  • 能够按照倍数放大或缩小元素的大小(根据给定的宽度和高度参数)
  • 默认值为 1,小于这个值就是缩小,大于这个值就是放大
div {
  transform: scale(2, 3);
}

3)2D 旋转

  • 对应有 1 个变形函数 rotate
  • 只接受一个值代表旋转的角度值
  • 取值可正可负,正值代表顺时针旋转,负值代表逆时针旋转
div {
  transform: rotate(20deg);
}

4)2D 倾斜

  • 对应有 3 个变形函数,分别是 skew、skewX、skewY
div {
  transform: skew(ax, ay);
}
  • ax:指定元素水平方向(X 轴方向)倾斜角度
  • ay:指定元素垂直方向(Y 轴方向)倾斜角度

7.2D 矩阵

  • 有些效果没有提供变形函数,如:镜像翻转的效果
  • 此时就需要 2D 矩阵函数 matrix
  • matrix 有六个参数
matrix(a,b,c,d,e,f)

1)六个参数对应的矩阵

2)计算坐标

  • 这六个参数组成的矩阵与原坐标矩阵相乘计算坐标

  • x 和 y 是元素中每一个像素的初始原点的坐标,而 x' 和 y' 是通过矩阵变化后得到的新原点坐标
  • 通过中间 3 x 3 变换矩阵,对原先的坐标施加变换,从而得到新的坐标
    • x' = ax + cy + e,表示变换后水平坐标
    • y' = bx + dy + f,表示变换后的垂直坐标
  • 所有 2D 变形函数都能够通过 matrix 矩阵函数来替代

3)矩阵实现偏移

x' = x + 偏移量
y' = y + 偏移量
  • 套用上面的公式那么各个参数的取值就应该是
a = 1; b = 0;
c = 0; d = 1;
e = x 偏移量; f = y 偏移量
x' = ax + cy + e = 1x + 0y + x 偏移量 = x + x 偏移量
y' = bx + dy + f = 0x + 1y + y 偏移量 = y + y 偏移量
  • 所以换成 matrix 函数就应该是
matrix(1, 0, 0, 1, x 偏移量, y 偏移量)

4)矩阵实现缩放

x' = x * x 缩放倍数
y’ = y * y 缩放倍数
  • 套用上面的公式就是
a = x缩放倍数; b = 0;
c = 0; d = y 缩放倍数;
e = 0; f = 0;
x' = ax + cy + e = x缩放倍数 * x + 0y + 0 = x缩放倍数 * x
y' = bx + dy + f = 0x + y 缩放倍数 * y + 0 = y 缩放倍数 * y
  • 所以换成 matrix 函数就应该是
matrix(x 缩放倍数, 0, 0, y 缩放倍数, 0, 0);

5)矩阵实现旋转

  • 旋转需要实现
水平倾斜角度 =  - 垂直倾斜角度
  • 变形函数是 rotate(θ),其中 θ 为旋转的角度
  • 套用上面的公式
x' = xcosθ - ysinθ + 0 = xcosθ - ysinθ;
y' = xsinθ + ycosθ + 0 = xsinθ + ycosθ
  • 转换为 matrix 的代码
matrix(cos(θ), sin(θ), -sin(θ), cos(θ), 0, 0)

6)矩阵实现倾斜

  • skew(θx, θy) 将一个元素按指定的角度在 X 轴和 Y 轴上倾斜
  • 倾斜对应的公式为
x' = x + ytan(θx) + 0 = x + ytan(θx)
y' = xtan(θy) + y + 0 = xtan(θy) + y
  • 转换为 matrix 的代码为
matrix(1,tan(θy),tan(θx),1,0,0)

7)矩阵实现镜像变形

a)水平镜像
  • y 坐标不变,x 坐标变负
x' = -x;
y' = y;

a = -1; b = 0;
c = 0; d = 1;
e = 0; f = 0;
  • 具体示例如下
div {
  width: 300px;
  height: 200px;
  margin: 150px;
  transition: all 1s;
  background: url("./ok.png") no-repeat;
  background-position: center;
  background-size: contain;
}
div:hover {
  transform: matrix(-1, 0, 0, 1, 0, 0);
}

b)垂直镜像
  • x 坐标不变,y 坐标变负
x' = x;
y' = -y;

a = 1; b = 0;
c = 0; d = -1;
e = 0; f = 0;
  • 具体示例如下
div:hover {
  transform: matrix(1, 0, 0, -1, 0, 0);
}

c)水平镜像 + 倒立
  • y 坐标变负,x 坐标变负
x' = -x;
y' = -y;

a = -1; b = 0;
c = 0; d = -1;
e = 0; f = 0;
  • 具体示例如下
div:hover {
  transform: matrix(-1, 0, 0, -1, 0, 0);
}

d)90 度旋转 + 镜像
x' = y;
y' = x;

a = 0; b = 1;
c = 1; d = 0;
e = 0; f = 0;
  • 具体示例如下
div:hover {
  transform: matrix(0, 1, 1, 0, 0, 0);
}

e)-90 度旋转 + 镜像
x' = -y;
y' = -x;

a = 0; b = -1;
c = -1; d = -0;
e = 0; f = 0;
  • 具体示例如下
div:hover {
  transform: matrix(0, -1, -1, 0, 0, 0);
}

8.3D 变形

  • 使用三维变形,可以改变元素在 Z 轴的位置

  • 3D 位移:包括 translateZ 和 translate3d 两个变形函数
  • 3D 旋转:包括 rotateX、rotateY、rotateZ 和 rotate3d 这四个变形函数
  • 3D 缩放:包括 scaleZ 和 scale3d 两个变形函数
  • 3D 矩阵:和 2D 变形一样,也有一个 3D 矩阵功能函数 matrix3d

1)3D 位移

div {
  transform: translate3d(tx, ty, tz);
}
  • tx:在 X 轴的位移距离
  • ty:在 Y 轴的位移距离
  • tz:在 Z 轴的位移距离
    • 值越大,元素离观察者越近
    • 值越小,元素离观察者越远

2)3D 旋转

  • 对应的变形函数有 rotateX、rotateY、rotateZ 以及 rotate3d
  • rotate3d 就是前面 3 个变形函数的复合函数
    • 不过除了 x、y、z 这三条轴的参数以外,还接受第四个参数 a,表示旋转角度
div {
  transform: rotate3d(x, y, z, a);
}
  • x:可以是 0 到 1 之间的数值,表示旋转轴 X 坐标方向的矢量
  • y:可以是 0 到 1 之间的数值,表示旋转轴 Y 坐标方向的矢量
  • z:可以是 0 到 1 之间的数值,表示旋转轴 Z 坐标方向的矢量
  • a:表示旋转角度
    • 正的角度值表示顺时针旋转
    • 负值表示逆时针旋转

3)3D 缩放

  • 主要有 scaleZ 和 scale3d
  • scale3d 就是 scaleX、scaleY 以及 scaleZ 的复合变形函数
div {
  transform: scale(sx, sy, sz);
}
  • sx:X 轴上的缩放比例
  • sy:Y 轴上的缩放比例
  • sz:Z 轴上的缩放比例
  • scaleZ 是 Z 轴上面的缩放,也就是厚度上面的变化
    • 所以如果不是立方体结构,基本上是看不出来 Z 轴上面的缩放效果的
  • 一般来讲,不会将 scaleZ 和 scale3d 单独使用
    • 因为 scaleZ 和 scale3d 这两个变形函数在单独使用时没有任何效果
    • 需要配合其他的变形函数一起使用时才会有效果

9.3D 矩阵

  • CSS3 中的 3D 矩阵比 2D 矩阵复杂,从二维到三维,在矩阵里 3*3 变成 4*4,即 9 到 16

1)3D 缩放

div {
  transform: matrix3d(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0, 0, 0, 0, 1);
}

2)倾斜

  • 倾斜是二维变形,不能在三维空间变形
  • 元素可能会在 X 轴和 Y 轴倾斜,然后转化为三维,但不能在 Z 轴倾斜

3)其他 3D 函数

  • translate3d(tx,ty,tz) 等价于 matrix3d(1,0,0,0,0,1,0,0,0,0,1,0,tx,ty,tz,1)

  • scale3d(sx,sy,sz) 等价于 matrix3d(sx,0,0,0,0,sy,0,0,0,0,sz,0,0,0,0,1)

  • rotate3d(x,y,z,a) 第四个参数 alpha 用于 sc 和 sq 中

10.真题解答

1)请简述一下 CSS3 中新增的变形如何使用?

在 CSS3 中的变形分为 2D 变形和 3D 变形


整体可以划分出 3 大类:

  1. 具有 X/Y 的函数:translateX、translateY、scaleX、scaleY、skewX、skewY
  2. 2D 变形函数:translate、scale、rotate、skew、matrix
  3. 3D 变形函数:rotateX、rotateY、rotate3d、translateZ、translate3d、scaleZ、scale3d、matrix3d

另外,还有一些重要的变形属性,如:

  1. transform 属性
  2. transform-origin 属性
  3. transform-style 属性
  4. perspective 属性
  5. perspective-origin 属性
  6. backface-visibility 属性

(十五)渐进式渲染

1.经典真题

  • 什么是渐进式渲染?

2.渐进式渲染

  • progressive rendering,也被称为惰性渲染
  • 指的是为了提高用户感知的加载速度,以尽快的速度来呈现页面的技术的集合

3.骨架屏

  • 在加载网络数据时,为了提升用户体验,通常会使用一个 loading 动画
  • 或者使用 Skeleton Screen 占位
  • 相比与 loading 动画,Skeleton Screen 的效果要更生动

4.图片懒加载

  • 先加载部分图片,剩余的图片等到需要的时候再加载
  • 在电商网站中尤其常见

5.图片占位符

  • 在网页加载的时候,某些图片还在请求中或者还未请求
  • 先找一个临时代替的图像,放在最终图像的位置上
  • 当图片数据准备好以后,会重新渲染真正的图形数据

6.拆分网页资源

  • 大部分用户不会用到一个网站的所有页面,但通常的做法却是把所有的功能都打包进一个很大的文件里面
    • 一个 bundle.js 文件的大小可能会有几 M
    • 一个打包后的 style.css 会包含网站的一切样式,从 CSS 结构定义到网站在各个版本的样式:移动端、平板、桌面、打印版等等
  • 但用户并不是一开始就需要所有的资源,所有可以对资源进行拆分
    • 首先加载关键的资源
    • 其他的资源等到需要的时候再去加载它

更多的关于渐进式渲染的内容,可以参阅 MDN:https://developer.mozilla.org/zh-CN/docs/Web/Progressive_web_apps/Loadingopen in new window

7.真题解答

1)什么是渐进式渲染?

渐进式渲染,英文全称 progressive rendering,也被称之为惰性渲染,指的是为了提高用户感知的加载速度,以尽快的速度来呈现页面的技术

但是这并不是某一项技术的特指,而是一系列技术的集合


例如:

  1. 骨架屏
  2. 图片懒加载
  3. 图片占位符
  4. 资源拆分

(十六)CSS 渲染性能优化

1.经典真题

  • 总结一下如何提升或者优化 CSS 的渲染性能

2.性能优化意义

1)用户角度

  • 网站优化能够让页面加载得更快,响应更加及时,极大提升用户体验

2)服务商角度

  • 优化会减少页面资源请求数,减小请求资源所占带宽大小,从而节省可观的带宽资源

3)目标

  • 减少网站加载时间,提高响应速度

4)网站加载速度和用户体验

Google 和亚马逊的研究表明,Google 页面加载的时间从 0.4 秒提升到 0.9 秒导致丢失了 20% 流量和广告收入

对于亚马逊,页面加载时间每增加 100ms 就意味着 1% 的销售额损失

  • 一个好的交互效果

3.CSS 性能优化

1)使用 id selector 非常的高效

  • 因为 id 是唯一的,所以不需要既指定 id 又指定 tagName
/* Bad  */
p#id1 {
  color: red;
}

/* Good  */
#id1 {
  color: red;
}

2)避免深层次的 node

/* Bad  */
div > div > div > p {
  color: red;
}

/* Good  */
p-class {
  color: red;
}

3)不要使用 attribute selector

  • 如:p[att1="val1"]
    • 这样的匹配非常慢
  • 如:p[id="id1"]
    • id selector 退化成 attribute selector
/* Bad  */
p[id="jartto"] {
  color: red;
}
p[class="blog"] {
  color: red;
}

/* Good  */
#jartto {
  color: red;
}
.blog {
  color: red;
}

4)通常将浏览器前缀置于前面,将标准样式属性置于最后

.foo {
  -moz-border-radius: 5px;
  border-radius: 5px;
}

推荐参阅 CSS 规范-优化方案:http://nec.netease.com/standard/css-optimize.htmlopen in new window

5)遵守 CSSLint 规则

规则说明
font-faces不能使用超过 5 个 web 字体
import禁止使用@import
regex-selectors禁止使用属性选择器中的正则表达式选择器
universal-selector禁止使用通用选择器*
unqualified-attributes禁止使用不规范的属性选择器
zero-units0 后面不要加单位
overqualified-elements使用相邻选择器时,不要使用不必要的选择器
shorthand简写样式属性
duplicate-background-images相同的 url 在样式表中不超过一次

更多的 CSSLint 规则可以参阅:https://github.com/CSSLint/csslintopen in new window

6)不要使用 @import

  • 会影响浏览器的并行下载
  • 多个 @import 会导致下载顺序紊乱

7)避免过分重排(Reflow)

  • 重排,浏览器重新计算布局位置与大小
  • 常见的重排元素
widthheightpaddingmargindisplay
border-widthbordertoppositionfont-size
floattext-alignoverflow-yfont-weightoverflow
leftfont-familyline-heightvertical-alignright
clearwhite-spacebottommin-height

8)依赖继承

  • 如果某些属性可以继承,那么自然没有必要再声明一遍

4.真题解答

1)总结一下如何提升或者优化 CSS 的渲染性能

CSS 渲染性能的优化来自方方面面,这里列举一些常见的方式:

  1. 使用 id 选择器非常高效,因为 id 是唯一的
  2. 避免深层次的选择器嵌套
  3. 尽量避免使用属性选择器,因为匹配速度慢
  4. 使用渐进增强的方案
  5. 遵守 CSSLint 规则
  6. 不要使用 @import
  7. 避免过分重排(Reflow)
  8. 依赖继承
  9. 值缩写
  10. 避免耗性能的属性
  11. 背景图优化合并
  12. 文件压缩

(十七)层叠上下文

1.经典真题

  • 请简述什么是层叠上下文、什么是层叠等级、什么是层叠顺序

2.层叠上下文

1)HTML 文档中的三维概念

  • HTML 文档中的元素是存在于三个维度中的
  • x 轴通常用来表示水平位置
  • y 轴来表示垂直位置
  • z 轴表示屏幕内外方向上的位置

  • 在 CSS 中要确定沿着 z 轴排列元素,表示的是用户与屏幕的这条看不见的垂直线

  • Stacking Context,层叠上下文,就是 HTML 中的一个三维的概念
  • 如果一个元素含有层叠上下文,可以理解为这个元素在 z 轴上就“高人一等”,最终表现就是它离屏幕观察者更近

2)创建层叠上下文

  • HTML 中的根元素 HTML 本身就具有层叠上下文,称为根层叠上下文
  • 普通元素设置 position 属性为非 static 值,并设置 z-index 属性为具体数值,会产生层叠上下文
  • CSS3 中的新属性也可以产生层叠上下文
<div class="one"></div>
<div class="two"></div>
div {
  width: 200px;
  height: 200px;
}
.one {
  background-color: red;
}
.two {
  background-color: blue;
  margin-top: -100px;
}
  • 默认情况下后来居上,蓝色的会盖住红色的

  • 给红色设置一个定位
.one {
  background-color: red;
  position: relative;
  z-index: 1;
}
  • 由于设置了定位和 z-index 属性,所以红色的 div 会创建一个层叠上下文

3.层叠等级与层叠顺序

  • 都用来表述在同一个层叠上下文中,元素在 z 轴上的显示顺序
    • 层叠等级,Stacking Level,是概念
    • 层叠顺序,Stacking Order,是具体规则

1)CSS2.1 年代的层叠顺序规则

2)两个元素在同一个层叠上下文中

  • 层叠等级越大的元素,就越靠前
  • 层叠等级的高低规则是由层叠顺序来体现的
  • 当两个元素层叠等级相同、层叠顺序相同时,在 DOM 结构中后面的元素层叠等级在前面元素之上

3)两个元素不在同一个层叠下上文中

  • 比较所处的层叠上下文的层叠等级【“从父”现象】

假设一个官员 A 是个省级领导,他下属有一个秘书 a-1,家里有一个保姆 a-2。另一个官员 B 是一个县级领导,他下属有一个秘书 b-1,家里有一个保姆 b-2。

a-1 和 b-1 虽然都是秘书,但是你想一个省级领导的秘书和一个县级领导的秘书之间有可比性么?甚至保姆 a-2 都要比秘书 b-1 的等级高得多。谁大谁小,谁高谁低一目了然,所以根本没有比较的意义。

因此只有在 A 下属的 a-1、a-2 以及 B 下属的 b-1、b-2 中相互比较大小高低才有意义。

4.实战案例

1)示例 1

<div class="one">
  <div class="item" style="background-color: black; z-index: 99;"></div>
</div>
<div class="two">
  <div class="item" style="background-color: pink;top: 50px; z-index: 1;"></div>
</div>
div {
  width: 200px;
  height: 200px;
}
.one {
  background-color: red;
  position: relative;
  z-index: 1;
}
.two {
  background-color: blue;
  position: relative;
  z-index: 2;
}
.item {
  width: 100px;
  height: 100px;
  position: absolute;
  left: 200px;
  top: 200px;
}
  • one 和 two 分别有自己的层叠上下文,但是 two 的层叠等级要比 one 高
  • 无论 one 中的子元素的 z-index 设置有多高,始终被 two 的子元素给覆盖
  • 因为如果两个元素不在同一层叠上下文中,比较的是所在层叠上下文的等级

2)示例 2

<div class="box1">
  <div class="child1"></div>
</div>

<div class="box2">
  <div class="child2"></div>
</div>
.box1,
.box2 {
  position: relative;
}
.child1 {
  width: 200px;
  height: 100px;
  background: #168bf5;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
}
.child2 {
  width: 100px;
  height: 200px;
  background: #32c292;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
}
  • .box1/.box2 虽然设置了相对定位,但是没有设置 z-index
  • 所以仍然是普通元素,.child1/.child2 属于 html 元素的“根层叠上下文”中
  • 也就是处于同一个层叠上下文中,根据层叠顺序谁的 z-index 值大,谁在上面

3)示例 3

.box1,
.box2 {
  position: relative;
  z-index: 0;
}
  • 仅仅修改了 .box1/.box2 的 z-index 属性值,最终结果完全相反
  • 因为设置 z-index: 0 后,.box1/.box2 产生了各自的层叠上下文
  • 这时候要比较 .child1/.child2 的层叠关系,属于不同的层叠上下文进行比较,由各自所在的层叠等级决定
  • 但是 .box1/.box2 的 z-index 值都为 0,都是块级元素
    • 所以它们的层叠等级,层叠顺序是相同的
    • 这种情况下,在 DOM 结构中后面的覆盖前面的,所以 .child2 就在上面

4)示例 4

<div class="box">
  <img src="./ok.png" alt="" class="item" />
</div>
.box {
  width: 200px;
  height: 200px;
  background: blue;
  position: absolute;
}
.item {
  position: absolute;
  width: 200px;
  left: 50px;
  top: 50px;
  z-index: -1;
}
  • .box 虽然设置了定位,但是并没有设置 z-index 属性
  • 所以并不会产生层叠上下文,仅仅是一个普通元素
  • 此时 .item 图片属于 html 元素的“根层叠上下文”中
  • 根据层叠顺序谁的 z-index 值大,谁在上面

5)示例 5

.box {
  width: 200px;
  height: 200px;
  background: blue;
  position: relative;
  z-index: 99;
}
  • 为 .box 添加一个 z-index 属性,并且给了一个很大的值,此时图片却在上面
  • 因为当 .box 设置了 z-index 后,就会产生一个层叠上下文
  • 也就是说对 .item 图片而言,找到的层叠上下文是 .box 而不是 html 根元素
  • 而根据层叠顺序,background 是处于最下层的,所以图片显示在了最上面

6)示例 6

<div class="parent">
  parent
  <div class="child1">child1</div>
  <div class="child2">
    child2
    <div class="child2-1">child2-1</div>
    <div class="child2-2">child2-2</div>
  </div>
</div>
.parent {
  width: 100px;
  height: 200px;
  background: #168bf5;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 0;
}
.child1 {
  width: 100px;
  height: 200px;
  background: #32d19c;
  position: absolute;
  top: 20px;
  left: 20px;
  z-index: 1;
}
.child2 {
  width: 100px;
  height: 200px;
  background: #e4c950;
  position: absolute;
  top: 40px;
  left: 40px;
  z-index: -1;
}
.child2-1 {
  width: 100px;
  height: 200px;
  background: #e45050;
  position: absolute;
  top: 60px;
  left: 60px;
  z-index: 9999;
}
.child2-2 {
  width: 100px;
  height: 200px;
  background: #db68a7;
  position: absolute;
  top: 80px;
  left: 40px;
  z-index: -9999;
}
  • .child1 和 .child2 处于同一个层叠上下文中,所以 .child1 在 .child2 的上面(因为 .child1 的 z-index 值更大)
  • 而 .child2-1 和 .child2-2 也是处于同一个层叠上下文 .child2 里面
  • 所以无论 .child2 的 z-index 值有多大,都一定在 .child2-1 和 .child2-2 下面
  • .child2-1 和 .child2-2 则根据 z-index 值的大小来决定谁覆盖谁

5.CSS3 中属性对层叠上下文的影响

  • 父元素的 display 属性值为 flex|inline-flex,子元素 z-index 属性值不为 auto 的时候,子元素为层叠上下文元素
  • 元素的 opacity 属性值不是 1
  • 元素的 transform 属性值不是 none
  • 元素 mix-blend-mode 属性值不是 normal
  • 元素的 filter 属性值不是 none
  • 元素的 isolation 属性值是 isolate
  • will-change 指定的属性值为上面任意一个
  • 元素的 -webkit-overflow-scrolling 属性值设置为 touch
<div class="box">
  <div class="parent">
    parent
    <div class="child">child</div>
  </div>
</div>
.box {
}
.parent {
  width: 200px;
  height: 100px;
  background: #168bf5;
  /* 虽然设置了z-index,但是没有设置position,z-index 无效,.parent还是普通元素,没有产生层叠上下文 */
  z-index: 1;
}
.child {
  width: 100px;
  height: 200px;
  background: #32d19c;
  position: relative;
  z-index: -1;
}
  • .child 被 .parent 覆盖了
  • 虽然 .parent 设置了 z-index 属性值,但是没有设置 position 属性,z-index 无效,所以没有产生层叠上下文,仍然是一个普通的块级元素
  • .child 的层叠上下文为 html 根元素,z-index 小于 0 的 .child 会被普通的 block 块级元素 .parent 覆盖

.box {
  display: flex;
}
  • 当给 .box 设置 display: flex; 时,.parent 也会变成一个弹性项目,成为一个层叠上下文元素
  • 于是对于 .child 来讲找到的层叠上下文就是 .parent 而非 html 根元素
  • 根据层叠顺序规则,层叠上下文元素的 background/border 的层叠等级小于 z-index 值小于 0 的元素的层叠等级
  • 所以 z-index 值为 -1 的 .child 在 .parent 上面

6.真题解答

1)请简述什么是层叠上下文、什么是层叠等级、什么是层叠顺序

层叠上下文概念

在 CSS2.1 规范中,每个盒模型的位置是三维的,分别是平面画布上的 X 轴,Y 轴以及表示层叠的 Z 轴

一般情况下,元素在页面上沿 X 轴 Y 轴平铺,我们察觉不到它们在 Z 轴上的层叠关系

而一旦元素发生堆叠,这时就能发现某个元素可能覆盖了另一个元素或者被另一个元素覆盖


层叠上下文触发条件

  1. HTML 中的根元素 HTML 本身就具有层叠上下文,称为“根层叠上下文”
  2. 普通元素设置 position 属性为非 static 值并设置 z-index 属性为具体数值,产生层叠上下文
  3. CSS3 中的新属性也可以产生层叠上下文

层叠等级

如果两个元素在同一个层叠上下文中,那么层叠等级越大的元素,就越靠前

层叠等级是一个概念,层叠等级的大小可以根据层叠顺序来进行判断


层叠顺序

层叠顺序表示元素发生层叠时按照特定的顺序规则在 Z 轴上垂直显示

说简单一点就是当元素处于同一层叠上下文内时如何进行层叠判断

(十八)CSS3 遮罩

1.CSS3 遮罩介绍

CSS mask 遮罩属性的历史非常久远了,远到比 CSS3 border-radius 等属性还要久远,最早是出现在 Safari 浏览器上的,差不多可以追溯到 2009 年

不过那个时候,遮罩只能作为实验性的属性,做一些特效使用。毕竟那个年代还是 IE 浏览器的时代,属性虽好,但价值有限

但是如今情况却大有变化,除了 IE 浏览器不支持,Firefox、Chrome、Edge 以及移动端等都已经全线支持,其实际应用价值已不可同日而语

尤其 Firefox 浏览器,从版本 53 开始,已经全面支持了 CSS3 mask 属性

并且 mask 属性规范已经进入候选推荐规范之列

1)首先需要准备两张图片

  • 一张 jpg 图片:zelda.jpg
  • 一张 png 图片:mask.png,该 png 图片 背景为透明

2)index.html

<div class="mask"></div>
* {
  margin: 0;
  padding: 0;
}
div {
  width: 1200px;
  height: 600px;
  outline: 1px solid;
  margin: 50px auto;
  background: url("./zelda.jpg") no-repeat center/cover;
}
/*  
  虽然 .mask 和 div 都是选择中的相同的元素
  这里为了单独观察 mask 相关设置,
  和 mask 不相关的属性设置放入到了 div 选择器中 
*/
.mask {
  -webkit-mask-image: url("./mask.png");
}
  • 为 div 设置了一个铺满整个盒子的背景图,然后为该盒子设置了遮罩效果
  • 由于 mask.png 无法占满整个盒子,所以出现了重复的效果
  • mask.png 遮罩图片透明的部分不会显示底部图片的信息,而非透明部分则会显示底层图片信息

  • 除了设置透明的 png 图片,还可以设置透明的渐变
.mask {
  -webkit-mask-image: linear-gradient(transparent 10%, white);
}

  • 无论是设置图片还是渐变,一定要有透明的部分,否则无法起到遮罩的效果

2.遮罩各属性介绍

1)mask-image

  • 默认值为 none,表示没有遮罩图片
  • 可以设置的值为透明图片,或透明渐变

2)mask-repeat

  • 表示遮罩层是否允许重复
  • 默认值为 repeat 允许重复
  • 可选值与 background-repeat 相同
.mask {
  -webkit-mask-image: url("./mask.png");
  -webkit-mask-repeat: no-repeat;
}

3)mask-position

  • 设置遮罩层的位置
  • 默认值为 0 0,在最左上角
  • 可选值与 background-position 相同
.mask {
  -webkit-mask-image: url("./mask.png");
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: center;
}

4)mask-size

  • 设置遮罩层的大小
  • 默认值为 auto
  • 可选值与 background-size 相同

.mask {
  -webkit-mask-image: url("./mask.png");
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: center;
  -webkit-mask-size: contain;
}

5)mask-origin

  • 默认值为 border-box
  • 可选值与 background-origin 相同

div {
  width: 1200px;
  height: 600px;
  border: 100px solid;
  margin: 50px auto;
  background: url("./zelda.jpg") no-repeat center/cover;
}
.mask {
  -webkit-mask-image: url("./mask.png");
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-origin: content-box;
}

6)mask-clip

  • 默认值为 border-box
  • 可选值与 background-clip 相同

.mask {
  -webkit-mask-image: url("./mask.png");
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-clip: content-box;
}

7)mask-mode

  • 默认值为 match-source,作用是根据资源的类型自动采用合适的遮罩模式
    • 如:遮罩效果使用的是 SVG 中的 <mask> 元素,则此时的值为 luminance,表示基于亮度来判断是否要进行遮罩
    • 如果是其他场景,则计算值是 alpha,表示基于透明度判断是否要进行遮罩
  • 可选值为 alpha、luminance、match-source
  • 使用搜索引擎搜索遮罩素材的时候,往往搜索的结果都是白底的 JPG 图片,因此使用默认的遮罩模式是没有预期的遮罩效果的,此时就非常适合设置遮罩模式为 luminance

目前仅 Firefox 浏览器支持 mask-mode 属性,Chrome 浏览器并不提供支持,但是可以使用非标准的 mask-source-type 属性来进行替代(没有私有前缀)

  • 准备一张 mask2.jpg 的遮罩图片,该素材首先是 jpg 格式的,其次并没有透明区域,仅有一些白底区域
.mask {
  -webkit-mask-image: url("./mask2.jpg");
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-mode: luminance;
}

8)mask-type

  • 功能和 mask-mode 属性类似,都是设置不同的遮罩模式
  • 但是 mask-type 属性只能作用于 SVG 元素上
    • 因为其本质上是由 SVG 属性演变而来的,Chrome 等浏览器也都支持该属性
    • 而 mask-mode 是一个针对所有元素类型的 CSS 属性,Chrome 等浏览器并不支持该属性,目前仅只有 Firefox 浏览器对其提供支持
  • 默认值表现为 SVG 元素默认遮罩模式,也就是默认值是 luminance 亮度遮罩模式
  • 如果需要支持透明度遮罩模式,可以设置为 alpha
mask-type: alpha;

9)mask-composite

  • 表示同时使用多张图片进行遮罩时的合成方式
  • 默认值为 add
  • 可选值为 add、subtract、intersect、exclude
属性值含义
add表示遮罩累加
默认值
subtract表示遮罩相减,也就是遮罩图片重合的区域不显示
遮罩层图片越多,遮罩区域越小
intersect表示遮罩相交,也就是遮罩图片重合的区域才显示遮罩
exclude表示遮罩排除,也就是遮罩图片重合的区域会被当作透明
上次编辑于: