2023前端面试系列-- CSS 篇

135 阅读18分钟

介绍下 BFC 及其应用

当面试官问到BFC相关的问题时,可以参考以下回答范例:

1. 什么是BFC:

BFC指的是块级格式化上下文,是CSS中的一种渲染模式。BFC可以理解为一个独立的渲染区域,它决定了元素如何排布和交互。BFC的主要作用是解决页面布局中的一些常见问题,比如浮动、margin重叠等。

2. BFC的触发条件:

BFC可以通过多种方式来触发,包括以下几个条件:

根元素(即html元素); 浮动元素(float属性不为none); 绝对定位元素(position属性为absolute或fixed); display属性为inline-block、table-cell、table-caption、flex、grid、inline-flex、inline-grid等; overflow属性不为visible。 BFC的特性:

3. BFC具有以下几个特性:

内部的盒子会在垂直方向上一个接一个地排列,不会发生重叠; 盒子计算高度时会考虑到浮动元素的高度; BFC区域不会与浮动元素重叠; BFC可以包含浮动元素,防止浮动元素跑出BFC; BFC可以防止margin重叠。

4. BFC的应用:

BFC有很多应用场景,以下是其中的一些:

清除浮动:通过给浮动元素的父元素创建BFC,可以清除浮动对其他元素的影响,避免浮动元素跑到父元素外面或者覆盖其他元素; 防止margin重叠:当两个相邻的元素都属于同一个BFC时,它们之间的margin会发生重叠,通过创建BFC可以避免margin重叠的问题; 自适应两栏布局:通过给容器创建BFC,可以实现自适应的两栏布局,其中一栏浮动,另一栏被包裹在BFC中,这样可以避免浮动元素覆盖其他元素; 实现垂直居中:通过给容器创建BFC,可以实现垂直居中,具体方法是将容器的display属性设置为table-cell或者使用flexbox布局。

5. 如何创建BFC:

可以使用以下方法来创建BFC:

给容器元素设置overflow属性,值不为visible; 给容器元素设置float、position属性; 给容器元素设置display属性为inline-block、table-cell、table-caption、flex、grid、inline-flex、inline-grid等。

6. BFC的兼容性问题:

虽然BFC是CSS中一个重要的概念,但是在一些老的浏览器中不支持BFC,可能会导致一些兼容性问题。在这种情况下,可以考虑使用一些hack技巧来实现类似BFC的效果,比如使用清除浮动的技巧、使用inline-block来实现两栏布局等。

总之,了解BFC的概念、特性和应用场景是CSS开发者的基本素养之一,能够灵活运用BFC可以有效解决布局问题,提高页面的兼容性和可维护性。

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

📢 参考回答:

  • 结构: display:none: 会让元素完全从渲染树中消失,渲染的时候不占据任何空间, 不能点击, visibility: hidden:不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,不能点击 opacity: 0: 不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,可以点击
  • 继承: display: none和opacity: 0:是非继承属性,子孙节点消失由于元素从渲染树消失造成,通过修改子孙节点属性无法显示。 visibility: hidden:是继承属性,子孙节点消失由于继承了hidden,通过设置visibility: visible;可以让子孙节点显式。
  • 性能: displaynone : 修改元素会造成文档回流,读屏器不会读取display: none元素内容,性能消耗较大 visibility:hidden: 修改元素只会造成本元素的重绘,性能消耗较少读屏器读取visibility: hidden元素内容 opacity: 0 : 修改元素会造成重绘,性能消耗较少
  1. display: none (不占空间,不能点击)(场景,显示出原来这里不存在的结构)
  2. visibility: hidden(占据空间,不能点击)(场景:显示不会导致页面结构发生变动,不会撑开)
  3. opacity: 0(占据空间,可以点击)(场景:可以跟transition搭配)

三、居中为什么要使用 transform(为什么不使用 marginLeft/Top)(阿里)

📢 参考回答:

