前端大厂面试秘籍——CSS篇

145 阅读10分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天 ,点击查看活动详情

1.介绍下什么是BFC

BFC(Block Format Context)块级格式化上下文,是一个独立的渲染区域,让处于 BFC 内部的元素与外部的元素相互隔离,使内外元素的定位不会相互影响。

  • 创建规则/触发条件
    • 根元素
    • 浮动元素( float 不取值为 none )
    • 绝对定位元素( position 取值为 absolute 或 fixed )
    • display 取值为 inline-block 、 table-cell 、 table-caption 、 flex 、inline-flex 之⼀的元素
    • overflow 不取值为 visible 的元素
  • 作用:清除浮动、防止同一 BFC 容器中的相邻元素间的外边距重叠问题(防止maigin合并)。
  • 如何创建无副作用的:它可以创建无副作用的 BFC。在父级块中使用 display: flow-root 可以创建新的 BFC。
  • 规则:
    • 属于同一个 BFC 的两个相邻 Box 垂直排列
    • 属于同一个 BFC 的两个相邻 Box 的 margin 会发生重叠
    • BFC 中子元素的 margin box 的左边, 与包含块 (BFC) border box的左边相接触 (子元素 absolute 除外)
    • BFC 的区域不会与 float 的元素区域重叠
    • 计算 BFC 的高度时,浮动子元素也参与计算
    • 文字层不会被浮动层覆盖,环绕于周围

2.简述 CSS 盒模型

  • 盒子由 margin、border、padding、content 组成;
  • 标准盒模型:box-sizing: content-box; width=content
  • IE 盒模型:box-sizing: border-box; width=padding+border+content

3.居中布局

  • 水平居中
    • 行内元素: text-align: center
    • 块级元素: margin: 0 auto
    • absolute + transform
    • flex + justify-content: center
  • 垂直居中
    • line-height: height
    • absolute + transform
    • flex + align-items: center
    • table
  • 水平垂直居中
    • 绝对定位 +上左50%, margin上左负宽高一半,需知盒子宽高
    • 绝对定位 +calc,需知盒子宽高
    • 绝对定位 + transform,不需确定盒子宽高
    • 绝对定位 +上下左右为零, margin: auto ,不需确定盒子宽高
    • display:flex + 水平对齐+纵轴对齐,不需确定盒子宽高
    • display: table-cell + 元素垂直居中对齐

具体代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <!--    div水平垂直居中-->
    <meta charset="UTF-8">
    <title>div水平垂直居中</title>
    <link rel="stylesheet" href="public.css/">
    <style>
        .father {
            background-color: rosybrown;
            height: 100%;
            width: 100%;
        }
        .children {
            width: 300px;
            height: 300px;
            background-color: beige;
        }
        /* 第一种:绝对定位 + margin ,需已知宽高
        缺点:需要知道盒子的宽高
        */
        /*
        .children {
            position: absolute;
            top: 50%;
            left: 50%;
            margin-top: -150px;
            margin-left: -150px;
        }
        */

        /* 第二种:绝对定位方法:不确定当前div的宽度和高度,采用 transform: translate(-50%,-50%);
        当前div的父级添加相对定位(position: relative;)
        优点:不需要盒子的确切宽高,也不要求盒子一定要有宽高
        缺陷:兼容性要求(IE8不支持)
        */
        /*
        .children {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
        }
         */

        /* 第三种:absolute + calc*/
        /*
        .children {
            position: absolute;
            top: calc(50% - 150px);
            left: calc(50% - 150px);
        }
         */

        /*    第四种:利用margin和绝对定位,不确定当前div的宽度和高度
        优点:简单
        缺点:需要固定宽高,IE7及之前版本不支持,无足够空间时,.盒子会被截断,但是不会有滚动条出现
        */
        /*
        .children {
            position: absolute;
            left: 0;
            right: 0;
            top: 0;
            bottom: 0;
            margin: auto;
        }
        */
        /*    第五种:display:flex
        优点:简单,只需给父级盒子加三个样式就可以 css3特性
        */
        /*
        .father {
            display: flex;
            justify-content: center;//水平对齐
            align-items: center;//纵轴对齐
        }
         */

        /*    第六种:display: table-cell
        缺点:父级盒子需固定宽高
        */
        /*
        .father {
            width: 500px;
            height: 500px;
            display: table-cell;
            vertical-align: middle;
        }

        .children {
            margin: auto;
        }
         */

        /*    第七种:display: grid
               缺点:css新出的网格布局 ,兼容性不太好。
        */

        /*
        .father {
            display: grid;
        }

        .children {
            align-self: center;
            justify-self: center;
        }
        */
        /*    总结:
        PC端有兼容性要求,宽高固定,推荐absolute + 负margin
        PC端有兼容要求,宽高不固定,推荐css-table
        PC端无兼容性要求,推荐flex
        移动端推荐使用flex
        水平垂直居中元素宽高固定:
        1.absolute + 负margin
        2.absolute + margin auto
        3.absolute + calc
        水平垂直居中元素宽高不固定:
        1. absolute + transform
        2. display: table-cell
        3. display: flex;
        4. display: grid;
        */
        /*    如果是多个元素水平居中的话建议用:display:flex、display: grid
        可参考:https://www.cnblogs.com/qianxiaox/p/14973963.html
        */
    </style>
