最新css面试题汇总【助力金三银四】

4,398 阅读23分钟

面试中要是被问到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>

1.png

怪异盒模型/IE盒模型

IE盒模型的总宽度 == 宽width + 外边距margin

以前的IE浏览器就是IE盒模型,现在IE浏览器已经没了,如果还想用这个盒模型就需要加上box-sizing: border-box;box-sizing的默认值就是content-box,也就是标准盒模型

既然总宽度变成了宽度加上外边距,所以宽度为300就是新width + padding + borderpaddingborder将自身的宽度挤进去了点,当你写样式时,为了防止撑大你可以用IE盒模型。

这就有点像是买110平的房子,住进去其实就是90平,因为人家还算上了公摊,这就类似怪异盒模型

2.png

二、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>
  1. id选择器

    #app {
    	/* 用 # 指定 */
    }
    
  2. 类名选择器

    .box1 {
        /* 用 . 指定 */
    }
    
    .box1, .box2, .box3 {
        /* 可以同时选中,同级关系 */
    }
    
  3. 后代选择器

    #app div{
        /* id里面指定某个标签 div中所有的东西都会影响 */
    }
    
  4. 子级选择器

    #app > div{
        /* id里面指定某个标签 与上面的区别是div里面的其他标签不会受影响 */
    }
    
  5. 相邻兄弟选择器

    .box1 + .box2 {
        /* 只有靠着box1的第一个box2才会生效 */
    }
    
  6. 群组选择器

    #app .box2 {
        /* id中指定某个类名 */
    }
    
  7. 属性选择器

    input[abc ='abc'] {
        /* 指定带有某个属性的标签 */
    }
    
  8. 伪元素选择器

    #input::after{
        /* 伪元素 第二个值还可以写before */
        content: '';
        display: block;
    }
    
    #input::before{
        content: '';
        display: block;
    }
    
  9. 伪类选择器

    #input:hover {
        /* 鼠标上去有颜色效果 */
    }
    
    #input:focus {
        /* 聚焦才有效果 */
    }
    

优先级

!important > 内联 > id选择器 > 类名选择器 > 标签选择器

内联就是写在body中的样式,如

<div class="box2" style="background-color: yellow;"></div>

三、说说css中的单位有哪些

  1. px : 像素单位 ,屏幕上的发光点

  2. rem : 相对单位, 相对于根字体大小,html默认就是16px

  3. 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

  4. vw / vh : 相对单位,相对于窗口宽高比

  5. % : 相对单位,相对于父容器

四、说说设备像素,css像素,设备独立像素,dpr, dpi之间的区别

  1. pc端 1px === 1个物理像素

    如今的手机两倍屏 1px === 0.5物理发光点,也就是一个设备独立像素 === 两个物理像素

  2. 页面缩放比为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中,有哪些方式可以隐藏页面的元素,区别是什么

隐藏元素有displayvisibilityopacitypositionclip-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: -9999pxtop: -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

3.png

如果我们将ul设置成BFC容器,那么就可以解决这个问题

4.png

其余的规则就不值得说了,比如从上到下,从左到右的布局

有哪些属性可以触发BFC

  1. float: left || right(会脱离文档流)
  2. position: absolute(相对于父容器) || fixed(固定的,相对于整个窗口)(会脱离文档流)
  3. display: inline-block || flex || inline-flex || grid || table-cell....大部分以table开头的属性
  4. 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: centerline-height来设置,line-height的参数设置成父容器的高即可

块级元素仅水平居中 margin: 0 auto

margin: 0 auto常见于仅水平居中块级元素,无法垂直居中

八、三栏布局怎么实现

提到三栏布局大家脑海肯定先蹦出个圣杯,双飞翼布局

所谓三栏布局就是,两边固定中间自适应变化,比如vant官网这里

1.gif

三栏布局之前顺带看下两栏布局的实现

两栏布局

两栏布局就是一栏固定,另一栏自适应。常见于后台管理系统

方法一:弹性

<!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会发现效果是这样的

5.png

为什么右边的下去了?左边的左浮了,脱离了文档流,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放在最上面,优先加载,那么效果是这样的我们可以理解

6.png

解决这个办法有个响当当的名词就是圣杯布局,这个方法非常巧妙

既然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>

7.png

注意,这个时候一定要记住,left,right都是在content的同一行,紧随其后,所以我给left部分加上一个margin-left: -100%让他跑到父容器的最左边