transform 属于合成属性(composite property),对合成属性进行 transition/animation 动画将会创建一个合成层(composite layer),这使得被动画元素在一个独立的层中进行动画。通常情况下,浏览器会将一个层的内容先绘制进一个位图中,然后再作为纹理(texture)上传到 GPU,只要该层的内容不发生改变,就没必要进行重绘(repaint),浏览器会通过重新复合(recomposite)来形成一个新的帧。

top/left属于布局属性,该属性的变化会导致重排(reflow/relayout),所谓重排即指对这些节点以及受这些节点影响的其它节点,进行CSS计算->布局->重绘过程,浏览器需要为整个层进行重绘并重新上传到 GPU,造成了极大的性能开销。

回答二:

在Web开发中,居中元素是一个非常常见的需求。虽然可以使用多种方式来实现元素的居中,但是使用CSS的transform属性是一种比较优秀的选择。原因如下:

  1. 相对定位 :使用margin-left和margin-top来实现元素的居中,通常需要将元素设置为相对定位。这样做的问题是,元素本身的位置并没有改变,只是通过margin调整了元素周围的空间。相对定位会占据原来的位置,可能会导致一些布局问题。而使用transform属性,可以实现元素的相对定位,同时不会占据原来的位置。这意味着元素的位置信息不会被改变,从而避免了一些潜在的布局问题。

  2. 性能优化: 使用margin调整元素的位置,可能会导致浏览器进行重排和重绘。这些操作是比较消耗性能的,尤其是在频繁调整元素位置的情况下。而使用transform属性,浏览器会使用GPU来执行变换操作。这样可以提高性能,特别是在需要频繁调整元素位置的情况下。

  3. 可扩展性: 使用transform属性可以实现更多的变换效果,比如旋转、缩放等。而使用margin进行元素居中则无法实现这些效果。因此,使用transform属性可以为后续的UI设计提供更多的扩展性和灵活性。 综上所述,使用CSS的transform属性来实现元素的居中是一种比较优秀的选择,它可以提高性能、避免一些布局问题,并且具有更高的可扩展性。

四、介绍下粘性布局(sticky)(网易)

📢 参考回答:

position 中的 sticky 值是 CSS3 新增的,设置了 sticky 值后,在屏幕范围(viewport)时该元素的位置并不受到定位影响(设置是top、left等属性无效),当该元素的位置将要移出偏移范围时,定位又会变成fixed,根据设置的left、top等属性成固定位置的效果。

sticky 属性值有以下几个特点:

  • 该元素并不脱离文档流,仍然保留元素原本在文档流中的位置。
  • 当元素在容器中被滚动超过指定的偏移值时,元素在容器内固定在指定位置。亦即如果你设置了top: 50px,那么在sticky元素到达距离相对定位的元素顶部50px的位置时固定,不再向上移动。
  • 元素固定的相对偏移是相对于离它最近的具有滚动框的祖先元素,如果祖先元素都不可以滚动,那么是相对于viewport来计算元素的偏移量

五、说出 space-betweenspace-around 的区别?(携程)

📢 参考回答:

这个是 flex 布局的内容,其实就是一个边距的区别,按水平布局来说,space-between是两端对齐,在左右两侧没有边距,而space-around是每个 子项目左右方向的 margin 相等,所以两个item中间的间距会比较大

  • space-between 会让第一个Flex项目的盒子起始边缘与Flex容器主轴起点相稳合,最后一个Flex项目的盒子结束边缘与Flex容器主轴终点相稳合,其它相邻Flex项目之间间距相等。当Flex容器中只有一个Flex项目时,其表现行为和 flex-start 等同

  • space-around 会让第一个Flex项目的盒子起始边缘与Flex容器主轴起点间距和最后一个Flex项目的盒子结束边缘与Flex容器主轴终点间距相等,并且等于其他相邻两个Flex项目之间间距的一半。当Flex容器中只有一个Flex项目时,其表现行为和 center 等同

image.png

