“寒冬”三年经验前端面试总结(含头条、百度、饿了么、滴滴等)之CSS篇

20,348 阅读8分钟

前言

不论是寒冬还是暖冬,找工作之前都需要做好充足的准备,面试的时候才能做到游刃有余。此文是把我最近找工作准备的以及笔试面试中涉及到的手写题做一个总结。给自己,也给需要的同学。

CSS是前端必须要掌握的技能之一。一般面试也都会从CSS开始。所以CSS问题答的好坏会直接影响你在面试官心中的形象。

本文主要介绍面试中常会遇到的CSS问题及给出建议性的答案。


往期

  1. “寒冬”三年经验前端面试总结(含头条、百度、饿了么、滴滴等)
  2. “寒冬”三年经验前端面试总结(含头条、百度、饿了么、滴滴等)之手写题(一)
  3. “寒冬”三年经验前端面试总结(含头条、百度、饿了么、滴滴等)之手写题(二)
  4. “寒冬”三年经验前端面试总结(含头条、百度、饿了么、滴滴等)之手写题(promise篇)

盒模型

盒模型感觉是刚学前端的时候就会接触到的问题。元素都是按照盒模型的规则布局在页面中的。盒模型由 margin + border + padding + content 四个属性组成,分为两种:W3C的标准盒模型和IE盒模型。

W3C的标准盒模型

width = content,不包含 border + padding

IE盒模型

width = border + padding + content

相互转换

二者之间可以通过CSS3的 box-sizing 属性来转换。

box-sizing: content-box 是W3C盒模型

box-sizing: border-box 是IE盒模型

垂直居中的方法

垂直居中的方法,如果全写出来,有10多种。面试的时候一般都会说比较常用的几种。flexposition + transformposition + 负margin是最常见的三种情况。

<div class="outer">
    <div class="inner"></div>
</div>

方法一:flex

.outer{
    display: flex;
    justify-content: center;
    align-items: center
}

方法二: position + transform, inner宽高未知

.outer{
    position:relative;
}
.inner{
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%,-50%);
}

方法三:position + 负margin, inner宽高已知

.outer{
    position: relative;
}
.inner{
    width: 100px;
    height: 100px;
    position: absolute;
    left: 50%;
    top: 50%;
    margin-left: -50px;
    margin-top: -50px;
}

方法四:设置各个方向的距离都是0,再将margin设为auto,也可以实现,前提是inner宽高已知

.outer {
    position: relative;
}
.inner {
    width: 100px;
    height: 100px;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    margin: auto;
}

三栏布局

三栏布局是很常见的一种页面布局方式。左右固定,中间自适应。实现方式有很多种方法。

第一种:flex

<div class="container">
    <div class="left">left</div>
    <div class="main">main</div>
    <div class="right">right</div>
</div>
.container{
    display: flex;
}
.left{
    flex-basis:200px;
    background: green;
}
.main{
    flex: 1;
    background: red;
}
.right{
    flex-basis:200px;
    background: green;
}

第二种:position + margin

<div class="container">
    <div class="left">left</div>
    <div class="right">right</div>
    <div class="main">main</div>
</div>
body,html{
    padding: 0;
    margin: 0;
}
.left,.right{
    position: absolute;
    top: 0;
    background: red;
}
.left{
    left: 0;
    width: 200px;
}
.right{
    right: 0;
    width: 200px;
}
.main{
    margin: 0 200px ;
    background: green;
}

第三种:float + margin

<div class="container">
    <div class="left">left</div>
    <div class="right">right</div>
    <div class="main">main</div>
</div>
body,html{
    padding:0;
    margin: 0;
}
.left{
    float:left;
    width:200px;
    background:red;
}
.main{
    margin:0 200px;
    background: green;
}
.right{
    float:right;
    width:200px;
    background:red;
}

CSS权重计算方式

CSS基本选择器包含ID选择器、类选择器、标签选择器、通配符选择器。 正常情况下,一般都能答出!important > 行内样式 > ID选择器 > 类选择器 > 标签选择器 > 通配符选择器

但如果这几种选择器同时作用于一个元素时,该元素最后应用哪个样式呢?这就涉及到权重计算的问题。 关于权重计算,有两种不同的计算方式:一种是以二进制的规则计算,一种是以1,10,100,1000这种的计算方式。我更倾向于二进制的这种方式。

各选择器权值:

  • 内联样式,权值为1000
  • ID选择器,权值为0100
  • 类,伪类和属性选择器,权值为0010
  • 标签选择器和伪元素选择器,权值为0001
  • 通配符、子选择器、相邻选择器等,权值为0000
  • 继承的样式没有权值

比较方式:

如果层级相同,继续往后比较,如果层级不同,层级高的权重大,不论低层级有多少个选择器。

BFC

BFC的全称为 Block Formatting Context,也就是块级格式化上下文的意思。