</head>
<body>
<div class="father">
    <div class="children"></div>
</div>
</body>
</html>

4.实现两栏布局(左侧固定 + 右侧自适应布局)

现在有以下 DOM 结构:

<div class="outer">
  <div class="left">左侧</div>
  <div class="right">右侧</div>
</div>

公用css

.outer {
  height: 100px;
}
.left {
  width: 200px;
  height: 100%;
  background: lightcoral;
}
.right {
  height: 100%;
  background: lightseagreen;
}
  • 方案一:利用浮动,左边元素宽度固定 ,设置向左浮动。将右边元素的 margin-left 设为固定宽度 。注意,因为右边元素的 width 默认为 auto ,所以会自动撑满父元素。
      .left {
          float: left;
      }
      .right {
          margin-left: 200px;
          height: 100%;
          background: lightseagreen;
      }
    
  • 方案二:同样利用浮动,左边元素宽度固定 ,设置向左浮动。右侧元素设置 overflow: hidden; 这样右边就触发了 BFC ,BFC 的区域不会与浮动元素发生重叠,所以两侧就不会发生重叠。
    .left {
        float: left;
    }
    .right {
        overflow: auto;
    }
    
  • 方案三:利用 flex 布局,左边元素固定宽度,右边的元素设置 flex: 1 。
    .outer {
        display: flex;
    }
    .right {
        flex: 1;
    }
    
  • 方案四:利用绝对定位,父级元素设为相对定位。左边元素 absolute 定位,宽度固定。右边元素的 margin-left 的值设为左边元素的宽度值。
    .outer {
        position: relative;
    }
    .left {
        position: absolute;
    }
    .right {
        margin-left: 200px;
    }
    
  • 方案五:利用绝对定位,父级元素设为相对定位。左边元素宽度固定,右边元素 absolute 定位, left 为宽度大小,其余方向定位为 0 。
    .outer {
        position: relative;
    
    }
    .right {
        position: absolute;
        left: 200px;
        top: 0;
        right: 0;
        bottom: 0;
    }
    

5.实现圣杯布局和双飞翼布局(经典三分栏布局)

圣杯布局和双飞翼布局的目的:

  • 三栏布局,中间一栏最先加载和渲染(内容最重要,这就是为什么还需要了解这种布局的原因)。
  • 两侧内容固定,中间内容随着宽度自适应。
  • 一般用于 PC 网页。 圣杯布局和双飞翼布局的技术总结:
  • 使用 float 布局。
  • 两侧使用 margin 负值,以便和中间内容横向重叠。
  • 防止中间内容被两侧覆盖,圣杯布局用 padding ,双飞翼布局用 margin。

参考:做了一份前端面试复习计划,保熟~

1) 圣杯布局

  .container {
      padding-left: 200px;
      padding-right: 150px;
      overflow: auto;
  }
  #container p {
      float: left;
  }
  .center {
      width: 100%;
      background-color: lightcoral;
  }
  .left {
      width: 200px;
      position: relative;
      left: -200px;
      margin-left: -100%;
      background-color: lightcyan;
  }
  .right {
      width: 150px;
      margin-right: -150px;
      background-color: lightgreen;
  }
  .clearfix:after {
      content: "";
      display: table;
      clear: both;
  }
  <div id="container" class="clearfix">
      <p class="center">我是中间</p>
      <p class="left">我是左边</p>
      <p class="right">我是右边</p>
  </div>