六、 CSS3 中 transition 和 animation 的属性分别有哪些(哔哩哔哩)

transition 过渡动画:

  • transition-property:指定过渡的 CSS 属性
  • transition-duration:指定过渡所需的完成时间
  • transition-timing-function:指定过渡函数
  • transition-delay:指定过渡的延迟时间
.box {
  width: 100px;
  height: 100px;
  background-color: red;
  transition-property: width;
  transition-duration: 2s;
  transition-timing-function: ease-in-out;
  transition-delay: 1s;
}

.box:hover {
  width: 200px;
}

animation 关键帧动画:

  • animation-name:指定动画的名称。
  • animation-duration:指定动画的持续时间。
  • animation-timing-function:指定动画的时间函数,可以用来控制动画效果的速度变化。
  • animation-delay:指定动画的延迟时间。
  • animation-iteration-count:指定动画的播放次数,可以设置为无限循环。
  • animation-direction:指定动画的播放方向,可以是正向播放、反向播放或交替播放。
  • animation-fill-mode:指定动画的填充模式,可以是在动画前后保持样式、在动画结束时回到起始状态等。
.box {
  width: 100px;
  height: 100px;
  background-color: red;
  animation-name: myanimation;
  animation-duration: 2s;
  animation-timing-function: ease-in-out;
  animation-delay: 1s;
  animation-iteration-count: infinite;
  animation-direction: alternate;
  animation-fill-mode: backwards;
}

@keyframes myanimation {
  0% {
    width: 100px;
  }
  50% {
    width: 200px;
  }
  100% {
    width: 100px;
  }
}

七、讲一下png8、png16、png32的区别,并简单讲讲 png 的压缩原理

📢 参考回答:

PNG图片主要有三个类型,分别为 PNG 8/ PNG 24 / PNG 32。

  • PNG 8:PNG 8中的8,其实指的是8bits,相当于用2^8(2的8次方)大小来存储一张图片的颜色种类,2^8等于256,也就是说PNG 8能存储256种颜色,一张图片如果颜色种类很少,将它设置成PNG 8得图片类型是非常适合的。
  • PNG 24:PNG 24中的24,相当于3乘以8 等于 24,就是用三个8bits分别去表示 R(红)、G(绿)、B(蓝)。R(0-255),G(0-255),B(0-255),可以表达256乘以256乘以256=16777216种颜色的图片,这样PNG 24就能比PNG 8表示色彩更丰富的图片。但是所占用的空间相对就更大了。
  • PNG 32:PNG 32中的32,相当于PNG 24 加上 8bits的透明颜色通道,就相当于R(红)、G(绿)、B(蓝)、A(透明)。R(0255),G(0255),B(0255),A(0255)。比PNG 24多了一个A(透明),也就是说PNG 32能表示跟PNG 24一样多的色彩,并且还支持256种透明的颜色,能表示更加丰富的图片颜色类型。

PNG图片的压缩,分两个阶段:

  • 预解析(Prediction):这个阶段就是对png图片进行一个预处理,处理后让它更方便后续的压缩。

  • 压缩(Compression):执行Deflate压缩,该算法结合了 LZ77 算法和 Huffman 算法对图片进行编码。

八、如何用 CSS 实现一个三角形

📢 参考回答:

可以利用 border 属性

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

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

示例代码如下:

<div class="triangle"></div>

.triangle {
  width: 0;
  height: 0;
  border-width: 20px;
  border-style: solid;
  border-color: transparent transparent #f00 transparent;
}

九、清除浮动的方法

📢 参考回答:

  • clear 清除浮动(添加空div法)在浮动元素下方添加空div,并给该元素写css样式: {clear:both;height:0;overflow:hidden;}
  • 给浮动元素父级设置高度
  • 父级同时浮动(需要给父级同级元素添加浮动)
  • 父级设置成inline-block,其margin: 0 auto居中方式失效
  • 给父级添加overflow:hidden 清除浮动方法
  • 万能清除法 ::after 伪元素清浮动(现在主流方法,推荐使用)

