面试中要是被问到css相关的问题基本上就是白给了,都是些基础知识,赶在金三银四之前,我们来复习下关于css的面试题
这里总结了16个近年来关于css面试热点问题,文章有点长,建议收藏下来慢慢消化
一、请说说你对css盒模型的理解
通常回答这类问题(谈谈什么,说说对什么的理解)是有个套路的,不要上来就急着回答他是用来干嘛的,一般都是先回答是什么,有哪些,然后其作用特点。
是什么
css盒模型,用于描述在浏览器当中渲染引擎计算一个文档的布局时,将左右的元素表示成一个个矩形的盒子。css盒模型有两种,一个是标准盒模型,一个是怪异盒模型或者说是IE盒模型
标准盒模型
标准盒模型的总宽度 == 宽width + 内边距padding + 边框border + 外边距margin
实际上盒子自身的宽度无论那个盒模型都不算上
margin
外边距
对于谷歌浏览器,默认行为就是标准盒模型,比如下面写的样式其宽度就是300 + 5 * 2 + 10 * 2 + 20 * 2 == 370
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 300px;
height: 300px;
border: 5px solid #000;
padding: 10px;
margin: 20px;
}
</style>
</head>
<body>
<div class="box">盒子模型</div>
</body>
</html>
怪异盒模型/IE盒模型
IE盒模型的总宽度 == 宽width + 外边距margin
以前的IE浏览器就是IE盒模型,现在IE浏览器已经没了,如果还想用这个盒模型就需要加上box-sizing: border-box;
,box-sizing
的默认值就是content-box
,也就是标准盒模型
既然总宽度变成了宽度加上外边距,所以宽度为300就是新width + padding + border
,padding
和border
将自身的宽度挤进去了点,当你写样式时,为了防止撑大你可以用IE盒模型。
这就有点像是买110平的房子,住进去其实就是90平,因为人家还算上了公摊,这就类似怪异盒模型
二、css中的选择器有哪些?说说优先级
css选择器就是些你写样式时定位到某个地方的东西,比如下面的内容
<body>
<div id="app">
<div class="box1">
<div class="title">
<h2>这是标题</h2>
</div>
</div>
</div>
<div class="box2"></div>
<div class="box2"></div>
<div class="box3"></div>
<input type="text" abc="abc">
<input type="text">
</body>
-
id选择器
#app { /* 用 # 指定 */ }
-
类名选择器
.box1 { /* 用 . 指定 */ } .box1, .box2, .box3 { /* 可以同时选中,同级关系 */ }
-
后代选择器
#app div{ /* id里面指定某个标签 div中所有的东西都会影响 */ }
-
子级选择器
#app > div{ /* id里面指定某个标签 与上面的区别是div里面的其他标签不会受影响 */ }
-
相邻兄弟选择器
.box1 + .box2 { /* 只有靠着box1的第一个box2才会生效 */ }
-
群组选择器
#app .box2 { /* id中指定某个类名 */ }
-
属性选择器
input[abc ='abc'] { /* 指定带有某个属性的标签 */ }
-
伪元素选择器
#input::after{ /* 伪元素 第二个值还可以写before */ content: ''; display: block; } #input::before{ content: ''; display: block; }
-
伪类选择器
#input:hover { /* 鼠标上去有颜色效果 */ } #input:focus { /* 聚焦才有效果 */ }
优先级
!important > 内联 > id选择器 > 类名选择器 > 标签选择器
内联就是写在body中的样式,如
<div class="box2" style="background-color: yellow;"></div>
三、说说css中的单位有哪些
-
px : 像素单位 ,屏幕上的发光点
-
rem : 相对单位, 相对于根字体大小,html默认就是16px
-
em : 相对单位,用于字体上其会继承父容器的字体大小,用在它处,是相对于当前容器自己的字体大小来定的
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .box{ font-size: 30px; } .wrap{ font-size: 20px; } h2{ font-size: 1em; } </style> </head> <body> <div class="box"> <div class="wrap"> <h2>hello world</h2> </div> </div> </body> </html>
这种情况,h2的字体大小就是20px。如果把wrap样式删掉就是30px,所以这个父容器字体大小是可以被继承的
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> h2{ font-size: 10px; width: 10em; height: 10em; background-color: blue; } </style> </head> <body> <div class="box"> <div class="wrap"> <h2>hello world</h2> </div> </div> </body> </html>
这里没用在字体上,此时的h2容器就是宽高各100px
-
vw / vh : 相对单位,相对于窗口宽高比
-
% : 相对单位,相对于父容器
四、说说设备像素,css像素,设备独立像素,dpr, dpi之间的区别
-
pc端 1px === 1个物理像素
如今的手机两倍屏 1px === 0.5物理发光点,也就是一个设备独立像素 === 两个物理像素
-
页面缩放比为1:1 时,1px === 1个物理像素
设备像素就是物理屏幕上的实际像素,比如分辨率1920 * 1080 的屏幕有1920个水平像素和1080个垂直像素
css像素就是浏览器使用的单位,就是通常说的px
设备独立像素在不同的设备上会映射到不同数量的物理像素,取决于设备
设备像素 == 物理像素
css像素 == 1px
设备独立像素 == 分辨率
dpr(Device Pixel Ratio设备像素比) === 设备像素 / 设备独立像素 ; iphone6是两倍屏手机 就是 宽750 / 375 = 2
就是高清屏,iPhone6 plus 的dpr为3就是超高清屏
dpi是像素密度
五、关于css中,有哪些方式可以隐藏页面的元素,区别是什么
隐藏元素有display
,visibility
,opacity
,position
,clip-path
这些方法,要讨论其区别就需要涉及到文档流,事件,回流重绘。
回流就是计算布局,重绘就是上色,详情见输入url到页面渲染后半段:回流,重绘,优化【一次性带你搞明白】 - 掘金 (juejin.cn)
我们可以给隐藏的元素添加一个点击事件,最后会发现,这些方法中仅有修改透明度的方法是可以响应事件的。另外opacity还非常特殊,如果是有动画的opacity,那么它还不会重绘
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 200px;
height: 200px;
background-color: blue;
opacity: 0;
animation: hide 2s ease; /* GPU有个加速能力,动用了这个能力是不会重绘的 */
}
@keyframes hide {
/* css定义动画的语法 */
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
</style>
</head>
<body>
<div class="box"></div>
<script>
let box = document.querySelector('.box')
box.addEventListener('click', () => {
console.log('box');
})
</script>
</body>
</html>
animation动画属性非常特殊,只要动用了这个属性就不会发生重绘,因为是GPU的加速模式在发挥作用,不发挥这个作用那么动画就会发生重绘
用position定位隐藏就是将其飞出屏幕之外,比如left: -9999px
,top: -9999px
。
relative是相对自身的位置作定位,absolute是相对于外层具有position属性的容器,无论什么参数,没有的话就是相对于html
clip-path是裁剪的属性,可以将元素裁剪为指定的形状,使得元素只显示裁剪区域的内容,隐藏裁剪外的元素
display: none | 脱离文档流 | 无响应事件 | 发生回流重绘 |
---|---|---|---|
visibility: hidden | 占据文档流 | 无响应事件 | 不发生回流,但重绘 |
opacity: 0 | 占据文档流 | 可响应事件 | 不发生回流,但重绘,若是动画,则不发生回流重绘 |
position: absolute | 脱离文档流 | 无响应事件 | 发生回流重绘 |
clip-path: circle(0%) | 占据文档流 | 无响应事件 | 不发生回流,但重绘 |
前四个方法都是非常常见的,最后一个方法如果能答出,那么就非常棒了
六、谈谈你对BFC的理解
又是这类问题,遵循套路,是什么,再谈其特征,作用。这个问题详情见面试官问你浮动?深入剖析浮动与BFC----全程干货分享 - 掘金 (juejin.cn)
是什么
BFC全称为Block Formatting Context
是块级格式化上下文,是css用于描述块级盒子布局的一种方式,有一套属于自己的渲染规则
渲染规则
BFC让浮动元素的高度也会计算在内
比如我给一个ul,里面有3个li,3个li都浮动起来,那么ul的高度会变成0,将ul变成BFC容器,那么ul就会被li撑起
BFC可以阻止子元素的margin-top和父容器重叠
我们看一个情景,给每一个li都添加一个margin-top
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
li {
list-style: none;
width: 200px;
height: 50px;
background-color: chocolate;
margin-top: 30px;
}
</style>
</head>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</body>
</html>
按道理ul是会占据上面的空隙,但实际上没有,这就是个bug
如果我们将ul设置成BFC容器,那么就可以解决这个问题
其余的规则就不值得说了,比如从上到下,从左到右的布局
有哪些属性可以触发BFC
- float: left || right(会脱离文档流)
- position: absolute(相对于父容器) || fixed(固定的,相对于整个窗口)(会脱离文档流)
- display: inline-block || flex || inline-flex || grid || table-cell....大部分以table开头的属性
- overflow: hidden || overlay(超出覆盖) || auto || scroll
应用
最多的应用就是清除浮动,这点我在上面挂的文章中讲的非常深入了
七、水平垂直居中的方式有哪些?
css要么不问,要么必问这个问题
同样一个情景:两个方块,大的包含小的,让小的水平垂直居中
方法一:定位 absolute + translate
给top和left分别一个50%,然后自身再top和left负50%
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 500px;
height: 500px;
background-color: rgb(28, 101, 164);
position: relative;
}
.wrap {
width: 200px;
height: 200px;
background-color: green;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
/* margin-top: -100px; */
/* margin-left: -100px; */
}
</style>
</head>
<body>
<div class="box">
<div class="wrap"></div>
</div>
</body>
</html>
当然,已知宽高的时候你也可以不用translate,直接换成margin-left: -100px;
和margin-top: -100px
方法二:弹性flex
父容器弹性并且给子元素在父容器的主轴和交叉轴居中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 500px;
height: 500px;
background-color: rgb(28, 101, 164);
display: flex;
justify-content: center;
align-items: center;
}
.wrap {
width: 200px;
height: 200px;
background-color: green;
}
</style>
</head>
<body>
<div class="box">
<div class="wrap"></div>
</div>
</body>
</html>
justify-content: center
是主轴居中,align-item: center
是交叉轴居中
方法三:网格布局grid
写法和弹性一模一样
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 500px;
height: 500px;
background-color: rgb(28, 101, 164);
display: grid;
justify-content: center;
align-items: center;
}
.wrap {
width: 200px;
height: 200px;
background-color: green;
}
</style>
</head>
<body>
<div class="box">
<div class="wrap">hhhhhh</div>
</div>
</body>
</html>
方法四:表格布局table,text-align和vertical-align
用表格布局就需要用上text-align: center
来居中,那么就需要子元素是非块级元素,所以将子元素设置display: inline-block
成为行内块,表格元素在y轴上居中用vertical-align: middle;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 500px;
height: 500px;
background-color: rgb(28, 101, 164);
display: table-cell;
text-align: center;
vertical-align: middle;
}
.wrap {
display: inline-block;
width: 200px;
height: 200px;
background-color: green;
}
</style>
</head>
<body>
<div class="box">
<div class="wrap">hhhhhh</div>
</div>
</body>
</html>
文字水平垂直居中 text-align、line-height
对于文字的水平垂直居中,你可以使用text-align: center
和line-height
来设置,line-height
的参数设置成父容器的高即可
块级元素仅水平居中 margin: 0 auto
margin: 0 auto
常见于仅水平居中块级元素,无法垂直居中
八、三栏布局怎么实现
提到三栏布局大家脑海肯定先蹦出个圣杯,双飞翼布局
所谓三栏布局就是,两边固定中间自适应变化,比如vant
官网这里
三栏布局之前顺带看下两栏布局的实现
两栏布局
两栏布局就是一栏固定,另一栏自适应。常见于后台管理系统
方法一:弹性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.wrap {
display: flex;
height: 200px;
}
.left {
width: 200px;
height: 100%;
background-color: antiquewhite;
}
.right {
flex: 1;
background-color: aqua;
height: 100%;
}
</style>
</head>
<body>
<div class="wrap">
<div class="left">left</div>
<div class="right">right</div>
</div>
</body>
</html>
一方固定宽度,另一方flex给1继承其余的宽度即可
方法二:网格grid
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.wrap {
display: grid;
grid-template-columns: 200px 1fr;
height: 200px;
}
.left {
height: 100%;
background-color: antiquewhite;
}
.right {
background-color: aqua;
height: 100%;
}
</style>
</head>
<body>
<div class="wrap">
<div class="left">left</div>
<div class="right">right</div>
</div>
</body>
</html>
网格布局,一方固定,另一方给1列即可
方法三:float + margin-left
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.wrap {
height: 200px;
}
.left {
width: 200px;
height: 100%;
background-color: antiquewhite;
float: left;
}
.right {
background-color: aqua;
height: 100%;
margin-left: 200px;
}
</style>
</head>
<body>
<div class="wrap">
<div class="left">left</div>
<div class="right">right</div>
</div>
</body>
</html>
仅仅给左侧加左浮,右边的区域会被左侧覆盖,但你会发现文字没被覆盖,为何右侧文字不被覆盖?这就是浮动的初衷,文字环绕。如何解决覆盖问题,加个margin-left
即可
三栏布局
方法一:弹性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.wrap {
height: 200px;
display: flex;
}
.left {
width: 200px;
height: 100%;
background-color: aqua;
}
.content {
height: 100%;
background-color: red;
flex: 1;
}
.right {
width: 200px;
height: 100%;
background-color: blue;
}
</style>
</head>
<body>
<div class="wrap clear">
<div class="left">left</div>
<div class="content">content</div>
<div class="right">right</div>
</div>
</body>
</html>
一样的道理,两边固定,中间给flex: 1
即可
方法二:网格grid
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.wrap {
height: 200px;
display: grid;
grid-template-columns: 200px 1fr 200px;
}
.left {
height: 100%;
background-color: aqua;
}
.content {
height: 100%;
background-color: red;
}
.right {
height: 100%;
background-color: blue;
}
</style>
</head>
<body>
<div class="wrap clear">
<div class="left">left</div>
<div class="content">content</div>
<div class="right">right</div>
</div>
</body>
</html>
同样的,两边固定宽度,中间给一列
方法三:左右先加载,中间后加载 float + margin
用浮动做三栏布局才是最经典的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.wrap {
height: 200px;
}
.left {
width: 200px;
height: 100%;
background-color: aqua;
float: left;
}
.right {
width: 200px;
height: 100%;
background-color: blue;
float: right;
}
.content {
height: 100%;
background-color: red;
margin-left: 200px;
margin-right: 200px;
}
</style>
</head>
<body>
<div class="wrap clear">
<div class="left">left</div>
<div class="content">content</div>
<div class="right">right</div>
</div>
</body>
</html>
这里如果你直接用左边左浮,右边右浮,然后中间给左右一个margin会发现效果是这样的
为什么右边的下去了?左边的左浮了,脱离了文档流,content
紧接着占据了一整行,没有脱离文档流,margin
也算上自身的宽度,然后right
发现,第一行被content
全占了,而且有个左边的左浮,已经没有容身之所让右边在第一行右浮了。这讲究一个先来后到,既然如此,我在body
中把content
放到最后加载不就可以了,确实可以,但是这样不优雅,一般给用户看三栏布局一定是中间的内容最先出来
所以目前来看,这个方法就是左右先加载,中间后加载的浮动
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.wrap {
height: 200px;
}
.left {
width: 200px;
height: 100%;
background-color: aqua;
float: left;
}
.right {
width: 200px;
height: 100%;
background-color: blue;
float: right;
}
.content {
height: 100%;
background-color: red;
margin-left: 200px;
margin-right: 200px;
}
</style>
</head>
<body>
<div class="wrap clear">
<div class="left">left</div>
<div class="right">right</div>
<div class="content">content</div>
</div>
</body>
</html>
方法四:圣杯布局 float + margin负值 + position: relative
继续,如果把content放在最上面,优先加载,那么效果是这样的我们可以理解
解决这个办法有个响当当的名词就是圣杯布局,这个方法非常巧妙
既然content占据了文档流,致使后面两个浮动下移了,那我就全部都浮动起来,右边的一部分也改其为左浮,这样,三个模块就会在同一行,并且是content,left,right依次排序。这个时候给整个容器wrap加上两边的内边距,位置不够,致使left和right下移,其实还是在同一行,只是因为同一行站不下了才导致的换行。
<style>
.wrap {
height: 200px;
padding: 0 200px 0 200px;
}
.left {
width: 200px;
height: 100%;
background-color: aqua;
float: left;
}
.right {
width: 200px;
height: 100%;
background-color: blue;
float: left;
}
.content {
float: left;
width: 100%;
height: 100%;
background-color: red;
}
</style>
注意,这个时候一定要记住,left,right都是在content的同一行,紧随其后,所以我给left部分加上一个margin-left: -100%
让他跑到父容器的最左边
然后给让其向左移动自身的宽度200px即可,也就是相对自身距离右边200px
现在操作right,right也是在content后面,我先让他向左移动200px,也就是margin-left: -200px
此时效果
此时再让他相对自身右移200px即可。也就是距离左边200px。
最终实现代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.wrap {
height: 200px;
padding: 0 200px 0 200px;
}
.left {
width: 200px;
height: 100%;
background-color: aqua;
float: left;
margin-left: -100%;
position: relative;
right: 200px;
}
.right {
width: 200px;
height: 100%;
background-color: blue;
float: left;
margin-left: -200px;
position: relative;
left: 200px;
}
.content {
float: left;
width: 100%;
height: 100%;
background-color: red;
}
</style>
</head>
<body>
<div class="wrap clear">
<div class="content">content</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
</body>
</html>
方法五:双飞翼布局 float + margin负值
双飞翼布局和圣杯布局有异曲同工之妙,先有圣杯后有的双飞翼
先丢份完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.wrap {
height: 200px;
}
.container {
height: 100%;
width: 100%;
background-color: red;
padding: 0 200px 0 200px;
box-sizing: border-box;
float: left;
}
.left {
width: 200px;
height: 100%;
background-color: aqua;
float: left;
margin-left: -100%;
}
.right {
width: 200px;
height: 100%;
background-color: blue;
float: left;
margin-left: -200px;
}
</style>
</head>
<body>
<div class="wrap clear">
<div class="container">
<div class="content">content</div>
</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
</body>
</html>
双飞翼布局同样是保证优先加载content
,与圣杯布局不同点在于它给中间的content
套了层容器包裹,样式重新从那个新包裹下手,新包裹container
给上一个两边的内边距,同样三个部分都需要向左浮动,由于有了padding
,这里需要打上IE盒模型,防止撑大,然后给left
置左,给right
向左移动200px即可
相比较圣杯布局,为何双飞翼布局不需要定位就可以实现这个效果?
因为中间的部分被包裹的容器就是wrap
的大小,然后left
和right
的父容器又恰好是wrap,刚好直接排在container
的右边,让left
置左,让right
向左移动即可
九、说说flexbox
问你弹性盒子就是问你弹性布局,弹性布局很容易被字节问到,弹性布局是现在最推荐的一种布局方式,因为太强大了
是什么
是一种布局方式,可以简便完整响应式的实现页面布局,容器默认存在两条轴,一个主轴,一个交叉轴,默认x轴为主轴,可以用flex-direction
来修改主轴的方向
css的响应式指的是屏幕变小,容器也跟着变小
特征
- 可以控制子元素在主轴上的对齐方式:
justify-content
- 可以控制子元素在交叉轴上的对齐方式:
align-items
- 可以控制元素的缩放比例,排列方式:
flex-grow, flex-shrink, order
应用场景
- 多栏布局
- 居中
十、css3新增了哪些属性
这个问题翻看前两年大家的面经还经常出现,现在少见了
尽管css3停留在这个版本很久了,但是有些新增的属性浏览器的兼容性依旧跟不上
- 选择器:属性选择器在css2是没有的,还有像是
last-child
这样的伪类选择器 - 盒子阴影
box-shadow
- 裁剪:
clip-path
裁剪以及background-clip
背景图裁剪 - 过度动画:
transition
- 转换
transform
:,平移,缩放,旋转,倾斜 - 纯动画
animation
- 颜色渐变
background: linear-gradient()
十一、css3中常见的动画有哪些?怎么实现
过渡动画transition
当其他属性值发生变更时,transition
可以控制变更所花费的时间以及变更曲线
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box{
width: 200px;
height: 50px;
background-color: blueviolet;
/* transition: width 2s linear; */
/* 2s内 linear匀速 ease慢快慢 ease-in越来越快 ease-out越来越慢 ease-in-out快到慢*/
transition: width 2s cubic-bezier(0.075, 0.82, 0.165, 1);
/* 贝塞尔曲线这个参数先快速上涨,后慢速下降 */
}
.box:hover{
/* 伪类选择器,鼠标移上去时宽度变成500 */
width: 500px;
}
</style>
</head>
<body>
<div class="box"></div>
</body>
</html>
转换动画transform
用于做容器的平移,缩放,旋转,倾斜等动画,可以搭配transition
过渡动画使其更优雅
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.wrap{
margin-top: 30px;
width: 200px;
height: 50px;
background-color: red;
transition: all 2s;
}
.wrap:hover{
transform: translateX(100px) rotateZ(90deg);
/* 从左往右移100px 绕z轴旋转90° */
}
</style>
</head>
<body>
<div class="wrap"></div>
</body>
</html>
纯动画animation
控制容器动画的关键帧
如何理解这个关键帧:就是以一个时间动下,取决于刷新率,60hz时间是16.7ms,120hz就是16.7/2ms。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
margin-top: 30px;
width: 200px;
height: 50px;
background-color: aquamarine;
animation: rotate 2s linear infinite;
/* infinite是无限循环 */
}
@keyframes rotate {
/* 自定义动画名 */
0%{
transform: rotateZ(0deg);
}
100%{
transform: rotateZ(360deg);
}
}
</style>
</head>
<body>
<div class="container"></div>
</body>
</html>
三个动画效果如下
十二、说说回流重绘
这个问题也有可能放在js中聊,之前也单独出过文章讲过,详情见输入url到页面渲染后半段:回流,重绘,优化【一次性带你搞明白】 - 掘金 (juejin.cn)
是什么
回流:浏览器渲染页面之前需要对结构进行布局计算
重绘:将已经计算好布局的容器绘制出来
触发
触发回流:页面上有容器的几何属性发生变更
触发重绘:容器非几何属性变更,比如颜色等
所以回流一定重绘,但是重绘不一定回流
十三、什么是响应式?
是什么
跟随用户页面设备尺寸的变化,页面实现自动的适配
比如你逛掘金的商城页面,缩放页面的时候发现1000-1160宽是一个适配,1160以外又是一个适配
实现方案
-
弹性布局:适合做某个容器内的响应式,比如
ul
的li
,但是不方便做整个页面的响应式弹性容器默认就是让子元素在收缩放大时平均分配
-
百分比:常适用于页面外层大容器,同样不适合整个页面的响应式,一般适配都是pc端一个,平板一个,手机一个,百分比过于灵活不适合
百分比继承父容器
-
rem + 媒体查询 (可用于任何地方,一般pc端是rem + 媒体查询,移动端是rem + js)
rem是参照根字体大小,css有媒体查询的语法,写法参考如下,
min-width
到max-width
就是区间<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; } li{ list-style: none; width: 200px; height: 100px; } li:nth-child(1){ background-color: antiquewhite; } li:nth-child(2){ background-color: aqua; } li:nth-child(3){ background-color: aquamarine; } li:nth-child(4){ background-color: azure; } li:nth-child(5){ background-color: black; } li:nth-child(6){ background-color: blueviolet; } </style> <style> li { width: 10rem; /* pc端用媒体查询 移动端用js处理 */ } @media screen and (min-width: 1000px) { /* 大于1000时 变化 pc端 */ html{ font-size: 30px; } } @media screen and (min-width: 800px) and (max-width: 1000px) { /* 平板端 */ html{ font-size: 20px; } } @media screen and (max-width: 500px) { /* 手机端 */ html{ font-size: 14px; } } </style> </head> <body> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> </ul> </body> </html>
-
直接媒体查询,不如第三个方法,这个代码量会很大
一个区间写一个样式,代码量会很大
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; } li{ list-style: none; width: 200px; height: 100px; } li:nth-child(1){ background-color: antiquewhite; } li:nth-child(2){ background-color: aqua; } li:nth-child(3){ background-color: aquamarine; } li:nth-child(4){ background-color: azure; } li:nth-child(5){ background-color: black; } li:nth-child(6){ background-color: blueviolet; } </style> <style> @media screen and (min-width: 1000px) { li{ width: 300px; } } @media screen and (min-width: 800px) and (max-width: 1000px) { li{ width: 200px; } } @media screen and (max-width: 500px) { li{ width: 100px; } } </style> </head> <body> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> </ul> </body> </html>
-
vw
/vh
:相对于window大小<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; } li{ list-style: none; width: 200px; height: 100px; } li:nth-child(1){ background-color: antiquewhite; } li:nth-child(2){ background-color: aqua; } li:nth-child(3){ background-color: aquamarine; } li:nth-child(4){ background-color: azure; } li:nth-child(5){ background-color: black; } li:nth-child(6){ background-color: blueviolet; } </style> <style> li{ width: 20vw; } </style> </head> <body> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> </ul> </body> </html>
十四、视差滚动效果如何实现
是什么
视差滚动是多层背景以不同的速度进行移动,实现视觉上的落差
比如这个效果
实现
方法一:background-attachment: fixed;
背景图像将会相对于视口固定不动,即无论页面如何滚动,背景图像都会保持在固定的位置
一个小demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
div{
height: 100vh;
background: rgba(0,0,0,0.7);
color: white;
font-size: 20vh;
text-align: center;
line-height: 100vh;
}
.box.img:nth-child(2){
background-position: center center;
/* 背景图片水平垂直居中 */
background-size: cover;
/* 覆盖整个屏幕 */
background-attachment: fixed;
/* 固定在最底层 */
background-image: url('https://ts3.cn.mm.bing.net/th?id=ORMS.342b2c95ab5ae7570c0d0d3a0a68004d&pid=Wdp&w=300&h=156&qlt=90&c=1&rs=1&dpr=1.25&p=0');
}
.box.img:nth-child(4){
background-position: center center;
background-size: cover;
background-attachment: fixed;
background-image: url('https://ts3.cn.mm.bing.net/th?id=ORMS.3f01fc441c612e673867c31284341c43&pid=Wdp&w=612&h=304&qlt=90&c=1&rs=1&dpr=1.25&p=0');
}
.box.img:nth-child(6){
background-position: center center;
background-size: cover;
background-attachment: fixed;
background-image: url('https://ts3.cn.mm.bing.net/th?id=ORMS.03797ce48cbc07bf9815a05232c35b27&pid=Wdp&w=300&h=156&qlt=90&c=1&rs=1&dpr=1.25&p=0');
}
.box.img:nth-child(8){
background-position: center center;
background-size: cover;
background-attachment: fixed;
background-image: url('https://ts3.cn.mm.bing.net/th?id=ORMS.b6811d54e9b136fca2e95d3603e9b3dc&pid=Wdp&w=300&h=156&qlt=90&c=1&rs=1&dpr=1.25&p=0');
}
</style>
</head>
<body>
<div class="box">1</div>
<div class="box img">2</div>
<div class="box">3</div>
<div class="box img">4</div>
<div class="box">5</div>
<div class="box img">6</div>
<div class="box">7</div>
<div class="box img">8</div>
</body>
</html>
效果如下
方法二:perspective + translateZ
同样一个小demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
html{
height: 100%;
overflow: hidden;
}
body{
height: 100%;
}
#app{
width: 100vw;
height: 400px;
text-align: center;
font-style: 30px;
padding-top: 100px;
overflow-y: scroll;
perspective: 1px;
/* 设置3d角度 视角安置在z轴的1px位置 滚动速度一样 由于近大远小 才感觉速度不一 */
/* transform-style: preserve-3d; */
}
.box1{
height: 200px;
width: 500px;
background: #d98383;
}
.box2{
height: 200px;
width: 500px;
background: #f62020;
transform: translateZ(-3px);
}
.box3{
height: 200px;
width: 500px;
background: #641a42;
transform: translateZ(-1px);
}
</style>
</head>
<body>
<div id="app">
<div class="box1">1</div>
<div class="box2">2</div>
<div class="box3">3</div>
</div>
</body>
</html>
效果如下
这个原理就是通过把视角位置安置在z轴的1px位置,然后朝着三个box看过去,由于三个box在z轴的位置不同,导致近大远小,滑动速度就会感觉不一样
十五、css画一个三角形
这个问题也是非常容易被问到的
用边框画三角形
将边框变大,然后不给宽度,之后就是个正方形,四条边,给任意三条边透明色就剩余一个三角形,想要变成一个边框我们可以加一个伪元素覆盖上去,伪元素覆盖部分须是透明色,这里也顺带实现了个扇形
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.box{
/* width: 50px; */
/* height: 50px; */
border: 50px solid;
/* border-color: #ccc #d61c1c #16bab2 #d1dd1f; */
/* box-sizing: border-box; */
border-color: transparent transparent #16bab2 #d1dd1f;
position: relative;
}
.box::after{
/* 伪元素使其变成空心 */
content: '';
position: absolute;
border: 34px solid;
border-color: transparent transparent #fff #fff;
left: -40px;
bottom: -40px;
}
.box2{
/* 扇形 */
border: 50px solid;
border-color: #ccc transparent transparent transparent;
border-radius: 50%;
}
</style>
</head>
<body>
<div class="box"></div>
<div class="box2"></div>
</body>
</html>
效果如下
canvas画布是js部分,如果可以用canvas画就方便很多
十六、如何显示一个小于10px的文字
目前谷歌浏览器默认字体大小是16px,以前谷歌浏览器最小支持的字体像素就是10px,但是目前最新版本的谷歌浏览器可以直接设置任意大小像素的字体,包括10像素以下
所以你可以直接告诉面试官,新版本的谷歌浏览器是可以支持任意像素的文字的
那么其他浏览器怎么办
zoom
和transform: scale
都是缩放属性
zoom
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box{
font-size: 20px;
zoom: 0.25;
}
</style>
</head>
<body>
<div class="box">hello world</div>
</body>
</html>
transform: scale()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box{
font-size: 20px;
transform: scale(0.25);
}
</style>
</head>
<body>
<div class="box">hello world</div>
</body>
</html>
最后
这些问题可能你都能回答出来,但是对于面试,一定是要尽量全部说出来,现在的环境都越来越卷了,别人回答得比你多你就输了,同时欢迎各位补充
另外有不懂之处欢迎在评论区留言,如果觉得文章对你学习有所帮助,还请”点赞+评论+收藏“一键三连,感谢支持!