一份 CSS 清单,霸占你的收藏夹 。

1,560 阅读15分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

前言

看看文章,或许下一个offer就是你的。💕

CSS考察一般在基础一面,一面因CSS挂掉总是可惜的。

所以整理一份各厂CSS面试题清单(自身经历 + 网上各厂面经),帮助我和大家应对未来某个时间点的捉襟见肘。如果后续碰到新的题型,会持续更新。

每一题都是结合多篇文章做的一个总结,也都核实确认过,但百密总有一疏,如有问题,评论区call我。

题目

link 与 import 有何区别?

  1. link 属于HTML提供的标签,不仅可以加载css文件,还可以定义RSS、定义rel连接属性等。 import 是css提供的语法规则,仅支持加载css。
  2. 采用 link 方式,HTML会将 css 与 html 主体一同加载;采用 import 方式,会等整个 html 加载完之后再加载。
  3. link 无兼容问题;import css2.1提出,有兼容问题(IE5-)。
  4. JS 可控制 link 标签,但无法操控 import 。

注意:不建议使用import,因 import 的 CSS 文件只有在当前 CSS 文件被下载、解析完成之后,浏览器才会开始下载 import 的 CSS 文件,破坏了并行下载样式文件。

CSS预处理有了解过么?

CSS预处理器,你还是只会嵌套么?

px 如何转换 rem ? px 如何转换 vw ?

【自适应】px 转 rem,你还在手算么?

为什么要初始化 CSS 样式

保证不同浏览器页面保持一致,淘宝样式初始化如下。