清除浮动是指在浮动元素的父元素内部,使其能够正确地包含浮动元素,避免出现高度塌陷或父元素无法自适应高度的问题。

常见的清除浮动的方法包括:

  1. 使用 clear 属性

可以在浮动元素下方添加一个空元素,然后设置 clear 属性,清除浮动效果。

<div class="parent">
  <div class="float-element"></div>
  <div style="clear:both;"></div>
</div>

  1. 使用 overflow 属性

可以在父元素中设置 overflow 属性为 auto 或 hidden,使其成为一个 BFC(块级格式化上下文),从而清除浮动效果。

<div class="parent" style="overflow:auto;">
  <div class="float-element"></div>
</div>

  1. 使用 after 伪元素

可以在父元素中使用 :after 伪元素,设置 content 为空,然后设置 clear 属性,清除浮动效果。

<div class="parent">
  <div class="float-element"></div>
</div>

.parent:after {
  content: "";
  display: block;
  clear: both;
}

  1. 使用双伪元素

在父元素中使用双伪元素(:before 和 :after),分别设置 content 为空,然后使用 clear 属性清除浮动。

<div class="parent">
  <div class="float-element"></div>
</div>

.parent:before,
.parent:after {
  content: "";
  display: table;
}
.parent:after {
  clear: both;
}

十、如何触发重排和重绘?

📢 参考回答:

任何改变用来构建渲染树的信息都会导致一次重排或重绘:

  • 添加、删除、更新DOM节点
  • 通过display: none隐藏一个DOM节点-触发重排和重绘
  • 通过visibility: hidden隐藏一个DOM节点-只触发重绘,因为没有几何变化
  • 移动或者给页面中的DOM节点添加动画
  • 添加一个样式表,调整样式属性
  • 用户行为,例如调整窗口大小,改变字号,或者滚动。

以下是一些常见的触发重排和重绘的操作:

  1. 修改 DOM 元素的结构

当我们修改 DOM 元素的结构,例如添加、删除或移动元素时,会导致浏览器重新计算页面布局,触发重排。如果修改后的元素的样式也发生了变化,则还会触发重绘。

  1. 修改 DOM 元素的样式

当我们修改 DOM 元素的样式,例如修改元素的背景颜色、字体大小等属性时,会触发重绘。如果修改后的样式影响了元素的位置或大小,则还会触发重排。

  1. 修改浏览器窗口大小

当我们调整浏览器窗口的大小,会导致页面布局的变化,从而触发重排和重绘。

  1. 获取某些属性值

当我们获取某些属性值,例如元素的位置、大小、样式等属性时,也会触发浏览器重新计算元素的布局,从而触发重排。

十一、重绘与重排的区别?

📢 参考回答:

重排: 部分渲染树(或者整个渲染树)需要重新分析并且节点尺寸需要重新计算,表现为重新生成布局,重新排列元素

重绘: 由于节点的几何属性发生改变或者由于样式发生改变,例如改变元素背景色时,屏幕上的部分内容需要更新,表现为某些元素的外观被改变

单单改变元素的外观,肯定不会引起网页重新生成布局,但当浏览器完成重排之后,将会重新绘制受到此次重排影响的部分

重排和重绘代价是高昂的,它们会破坏用户体验,并且让UI展示非常迟缓,而相比之下重排的性能影响更大,在两者无法避免的情况下,一般我们宁可选择代价更小的重绘。

『重绘』不一定会出现『重排』,『重排』必然会出现『重绘』。

十二、如何优化图片