2) 双飞翼布局

  .float {
      float: left;
  }
  #main {
      width: 100%;
      height: 200px;
      background-color: lightpink;
  }
  #main-wrap {
      margin: 0 190px 0 190px;
  }
  #left {
      width: 190px;
      height: 200px;
      background-color: lightsalmon;
      margin-left: -100%;
  }
  #right {
      width: 190px;
      height: 200px;
      background-color: lightskyblue;
      margin-left: -190px;
  }
  <div id="main" class="float">
      <div id="main-wrap">main</div>
  </div>
  <div id="left" class="float">left</div>
  <div id="right" class="float">right</div>

注意:上述代码中 margin-left: -100% 相对的是父元素的 content 宽度,即不包含 paddig 、 border 的宽度。

总结:其实以上问题需要掌握 margin 负值问题 即可很好理解。

3) flex方式

  .box {
      display: flex;
      justify-content: center;
      height: 200px;
  }
  .left {
      width: 200px;
      background-color: red;
      height: 100%;
  }
  .content {
      background-color: yellow;
      flex: 1;
  }
  .right {
      width: 200px;
      background-color: green;
  }
  <div class="box">
      <div class="left"></div>
      <div class="content"></div>
      <div class="right"></div>
  </div>

4)绝对定位方式

  .box {
      position: relative;
      height: 200px;
  }
  .left {
      width: 200px;
      background-color: red;
      left: 0;
      height: 100%;
      position: absolute;
  }
  .content {
      background-color: yellow;
      left: 200px;
      right: 200px;
      height: 100%;
      position: absolute;
  }
  .right {
      width: 200px;
      background-color: green;
      right: 0;
      height: 100%;
      position: absolute;
  }
  <div class="box">
      <div class="left"></div>
      <div class="content"></div>
      <div class="right"></div>
  </div>

5)浮动方式

  .box {
      height: 200px;
  }
  .left {
      width: 200px;
      background-color: red;
      height: 100%;
      float: left;
  }
  .content {
      background-color: yellow;
      height: 100%;
  }
  .right {
      width: 200px;
      background-color: green;
      height: 100%;
      float: right;
  }
  <div class="box">
      <div class="left"></div>
      <div class="right"></div>
      <div class="content"></div>
  </div>

6.清除浮动的方式有哪些?请说出各自的优点

  • 给父元素单独定义高度
    • 优点:快速简单,代码少
    • 缺点:无法进行响应式布局
  • 父级定义 overflow:hidden;
    • 优点:简单快速、代码少,兼容性较高
    • 缺点:超出部分被隐藏,布局时要注意
  • 在浮动元素后面加一个空标签,clear:both;
    • 优点:简单快速、代码少,兼容性较高
    • 缺点:增加空标签,不利于页面优化

7.介绍下重绘和重排/回流(Repaint &Reflow),如何避免?

  • 重绘:当 render tree 中的一些元素需要更新属性,而这些属性只是影响元素的外观,不会影响布局,就叫重绘
    • 触发重绘:color、background 相关属性:background-color、background-image等
  • 重排/回流:为元素的规模尺寸,布局,隐藏等改变而需要重新构建,这就叫回流
    • 触发重排/回流:页面的首次渲染 、浏览器的窗口大小发生变化 、元素的内容发生变化 、元素的尺寸或者位置发生变化、 元素的字体大小发生变化、 激活 CSS 伪类、 查询某些属性或者调用某些方法 、添加或者删除可见的 DOM 元素
  • 减少重绘和重排的⽅法:
    • 不在布局信息改变时做 DOM 查询
    • 避免逐个修改节点样式,尽量一次性修改
    • 对于多次重排的元素,如动画,使⽤绝对定位脱离⽂档流,让他的改变不影响到其他元素
    • 提升为合成层 将元素提升为合成层有以下优点:
      • 合成层的位图,会交由 GPU 合成,比 CPU 处理要快
      • 当需要 repaint 时,只需要 repaint 本身,不会影响到其他的层
      • 对于 transform 和 opacity 效果,不会触发 layout 和 paint
      • 提升合成层的最好方式是使用 CSS 的 will-change 属性:
       #target {
          will-change: transform;
      }
      

8.Flex 布局原理

就是通过给父盒子添加 flex 属性,来控制子盒子的位置和排列方式 详解:Flex 布局教程:语法篇