body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, pre, form, fieldset, legend, button, input, textarea, th, td { margin:0; padding:0; }
body, button, input, select, textarea { font:12px/1.5tahoma, arial, \5b8b\4f53; }
h1, h2, h3, h4, h5, h6{ font-size:100%; }
address, cite, dfn, em, var { font-style:normal; }
code, kbd, pre, samp { font-family:couriernew, courier, monospace; }
small{ font-size:12px; }
ul, ol { list-style:none; }
a { text-decoration:none; }
a:hover { text-decoration:underline; }
sup { vertical-align:text-top; }
sub{ vertical-align:text-bottom; }
legend { color:#000; }
fieldset, img { border:0; }
button, input, select, textarea { font-size:100%; }
table { border-collapse:collapse; border-spacing:0; }


Normalize.css 和 Reset.css的区别

Reset.css 重置所有的浏览器自带样式,保持统一性。Normalize.css是保留有用的浏览器默认样式,重置了该重置的样式,更通用;同时还修复了一些bug。

CSS像素、设备像素、DPR、PPI

CSS像素:CSS逻辑中的虚拟像素,单位px,值相对于设备像素。
设备像素:屏幕物理像素点,出厂后就固定,单位pt。
DPR: 设备像素 / CSS 像素。
PPI: 每英寸的像素值,像素密度。

重排和重绘的区别 ?

重绘不一定导致重排但重排一定会导致重绘。

重排:重排也叫回流,当 DOM 的变化影响了元素的几何信息(位置 + 尺寸),浏览器需要重新计算元素的几何属性,将其放在界面的正确位置,这个过程叫重排。

引起重排的因素:

  1. 页面初始渲染(开销最大的重排)
  2. 添加/删除可见DOM元素
  3. 改变元素位置、尺寸、内容、字体大小。
  4. 改变窗口尺寸。
  5. 激活 CSS 伪类。
  6. 设置 style 属性。
  7. 查询属性:offset(Top|Left|Width|Height)、scroll(Top|Left|Width|Height)、client(Top|Left|Width|Height)、getComputedStyle()等。

Tips: 当操作 DOM 时,浏览器不是立马执行,而是将操作存储在一个队列中。当达到一定数量或经一定时间再统一去执行队列中的操作。但当查询属性(7)时会立马触发重排,强制刷新队列,因为不立马执行,得到的结果就是错误的。

重绘:当元素外观发生变化,但没有改变布局,重新把元素外观内容绘制出来,称重绘。

因素:

  1. color、border-style 、visibility 、background 等。

这里可能还会问 display 和 visibility ? display是触发重排的,visibility触发的是重绘。

flex:1 简写的含义?

这里列举所有 flex 简写的含义。

flex: initial === flex: 0 1 auto,默认写法。
flex:1 === flex:1 1 0%,适用等分布局。
flex:auto === flex: 1 1 auto,适用基于内容动态适配空间的布局。
flex:100px === flex: 1 1 100px,适用文本内容固定的元素。
flex:0 === flex: 0 1 0%,适合场景较少,可用于一些替换元素,如图片等。
flex:none === flex: 0 0 auto,适用于不换行的内容固定的小控件,如按钮。

参数一:代表 flex-grow ,若存在剩余空间,定义元素的放大占比。
参数二:代表 flex-shrink ,若空间不足,定义元素的缩小占比。
参数三:代表 flex-basis ,定义元素本身的大小。

图片自适应容器的方式

自适应不是让图片自动撑满容器,那样会导致图片失真。

第一种方式是通过 max-widthmax-height

img {
  max-width: 100%;
  max-height: 100%;
}

这种方式有个缺陷:当图片宽高都小于容器时,图片的长边和短边都无法填满容器。

第二种方式通过背景图的方式

div {
  width: 100%;
  height: 100%;
  background: url('') no-repeat center;
  background-size: contain;
}

第三种方式通过object-fit的方式

img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

grid 布局了解多少?

典型学了就忘🤦‍♂️,目前没有普及主要还是兼容性的问题。
张鑫旭
阮一峰

CSS盒模型

CSS盒模型有两种类型:标准模型IE盒子模型

IE盒子模型

  1. 元素的width、height不仅包含content,还包括padding、border。
  2. 盒子实际大小 = width

标准模型

  1. 元素的width、height只包含content,不包含padding、border。
  2. 盒子实际大小 = width + padding + border

IE盒子模型:box-sizing:border-box ;
标准盒子模型:box-sizing: content-box ;

BFC 了解么?还有IFC ?

BFC 全拼 Block Formatting Context称块级格式化上下文。

具有 BFC 特性的元素有如下几个特点:

  1. 是块级元素。
  2. 是一个隔离的独立容器,容器里的标签不会影响到外部标签。
  3. 垂直方向距离由 margin 决定,同一个 BFC 内两个相邻的标签外边距会发生重叠。
  4. 浮动元素参与高度的计算。

触发 BFC 因素:

  1. 根元素。
  2. 浮动元素,float的值不为 none。
  3. overflow 的值不是 visible 。
  4. display:inline-block / table-cell / table-caption元素。
  5. 绝对定位元素,position:absolute / fixed。
  6. 弹性布局 flex、网格布局 grid 的直接子元素。

能帮助解决如高度塌陷margin重叠等问题。

IFC 全拼 Inline Formatting Contexts称行内格式化上下文。 IFC 应用:

  1. 水平居中:当一个块要在环境中水平居中时,设置其为inline-block则会在外层产生IFC,通过text-align则可以使其水平居中。
  2. 垂直居中:创建一个IFC,用其中一个元素撑开父元素的高度,然后设置其vertical-align:middle,其他行内元素则可以在此父元素下垂直居中。

CSS有哪些可继承的属性 ?

可继承属性

  1. 字体系列属性:如font-size、font-family、font-weight等。
  2. 文本系列属性:如text-align、line-height、color、text-indent、word-spacing、letter-spacing等。
  3. 元素可见属性:visibility。
  4. 光标属性:cursor。
  5. 表格布局属性:caption-side、border-collapse、empty-cells。
  6. 列表属性:list-style-type、list-style-image、list-style-position。

不可继承属性。

  1. display
  2. 文本系列属性:vertical-align、text-decoration、text-shadow、white-space等。
  3. 盒子模型属性:width、height、margin、padding、border等。
  4. 背景属性:background及子属性background-color、background-image等。

浏览器是怎么解析CSS选择器

从右向左解析,避免大量不符合规则且冗余的 CSS 声明。

CSS权重和优先级?

优先级就是分配给指定的 CSS 声明的一个权重。

权重规则:

选择器权重
!important无敌
行内样式1000
ID选择器0100
类选择器、伪类、属性选择器0010
元素选择器0001
通配符、关系选择符(+、>、~)、否定伪类(:not)0000

当多个 CSS 声明优先级相等,应用最后那个声明。

伪类 和 伪元素 ?

伪类:用于向选择器添加特殊的效果。
用法::pseudo-class-name

伪类作用
:active鼠标按下未松开时激活的元素
:focus获取光标焦点的元素,主要是Input
:hover悬浮的元素
:link未被访问过的链接
:visited被访问过的链接
:first-child第一个子元素
:last-child最后一个子元素

伪元素:用于将特殊的效果添加到某些选择器。
用法:::pseudo-element-name

伪类作用
::before鼠标按下未松开时激活的元素
::after获取光标焦点的元素,主要是Input
::first-letter文本的首字母
::first-line文本首行

css3新增哪些新特性

新增了一些选择器。

选择器例子例子描述
element1 ~ element2p ~ ul选择前面有怕元素的每个ul元素
[attribute^=value]a[src^="https"]选择其src属性值以https开头的每个a属性
[attribute$=value]a[src$=".pdf"]选择其src属性值以pdf结尾的每个a属性
[attribute*=value]a[src*="abc"]选择其src属性值包含abc的每个a属性
:first-of-typep:first-of-type选择属于父元素下的首个p元素的每个p元素
:last-of-typep:last-of-type选择属于父元素下的最后一个p元素的每个p元素
:only-of-typep:only-of-type选择属于父元素的唯一p元素的每个p元素
:only-childp:only-child选择属于父元素的唯一子元素是p元素的每个p元素
:nth-child(n)p:nth-child(2)选择属于父元素的第二个子元素是p元素的每个p元素
:nth-last-child(n)p:nth-last-child(2)选择属于父元素的倒数二个子元素是p元素的每个p元素
:nth-of-type(n)p:nth-of-type(2)选择属于父元素的第二个p元素的每个p元素
:nth-last-of-type(n)p:nth-last-of-type(2)选择属于父元素的倒数二个p元素的每个p元素
:last-childp:last-child选择属于父元素最后一个子元素的每个p元素

新增了一些样式。

属性描述
border-radius圆角
box-shadow阴影
border-image图片绘制边框
background-clip背景从属性值开始显示(border-box/padding-box/content-box)
background-origin设置背景原点
background-size调整背景大小
word-wrap文字换行(break-word)
text-overflow文字溢出设置(clip/ellipsis)
text-shadow文字阴影
text-decoration文字装饰
transform元素平移、旋转、缩放、倾斜

颜色新增 RGBA和 HSLA 表述形式,字体新增自定义font-face、背景新增渐变,动画新增transition/animation,布局新增flex/grid,新增媒体查询。

position属性有哪些

static/relative/absolute/fixed/sticky

sticky 结合 relative 和 fixed,指当滚动到阈值前是relative,阈值后是fixed。

垂直居中布局

垂直居中布局主要根据元素是否定宽高而采取不同的措施。

<html>
  <head>
    <style>
      html, body {
        width: 100vw;
        height: 100vh;
      }
      .container {
        position: relative;
        width: 100%;
        height: 100%;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="box"></div>
    </div>
  </body>
</html>
  1. 绝对定位 + margin(仅限定宽高)
.box {
  width: 50px;
  height: 50px;
  margin: auto;
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  background: black;
}
  1. 绝对定位 + margin负值(仅限定宽高)
.box {
  width: 50px;
  height: 50px;
  margin-left: -25px;
  margin-top: -25px;
  position: absolute;
  left: 50%;
  top: 50%;
  background: black;
}
  1. 绝对定位 + transform (定宽高 和 不定宽高有内容均可)
.box {
  width: 50px;
  height: 50px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  background: black;
}
  1. flex (父元素必须有宽高,子元素宽高没有限制)
.container {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
}
.box {
  width: 50px;
  height: 50px;
  background: black;
}
  1. grid (父元素必须有宽高,子元素宽高没有限制)
.container {
  display: grid;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
}
.box {
  width: 50px;
  height: 50px;
  background: black;
}
  1. table + vertical-align (主要针对多行文本垂直居中)
<html>
  <head>
    <style>
      html, body {
        width: 100vw;
        height: 100vh;
      }
      .container {
        display: table;
        width: 100%;
        height: 100%;
      }
      .box {
        display: table-cell;
        text-align: center;
        vertical-align: middle;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="box">多行文本多行文本多行文本多行文本多行文本多行文本多行文本多行文本多行文本多行文</div>
    </div>
  </body>
</html>

清除浮动

包含浮动元素后添加空div或者添加伪元素,以伪元素为例,最常见就是解决高度塌陷问题。

div::after {
  display:block; // clear只在block元素上起作用
  content:""; 
  clear:both;  
  height:0; 
  overflow:hidden;
}

三栏布局

三栏布局通常是两端固定,中间自适应,这边列举几种方式。

  1. 浮动布局 原理:两侧盒子浮动,中间盒子得置于最后,左右位置随意。
    注意:左右两侧的宽度之和需要小于父容器 container 的宽度,否则右边盒子会被挤到第二行。
<html>
  <head>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      html, body {
        width: 100vw;
        height: 100vh;
      }
      .container {
        width: 100%;
        height: 100%;
        overflow: hidden;
      }
      .left {
        width: 200px;
        height: 100%;
        float: left;
        background: #7474BF;
      }
      .right {
        width: 120px;
        height: 100%;
        float: right;
        background: #348AC7;
      }
      .middle {
        height: 100%;
        background: #203A43;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="left"></div>
      <div class="right"></div>
      <div class="middle"></div>
    </div>
  </body>
</html>
  1. 绝对定位布局 原理:两侧盒子绝对定位,脱离文档流。
    注意:所有子元素也脱离文档流,可用性和有效性都比较差。
<html>
  <head>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      html, body {
        width: 100vw;
        height: 100vh;
      }
      .container {
        position: relative;
        width: 100%;
        height: 100%;
      }
      .left {
        position: absolute;
        top: 0;
        left: 0;
        width: 200px;
        height: 100%;
        background: #7474BF;
      }
      .right {
        position: absolute;
        top: 0;
        right: 0;
        width: 120px;
        height: 100%;
        background: #348AC7;
      }
      .middle {
        margin: 0 100px;
        height: 100%;
        background: #203A43;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="left"></div>
      <div class="right"></div>
      <div class="middle"></div>
    </div>
  </body>
</html>
  1. 弹性布局 原理:父元素设置 flex,中间盒子设置 flex:1。
    注意:兼容性问题,IE11+
<html>
  <head>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      html, body {
        width: 100vw;
        height: 100vh;
      }
      .container {
        display: flex;
        width: 100%;
        height: 100%;
      }
      .left {
        width: 200px;
        height: 100%;
        background: #7474BF;
      }
      .right {
        width: 120px;
        height: 100%;
        background: #348AC7;
      }
      .middle {
        flex: 1;
        height: 100%;
        background: #203A43;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="left"></div>
      <div class="middle"></div>
      <div class="right"></div>   
    </div>
  </body>
</html>
  1. 网格布局 原理: 父元素设置grid,通过grid-template-rows和grid-template-columns设置三个盒子。 注意:兼容性问题,IE10+
<html>
  <head>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      html, body {
        width: 100vw;
        height: 100vh;
      }
      .container {
        display: grid;
        width: 100%;
        height: 100%;
        grid-template-rows: 100%;
        grid-template-columns: 200px auto 120px;
      }
      .left {
        background: #7474BF;
      }
      .right {
        background: #348AC7;
      }
      .middle {
        background: #203A43;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="left"></div>
      <div class="middle"></div>
      <div class="right"></div>   
    </div>
  </body>
</html>
  1. 表格布局 原理: 设置父元素为table,设置table-layout:fixed。表示列宽自身宽度决定,而不是自动计算。所有的盒子设置display:table-cell设置为表格单元。左右设置固定宽度,中间设置width:100%填充剩下的宽度。 注意:扩展性较差,后续若布局有较大变动,更改地方较多。
<html>
  <head>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      html, body {
        width: 100vw;
        height: 100vh;
      }
      .container {
        display: table;
        width: 100%;
        height: 100%;
        table-layout: fixed;
      }
      .left {
        display: table-cell;
        width: 200px;
        background: #7474BF;
      }
      .right {
        display: table-cell;
        width: 120px;
        background: #348AC7;
      }
      .middle {
        display: table-cell;
        width: 100%;
        background: #203A43;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="left"></div>
      <div class="middle"></div>
      <div class="right"></div>   
    </div>
  </body>
</html>
  1. 圣杯布局 原理:父元素使用padding预留左右元素的位置,三个盒子均浮动,左侧盒子通过margin负值和left偏移去定位;右侧盒子通过margin负值和right偏移去定位。
    注意:浏览器放大或者变窄,圣杯将会破碎,当中间盒子宽小于左侧盒子就会发生布局混乱。
<html>
  <head>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      html, body {
        width: 100vw;
        height: 100vh;
      }
      .container {
        height: 100%;
        padding: 0 120px 0 200px;
      }
      .left {
        position: relative;
        float: left;
        width: 200px;
        height: 100%;
        margin-left: -100%;
        left: -200px;
        background: #7474BF;
      }
      .right {
        position: relative;
        float: left;
        margin-left: -120px; 
        width: 120px;
        height: 100%;
        right: -120px;
        background: #348AC7;
      }
      .middle {
        position: relative;
        float: left;
        width: 100%;
        height: 100%;
        background: #203A43;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="middle"></div>
      <div class="left"></div>
      <div class="right"></div>   
    </div>
  </body>
</html>
  1. 双飞翼布局 原理:在圣杯布局的基础上,舍去相对定位,增加一层dom包裹。
    注意: 多层dom结构,增加渲染树的生成的计算量。
<html>
  <head>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      html, body {
        width: 100vw;
        height: 100vh;
      }
      .container {
        height: 100%;

      }
      .left {
        float: left;
        width: 200px;
        height: 100%;
        margin-left: -100%;
        background: #7474BF;
      }
      .right {
        float: left;
        margin-left: -120px; 
        width: 120px;
        height: 100%;
        background: #348AC7;
      }
      .middle {
        float: left;
        width: 100%;
        background: #203A43;
      }
      .main {
        margin: 0 120px 0 200px;
        height: 100%;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="middle">
        <div class="main"></div>
      </div>
      <div class="left"></div>
      <div class="right"></div>   
    </div>
  </body>
</html>

CSS 画一个三角形

主要思路就是高宽设为0,border3个边设置transparent,根据自己需求设置三角指向。

.border {
  width: 0;
  height: 0;
  border-top: #4285f4 solid;
  border-right: transparent solid; 
  border-left: transparent solid;
  border-bottom: transparent solid;
  border-width: 85px;
}

如何实现文本溢出省略

单行文本溢出

div {
  width: 100px;
  height: 40px;
  line-height: 40px;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
}

多行文本溢出

div {
  width: 100px;
  -webkit-line-clamp: 2;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}

CSS 如何实现视差滚动效果

视差滚动:指多层背景以不同速度,形成立体的运动效果。

CSS可以通过两种方式来实现:background-attachment: fixedtransform: translate3d来实现

background-attachment

作用是设置背景图像是否固定或者随着页面的其余部分滚动,值有fixedscrolllocal

  1. fixed 表示背景相对于视口固定。即使一个元素拥有滚动机制,背景也不会随着元素内容滚动。
  2. scroll 表示背景相对于元素本身固定,而不是随着它的内容滚动。
  3. local 表示背景相对于元素的内容固定。如果一个元素拥有滚动机制,背景将会随着元素的内容滚动。

背景图片使用background-attachment: fixed就可产生背景固定,元素移动的视觉效果。

transform: translate3d

原理

  1. 容器设置上 transform-style: preserve-3d 和 perspective: 1px,那么处于这个容器的子元素就将位于3D空间中。
  2. 子元素设置不同translateZ的值,使元素距离屏幕的值不一样,从而上下滚动translateY的也是不一样的。
<html>
  <head>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      html {
        height: 100vh;
        overflow: hidden; // 包裹3D元素内容设置hidden,禁止滚动。
      }
      body {
        perspective: 1px;
        transform-style: preserve-3d; 
        height: 100%;
        overflow-y: scroll;
        overflow-x: hidden;
      }
      .container {
        width: 100vw;
        height:200vh; // 促使body滚动
      }
      .one {
        width: 100px;
        height: 100px;
        transform: translateZ(-1px);
        background: #7474BF;
      }
      .two {
        width: 100px;
        height: 100px;
        transform: translateZ(-2px);
        background: #348AC7;
      }
      .three {
        width: 100px;
        height: 100px;
        transform: translateZ(-3px);
        background: #203A43;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="one">one</div>
      <div class="two">two</div>
      <div class="three">three</div>   
    </div>
  </body>
</html>

requestAnimationFrame

requestAnimation 与 setTimeout 相似,不同之处在于,setTimeout是指定毫秒后被调用,且由于事件循环,真正执行总是要比设定的时间要晚,从而导致实现的动画不够流畅。requestAnimationFrame则是依赖于屏幕刷新频率。目前大部分屏幕刷新频率为60HZ,意味着 1000 / 60 = 16.67ms 刷新一次,动画实现相对 setTimeout 更加平滑、流畅,同时针对不可见的元素,requestAnimationFrame也会暂停,有效节省了CPU开销。

Chrome如何实现小于12px的文字方式

  1. 使用 zoom,有兼容性问题,可在can i use查询。
  2. 使用 transform: scale。该属性对块级或行内块元素生效。

CSS提升性能的方法?

  1. 若大部分CSS文件提交较小,可考虑合并CSS文件。
  2. 拆分公共CSS文件。
  3. 提取首屏关键CSS(14.6kB限制)进行内联,而非外部引入。
  4. 首屏不需要的CSS进行异步加载。
  5. 打包工具压缩样式文件。
  6. 不使用@import引入css,因会破坏并行下载,导致并行变同步,增加耗时。如某css文件import另一个css文件必须等待当前css文件解析执行完后,才可加载另一个css文件。
  7. 雪碧图,压缩图片,icon可转base64。
  8. 减少并不必要的重排、重绘操作。

响应式设计

响应式设计即页面可根据用户行为或设备进行响应和调整。

处理移动端需添加meta头

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no”>

实现响应式布局就是结合媒体查询 + 百分比 + rem + vw/vh。