📢 参考回答:

  1. 对于很多装饰类图片,尽量不用图片,因为这类修饰图片完全可以用 CSS 去代替。
  2. 对于移动端来说,屏幕宽度就那么点,完全没有必要去加载原图浪费带宽。一般图片都用 CDN 加载,可以计算出适配屏幕的宽度,然后去请求相应裁剪好的图片。
  3. 小图使用 base64 格式
  4. 将多个图标文件整合到一张图片中(雪碧图)
  5. 选择正确的图片格式:
  • 对于能够显示 WebP 格式的浏览器尽量使用 WebP 格式。因为 WebP 格式具有更好的图像数据压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量,缺点就是兼容性并不好

  • 小图使用 PNG,其实对于大部分图标这类图片,完全可以使用 SVG 代替

  • 照片使用 JPEG

十三、你能描述一下渐进增强和优雅降级之间的不同吗?

📢 参考回答:

渐进增强 (progressive enhancement) :针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。

优雅降级 (graceful degradation) :一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。

区别:优雅降级是从复杂的现状开始,并试图减少用户体验的供给,而渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要。降级(功能衰减)意味着往回看;而渐进增强则意味着朝前看,同时保证其根基处于安全地带。

十四、隐藏页面中的某个元素的方法有哪些?

📢 参考回答:

隐藏类型

屏幕并不是唯一的输出机制,比如说屏幕上看不见的元素(隐藏的元素),其中一些依然能够被读屏软件阅读出来(因为读屏软件依赖于可访问性树来阐述)。为了消除它们之间的歧义,我们将其归为三大类:

  • 完全隐藏:元素从渲染树中消失,不占据空间。
  • 视觉上的隐藏:屏幕中不可见,占据空间。
  • 语义上的隐藏:读屏软件不可读,但正常占据空。

完全隐藏

(1) display 属性

 display: none;

(2) hidden 属性 HTML5 新增属性,相当于 display: none

<div hidden></div>

视觉上的隐藏

(1) 设置 posoition 为 absolute 或 fixed,通过设置 top、left 等值,将其移出可视区域。

position:absolute;
left: -99999px;

(2) 设置 position 为 relative,通过设置 top、left 等值,将其移出可视区域。

position: relative;
left: -99999px;
height: 0

(3) 设置 margin 值,将其移出可视区域范围(可视区域占位)。

margin-left: -99999px;
height: 0;
复制代码

语义上隐藏

aria-hidden 属性

读屏软件不可读,占据空间,可见。

<div aria-hidden="true"></div>

十五、CSS3 新增了那些东西?

📢 参考回答:

CSS3 新增东西众多,这里列举出一些关键的新增内容:

  • 选择器

  • 盒子模型属性:border-radius、box-shadow、border-image

  • 背景:background-size、background-origin、background-clip

  • 文本效果:text-shadow、word-wrap

  • 颜色:新增 RGBA,HSLA 模式

  • 渐变:线性渐变、径向渐变

  • 字体: @font-face

  • 2D/3D转换:transform、transform-origin

  • 过渡与动画:transition、@keyframes、animation

  • 多列布局

  • 媒体查询

CSS3 是 CSS 的最新版本,引入了许多新的功能和属性。下面是一些 CSS3 新增的东西:

  1. 选择器:CSS3 引入了新的选择器,如通用选择器、属性选择器、伪类选择器、伪元素选择器等。
  2. 盒子模型:CSS3 引入了新的盒子模型,包括盒子阴影、圆角、边框图片等。
  3. 字体:CSS3 引入了新的字体模块,包括 @font-face 属性和 Web 字体,允许开发者使用自定义字体。
  4. 颜色:CSS3 引入了新的颜色模块,包括透明度、渐变、颜色值的拓展等。
  5. 背景:CSS3 引入了新的背景模块,包括多背景图层、背景图片的尺寸、定位和滤镜等。
  6. 弹性盒子布局:CSS3 引入了弹性盒子布局模块,可以更方便地创建灵活的布局。
  7. 网格布局:CSS3 引入了网格布局模块,可以更容易地创建复杂的网格布局。
  8. 过渡和动画:CSS3 引入了过渡和动画,可以使网页更加生动有趣。
  9. 2D 和 3D 转换:CSS3 引入了 2D 和 3D 转换,可以在网页中创建各种形状和动画效果。