9.Px,rem,em 的区别

  • Px,绝对长度单位,像素 px 是相对于显示器屏幕分辨率来说的
  • Px是固定像素,无法因页面大小的改变而改变
  • em和rem相对于px更灵活,他们是相对长度单位,更适用于响应式布局
  • em 相对长度单位,相对于当前对象内文本的字体尺寸em 的值并不是固定的
  • em 会继承父级元素的字体大小(参考物是父元素的font-size)em 中所有的字体都是相对于父元素的大小决定的,所以就会存在一个问题,就是每一层父元素都必须有它的数值
  • rem 相对于 html 根元素的 font-size 1em=1rem=16px 在 body 中加入 font-size:62.5%这样直接就是原来的 px 数值除以 10 加上 em 就可以

10.选择器优先级

  • !important > 行内样式 > #id > .class > tag > * > 继承 > 默认
  • 选择器 从右往左 解析

11.link 与 @import 的区别

  • link功能较多,可以定义 RSS,定义 Rel 等作用,而@import只能用于加载 css
  • 当解析到link时,页面会同步加载所引的 css,而@import所引用的 css 会等到页面加载完才被加载
  • @import需要 IE5 以上才能使用
  • link可以使用 js 动态引入,@import不行

12.position的值有哪些?relative和absolute定位原点是

  • relative :相对定位,不脱离文档流,相对于其正常位置进⾏定位
  • absolute :绝对定位,脱离文档流,相对于 static 定位以外的第⼀个⽗元素进⾏定位
  • fixed :绝对定位素,脱离文档流,相对于浏览器窗⼝进⾏定位
  • static 默认值。没有定位,元素出现在正常的流中
  • inherit 规定从⽗元素继承 position 属性的值

13.分析比较 opacity: 0、visibility: hidden、display: none 优劣和适用场景

  • display: none - 不占空间,不能点击,会引起回流,子元素不影响
  • visibility: hidden - 占据空间,不能点击,引起重绘,子元素可设置visible进行显示
  • opacity: 0 - 占据空间,可以点击,引起重绘,子元素不影响

14.用纯 CSS 创建一个三角形

 #demo {
    width: 0;
    height: 0;
    border:6px solid;
    border-color: transparent transparent red transparent;
}

15.为什么要使用CSS预处理器,预处理器有哪些优缺点?

  • 因为语法不够强大,比如无法嵌套书写,导致模块化开发中需要书写很多重复的选择器;没有变量和合理的样式复用机制,使得逻辑上相关的属性值必须以字面量的形式重复输出,导致难以维护。
  • 优点:可以提供CSS 缺失的样式层复用机制、减少冗余代码,提高样式代码的可维护性,大大提高了开发效率。
  • 缺点:CSS的好处在于简便、随时随地被使用和调试。预编译CSS步骤的加入,让我们开发工作流中多了一个环节,调试也变得麻烦。更大的问题在于,预编译很容易造成后代选择器的滥用。

16.CSS预处理sass less是什么?

  • sass 和 less 都是 css 预处理器,是 css 上的一种抽象层,是一种特殊的语法,最终会编译成 css;
  • 都是一种动态样式语言,给css 赋予了动态语言的特性,比如:变量,继承,嵌套。Less 既可以在客户端运行,在可以在服务端运行(需要借助 node);
  • 它们的后缀名不同、语法不同、Sass功能较Less强大 (sass有变量和作用域、sass有函数的概念等) sass
    @width100px;
    .box{
      width:@width;
    }
    
    less
    $width:100px;
    .box{
      width:$width;
    }
    
  • 常用功能
    • 嵌套
    • 变量
    • 循环语句
    • 条件语句
    • 自动前缀
    • 单位转换
    • mixin复用

17.CSS有哪些常用选择器

  • 派生选择器(用 HTML 标签申明)
  • id 选择器(用 DOM 的 ID 申明)
  • 类选择器(用一个样式类名申明
  • 后代选择器(利用空格间隔,比如 div .a{ })
  • 群组选择器(利用逗号间隔,比如 p,div,#a{ })

18.⾏内元素有哪些?块级元素有哪些? 空(void)元素有那些?⾏内元素和块级元素有什么区别?

  • ⾏内元素有: a b span img input select strong
  • 块级元素有: div ul ol li dl dt dd h1 h2 h3 h4… p
  • 空元素: <br> <hr> <img> <input> <link> <meta>
  • ⾏内元素不可以设置宽⾼,不独占⼀⾏
  • 块级元素可以设置宽⾼,独占⼀⾏