8.png

然后给让其向左移动自身的宽度200px即可,也就是相对自身距离右边200px

9.png

现在操作right,right也是在content后面,我先让他向左移动200px,也就是margin-left: -200px此时效果

10.png

此时再让他相对自身右移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的大小,然后leftright的父容器又恰好是wrap,刚好直接排在container的右边,让left置左,让right向左移动即可

九、说说flexbox

问你弹性盒子就是问你弹性布局,弹性布局很容易被字节问到,弹性布局是现在最推荐的一种布局方式,因为太强大了

是什么

是一种布局方式,可以简便完整响应式的实现页面布局,容器默认存在两条轴,一个主轴,一个交叉轴,默认x轴为主轴,可以用flex-direction来修改主轴的方向

css的响应式指的是屏幕变小,容器也跟着变小

特征

  1. 可以控制子元素在主轴上的对齐方式:justify-content
  2. 可以控制子元素在交叉轴上的对齐方式:align-items
  3. 可以控制元素的缩放比例,排列方式:flex-grow, flex-shrink, order

应用场景

  1. 多栏布局
  2. 居中

十、css3新增了哪些属性

这个问题翻看前两年大家的面经还经常出现,现在少见了

尽管css3停留在这个版本很久了,但是有些新增的属性浏览器的兼容性依旧跟不上

  1. 选择器:属性选择器在css2是没有的,还有像是last-child这样的伪类选择器
  2. 盒子阴影box-shadow
  3. 裁剪:clip-path裁剪以及background-clip背景图裁剪
  4. 过度动画:transition
  5. 转换transform:,平移,缩放,旋转,倾斜
  6. 纯动画animation
  7. 颜色渐变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>

三个动画效果如下

2.gif

十二、说说回流重绘

这个问题也有可能放在js中聊,之前也单独出过文章讲过,详情见输入url到页面渲染后半段:回流,重绘,优化【一次性带你搞明白】 - 掘金 (juejin.cn)

是什么

回流:浏览器渲染页面之前需要对结构进行布局计算

重绘:将已经计算好布局的容器绘制出来

触发

触发回流:页面上有容器的几何属性发生变更

触发重绘:容器非几何属性变更,比如颜色等

所以回流一定重绘,但是重绘不一定回流

十三、什么是响应式?

是什么

跟随用户页面设备尺寸的变化,页面实现自动的适配

比如你逛掘金的商城页面,缩放页面的时候发现1000-1160宽是一个适配,1160以外又是一个适配

实现方案

  1. 弹性布局:适合做某个容器内的响应式,比如ulli,但是不方便做整个页面的响应式

    弹性容器默认就是让子元素在收缩放大时平均分配

  2. 百分比:常适用于页面外层大容器,同样不适合整个页面的响应式,一般适配都是pc端一个,平板一个,手机一个,百分比过于灵活不适合

    百分比继承父容器

  3. rem + 媒体查询 (可用于任何地方,一般pc端是rem + 媒体查询,移动端是rem + js)

    rem是参照根字体大小,css有媒体查询的语法,写法参考如下,min-widthmax-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>
    
  4. 直接媒体查询,不如第三个方法,这个代码量会很大

    一个区间写一个样式,代码量会很大

    <!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>
    
  5. 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>
    

十四、视差滚动效果如何实现

是什么

视差滚动是多层背景以不同的速度进行移动,实现视觉上的落差

比如这个效果

3.gif

实现

方法一: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>

效果如下

5.gif

方法二: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>

效果如下

6.gif

这个原理就是通过把视角位置安置在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>

效果如下

11.png

canvas画布是js部分,如果可以用canvas画就方便很多

十六、如何显示一个小于10px的文字

目前谷歌浏览器默认字体大小是16px,以前谷歌浏览器最小支持的字体像素就是10px,但是目前最新版本的谷歌浏览器可以直接设置任意大小像素的字体,包括10像素以下

所以你可以直接告诉面试官,新版本的谷歌浏览器是可以支持任意像素的文字的

那么其他浏览器怎么办

zoomtransform: 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>

最后

这些问题可能你都能回答出来,但是对于面试,一定是要尽量全部说出来,现在的环境都越来越卷了,别人回答得比你多你就输了,同时欢迎各位补充

另外有不懂之处欢迎在评论区留言,如果觉得文章对你学习有所帮助,还请”点赞+评论+收藏“一键三连,感谢支持!