以下方式都会创建BFC:

  • 根元素(html)
  • 浮动元素(元素的 float 不是 none)
  • 绝对定位元素(元素的 position 为 absolute 或 fixed)
  • 行内块元素(元素的 display 为 inline-block)
  • 表格单元格(元素的 display为 table-cell,HTML表格单元格默认为该值)
  • 表格标题(元素的 display 为 table-caption,HTML表格标题默认为该值)
  • 匿名表格单元格元素(元素的 display为 table、table-row、table-row-group、table-header-group、table-footer-group(分别是HTML table、row、tbody、thead、tfoot的默认属性)或 inline-table)
  • overflow 值不为 visible 的块元素
  • display 值为 flow-root 的元素
  • contain 值为 layout、content或 paint 的元素
  • 弹性元素(display为 flex 或 inline-flex元素的直接子元素)
  • 网格元素(display为 grid 或 inline-grid 元素的直接子元素)
  • 多列容器(元素的 column-count 或 column-width 不为 auto,包括 column-count 为 1) column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中(标准变更,Chrome bug)。

BFC布局规则:

  1. 内部的box会在垂直方向,一个接一个的放置。
  2. box垂直方向的距离有margin决定。属于同一个BFC的两个相邻box的margin会发生重叠。
  3. 每个元素的左外边距与包含块的左边界相接触,即使浮动元素也是如此。
  4. BFC的区域不会与float的元素区域重叠。
  5. 计算BFC的高度时,浮动子元素也参与计算。
  6. BFC就是页面上一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然。

BFC能解决的问题:

  1. 父元素塌陷
  2. 外边距重叠
  3. 清除浮动

清除浮动的方法

清除浮动主要是为了防止父元素塌陷。清除浮动的方法有很多,常用的是 clearfix 伪类。

方法一:clearfix

<div class="outer clearfix">
    <div class="inner">inner</div>
</div>
.outer{
    background: blue;
}
.inner{
    width: 100px;
    height: 100px;
    background: red;
    float: left;
}
.clearfix:after{
    content: "";
    display: block;
    height: 0;
    clear:both;
    visibility: hidden;
}

方法二:额外加一个div,clear:both

<div class="container">
    <div class="inner"></div>
    <div class="clear"></div>
</div>
.container{
    background: blue;
}
.inner {
    width: 100px;
    height: 100px;
    background: red;
    float: left;
}
.clear{
    clear:both;
}

方法三:触发父盒子BFC,overflow:hidden

<div class="outer">
    <div class="inner">inner</div>
</div>
.outer{
    background: blue;
    overflow: hidden;
}
.inner {
    width: 100px;
    height: 100px;
    background: red;
    float: left;
}

flex布局

flex 布局现在已经很普及的在用了。垂直居中用 flex 实现起来很简单。关于 flex 的属性也不是很多,父容器和子容器各6个,一共12个,比较好记。

下面是我复习flex属性时的一张导图。

position属性

position属性的重要性应该没啥可说的了。想必谁都回答的上来。

  • absolute 绝对定位,相对于 static 定位以外的第一个父元素进行定位。
  • relative 相对定位,相对于其自身正常位置进行定位。
  • fixed 固定定位,相对于浏览器窗口进行定位。
  • static 默认值。没有定位,元素出现在正常的流中。
  • inherit 规定应该从父元素继承 position 属性的值。

但是要注意一个问题,absolute 是相对于父元素的哪个属性进行定位的?通过下面的例子我们来看一看。

.container{
    position: relative;
    width: 30px;
    height: 30px;
    margin: 20px;
    border: 10px solid red;
    padding: 10px;
    background: blue;
}
.inner {
    position: absolute;
    width: 10px;
    height: 10px;
    top: 0;
    left: 0;
    background: pink;
}

从上图可以看出,是相对于 static 定位以外的第一个父元素的 padding 来定位的。

CSS3中新增了一个 position:sticky 属性,该属性的作用类似 position:relativeposition:fixed的结合。元素在跨越特定阈值前为相对定位,之后为固定定位。必须指定 top, right, bottomleft 四个阈值其中之一,才可使粘性定位生效。否则其行为与相对定位相同。但 sticky 尚在实验性阶段。

如何实现一个自适应的正方形

方法1:利用CSS3的vw单位

vw 会把视口的宽度平均分为100份

.square {
    width: 10vw;
    height: 10vw;
    background: red;
}

方法2:利用margin或者padding的百分比计算是参照父元素的width属性

.square {
    width: 10%;
    padding-bottom: 10%; 
    height: 0; // 防止内容撑开多余的高度
    background: red;
}

如何用css实现一个三角形

方法1: 利用border属性

利用盒模型的 border 属性上下左右边框交界处会呈现出平滑的斜线这个特点,通过设置不同的上下左右边框宽度或者颜色即可得到三角形或者梯形。

.triangle {
    height:0;
    width:0;
    border-color:red blue green pink;
    border-style:solid;
    border-width:30px;
}

如果想实现其中的任一个三角形,把其他方向上的 border-color 都设置成透明即可。

.triangle {
    height:0;
    width:0;
    border-color:red transparent transparent transparent;
    border-style:solid;
    border-width:30px;
}

方法二: 利用CSS3的clip-path属性

不了解 clip-path 属性的可以先看看 MDN 上的介绍:chip-path

.triangle {
    width: 30px;
    height: 30px;
    background: red;
    clip-path: polygon(0px 0px, 0px 30px, 30px 0px); // 将坐标(0,0),(0,30),(30,0)连成一个三角形
    transform: rotate(225deg); // 旋转225,变成下三角
}

写在最后

有错误之处还请小伙伴们及时指出,以免误人子弟。想看往期内容,翻到页面最上面有链接~