平平无奇古哥哥
2023/05/23阅读:15主题:橙心
前端面试:CSS高频面试题「2023」

本文收录于我写的《前端面试手册》,想获得更好的阅读体验请访问在线地址:https://gugiegie.gitee.io/frontend
1. 清除浮动有哪些方案?
清除浮动主要是为了解决父元素因为子元素浮动引起高度塌陷的问题。
本质上清除浮动的方式有两种,一种是利用clear属性,一种是利用BFC。
clear属性清除浮动又包括空标签法和伪元素法两种,代码如下:
-
使用空标签清除浮动 在浮动元素的末尾添加一个空标签,并设置 clear: both 属性,即可清除浮动。例如:
<div class="float-parent">
<div class="float-left"></div>
<div class="float-right"></div>
<div class="clearfix"></div>
</div>
.clearfix {
clear: both;
}
-
使用 :after 伪元素清除浮动
<div class="float-parent">
<div class="float-left"></div>
<div class="float-right"></div>
<div class="clearfix"></div>
</div>
.float-parent:after {
content: "";
display: table;
clear: both;
}
BFC清除浮动的方式有多种,我这里就以overflow为例:
<div class="float-parent" style="overflow: hidden;">
<div class="float-left"></div>
<div class="float-right"></div>
</div>
2. 伪类和伪元素有什么区别?
伪类表示被选择元素的某种状态或者选择是,常见的伪类有三种,状态类、结构类和表单类。例如:hover
就是状态类伪类,:first-child
就是结构类伪类,:cheked
就是表单类伪类。
a:hover { color: red; } /* 鼠标悬停在链接上时文字变成红色 */
input:checked + label { background-color: green; } /* 选中表单元素时相邻的标签背景变成绿色 */
伪元素用于创建一些不在文档树中的元素,并为其添加样式。伪元素常见的用途有给元素添加小部件、小图标以及清除浮动。 例如:
.arrow::before {
content: "";
display: block;
width: 0;
height: 0;
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
border-right: 10px solid red;
}
另外,虽然没有强制规定,但是伪类通常是单冒号,伪元素通常是用双冒号。
3. 你知道哪些实现元素居中的方案?
-
margin: 0 auto;
.element {
width: 200px;
margin: 0 auto;
}
-
flex居中
.parent {
display: flex;
justify-content: center;
align-items: center;
}
.element {
width: 200px;
height: 100px;
}
-
绝对定位 + transform实现居中:使用 position:absolute
属性和top、left、right、bottom属性,适用于元素宽度和高度未知的情况。
.parent {
position: relative;
}
.element {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
-
text-align: center;
适用于内联元素或将display属性设置为inline或inline-block的块级元素的子元素的水平居中。内联元素的垂直居中可以将line-height设置和height相等。
除此之外,还有其它很多居中方式,比如绝对定位 + 负margin、table布局居中、栅格布局居中等等。面试中只要了解每种方式的优缺点和适用场景,讲清楚最常用的几种方式就够了。
4. 什么是BFC,有什么作用?
BFC指的是块级格式化上下文,一个元素形成了BFC之后,那么它内部元素产生的布局不会影响到外部元素,外部元素的布局也不会影响到BFC中的内部元素。一个BFC就像是一个隔离区域,和其他区域互不影响。
触发 BFC 的方式有很多,主要是设置overflow、display、position属性,常见的有:
-
overflow值只要不为visible -
display取值为inline-block、flow-root、flex、table-cell -
position为absolute或fixed
BFC的作用主要是:
-
清除浮动 -
解决外边距重合问题
5. 讲一下你对盒模型的理解?
-
盒模型分为:内容(content)、填充(padding)、边界(margin)、边框(border)四个部分。
-
盒模型有两种:IE盒模型和标准盒模型。两者的区别是标准和模型的宽高不包含border和padding,而IE盒模型的宽高包含border和padding。
-
使用box-sizing属性可以切换和模型,默认值为content-box,即标准盒模型,border-box则是IE盒模型。
6. 怎么做移动端适配?
常用的移动端适配方案有以下几种:
-
rem方案:淘宝的移动端适配方案,使用相对单位rem结合JS动态计算rem值来实现移动端适配,将页面在不同尺寸的屏幕小按照宽度等比例缩放。
-
vw方案:使用Viewport相关的单位(如vw、vh、vmin和vmax)进行布局,可以让元素的大小和位置自适应不同的屏幕尺寸。
-
px方案:rem和vw方案都是等比例缩放,但是对于一些对UI要求特别高的大厂项目,缩放的显示效果并不是最佳,这时候也可以和UI配合采取px绝对像素。
-
媒体查询:对于一些具体的场景,可以根据不同设备的像素区间来针对性地编写样式,这时候就使用媒体查询。
-
百分比布局:将元素的宽度和高度设置为百分比,使得页面可以根据不同的屏幕尺寸进行等比例缩放,这种方案和rem、vw原理类似,但是计算比较困难,而且百分比相对的元素不固定,容易使问题变得复杂。
-
响应式布局:对于一些定制化程度要求不高,但是需要PC和移动两端共用一套代码的场景,可以使用一些响应式布局的样式库,比如Bootstrap和Tailwind。
我在项目里一般使用vw方案,结合自动化工具,如postcss-px-to-viewport和flexible.js进行自动的转换适配。然后对于一些特殊的场景,采用媒体查询作为辅助来实现。
7. 移动端1px边框问题怎么解决?
由于不同的设备屏幕像素密度的不同,一些边框、线条等细节元素的显示可能会出现“1px问题”,即在某些设备上,本应该显示为1像素的边框或者线条,实际上却被放大成了2像素或者更多像素,导致显示效果不佳。
常见的解决方案:
-
使用border-image:使用border-image可以将图片作为边框来显示,避免了使用CSS边框样式时的1px问题。
-
使用box-shadow:使用box-shadow代替边框,然后将边框设为透明,可以避免1px问题。
.border {
box-shadow: 0 0 0 1px #ccc;
}
-
border + transform:使用transform将边框缩小一半。
.border {
border: 1px solid #ccc;
transform: scaleY(0.5);
}
-
伪元素 + transform:与3类似,不同的是用伪元素来实现。
.border:before{
content: "";
display: block;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
border: 1px solid #ccc;
transform-origin: 0 0;
transform: scaleY(0.5);
}
在父元素上添加一个伪元素,然后给伪元素设置一个边框,并将其缩小为0.5倍。这样就可以实现1px的边框效果了。
-
使用viewport单位:使用viewport相关的单位(如vw、vh、vmin和vmax)来设置边框或者线条的大小,可以让元素的大小自适应不同的设备像素密度。
8. CSS有哪些主流布局方式?
CSS主要有五大主流布局:
-
flex布局,目前应用最广的布局方式,虽然不兼容IE低版本,但是就连微软自己都已经放弃IE11了。 -
浮动布局,需要清除浮动,副作用较多,现在使用的已经不多了,除了在部分PC端需要兼容IE低版本的项目中。 -
定位布局,主要用来实现定位效果,依然使用频繁。 -
栅格布局,面向未来的布局,只是现在兼容性还不是很好,且学习成本比较高。 -
table布局,比浮动布局还要老的布局,现在已经很少使用,不过兼容性特别好。
可以根据自己的日常开发经验以及这五种布局方式的优缺点和适用场景谈一谈对它们的理解。
9. 讲一下什么是重绘和回流?
重绘(Repaint):重绘是指当元素的样式改变,但不影响其在文档流中的位置时,浏览器会将新样式直接绘制到屏幕上,这个过程称为重绘。
回流(Reflow):当元素的尺寸、位置或其他属性发生变化时,浏览器需要重新计算页面中所有元素的位置和大小,并且将它们绘制到屏幕上,这个过程称为回流,又叫做重排。
回流的代价比重绘高得多,因为回流会导致浏览器重新计算页面布局,这个过程中涉及到大量的计算和DOM操作,所以需要尽量减少回流的次数。以下是一些可能导致回流的操作:
-
页面初始渲染时。 -
调整窗口大小时。 -
改变字体大小。 -
改变元素的大小或位置。 -
修改元素的内容,例如输入框中的文字。
可以通过以下方式来减少回流的次数:
-
使用transform替代top或left。 -
使用visibility替换display: none,因为前者只会引起重绘,后者会引发回流(改变了布局)。 -
不要把DOM节点的属性值放在一个循环里当成循环里的变量。 -
尽量不要使用table布局,可能很小的一个小改动就会造成整个table的重新布局。 -
尽量减少DOM的嵌套层级,减少不必要的父子元素节点。
10. 对CSS动画有了解吗,CSS实现动画有哪几种方式?
CSS动画主要包括transition动画、transform动画和animation动画。
-
transition动画:主要用来实现过渡效果,包括颜色、透明度、大小、位置,从一个状态向另一个状态过渡。
.element {
transition: property duration timing-function delay;
}
-
transform动画:用于对元素进行变形和转换,如旋转、缩放、平移和倾斜等。transform可以配合transition一起使用,例如:
.element {
transform: rotate(45deg);
transition: transform duration timing-function delay;
}
-
animation动画:使用@keyframes规则定义一组关键帧,描述元素在动画过程中的样式变化。然后通过animation属性将关键帧应用到元素上:
@keyframes animationName {
0% { /* 初始样式 */ }
50% { /* 中间样式 */ }
100% { /* 结束样式 */ }
}
.element {
animation: animationName duration timing-function delay iteration-count direction;
}
在日常开发中大多数时候制作简单动画使用一些第三方的CSS动画库就足够了,比如Animate.css、Hover.css,但是复杂动画不仅要考虑CSS,还要考虑JS。在Vue和React这样的框架中,都提供了Transition组件来让我们实现动画。
对于复杂动画,除了实现效果之外还要考虑到动画的性能优化,需要使用Chrome工具去调优。
前端动画是一个可以深入研究的话题,后续我也将会出专栏去深入讲解前端动画。
11. 什么是CSS工程化?
这是一个偏主观性的题,可以根据自己的项目经历从以下几个方面来回答:
-
预编译器:less、sass、stylus等。 -
CSS模块化方案:常见的像Vue里的scoped方案以及React里的CSS-in-JS方案。 -
CSS自动化工具:比如PostCSS,就提供很多有用的插件,让我们可以做一些CSS的自动化工作,比如自动添加前缀、自动格式化代码、移动端适配。 -
代码检测工具:如CSSLint、Stylelint等,可以自动化检测CSS代码的错误和潜在问题,提高代码质量和稳定性。 -
样式指南:主要是指CSS的规范,包括设计原则、排版规则、颜色使用、图标规范、命名规范、代码格式化等各方面的规范。
12. 怎么实现换肤?
-
使用CSS变量,可以定义一个 theme-color
变量来存储主题色:
:root {
--theme-color: #007bff; /* 定义主题色 */
}
然后在需要使用主题色的地方使用var()函数来引用这个变量:
.button {
background-color: var(--theme-color); /* 使用主题色 */
}
再通过JS动态更改这个CSS变量的值,从而实现换肤的效果。
-
使用class切换,通过添加或移除不同的class来改变元素的样式,从而实现换肤。
比如,可以定义多个class来表示不同的主题样式:
.theme-blue {
/* 定义蓝色主题样式 */
background-color: #007bff;
color: #fff;
}
.theme-red {
/* 定义红色主题样式 */
background-color: #dc3545;
color: #fff;
}
然后在需要换肤的元素上添加对应的class:
<button class="theme-blue">蓝色主题</button>
<button class="theme-red">红色主题</button>
最后再通过JS动态添加或移除这些class来改变元素的样式,来实现换肤的效果。
13. 预编译器用的哪个,了解哪些预编译器语法?
以less为例:
-
嵌套:最常用的预编译器语法,嵌套写法不仅减少了代码量,也使得样式代码更容易阅读维护了。
-
变量:可以使用“@”符号定义变量,比如颜色、字体大小、边框等等。
举个例子,我们定义了两个变量:
@primary-color: #007bff;
@font-size: 14px;
然后就可以在需要的地方使用:
h1 {
color: @primary-color;
font-size: @font-size;
}
-
函数:less函数用于封装通用的样式,比如封装一个给元素添加圆角的函数:
.border-radius(@radius) {
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
border-radius: @radius;
}
然后在需要用到的地方调用:
.box {
.border-radius(5px);
border: 1px solid #ccc;
}
-
mixin:和函数类似,也可以用来封装通用样式,比如居中、清除浮动等。
以居中为例:
@mixin center-both {
display: flex;
justify-content: center;
align-items: center;
}
然后就可以在需要居中的元素样式里使用了:
.my-element {
@include center-both;
width: 200px;
height: 200px;
}
14. 有没有了解过CSS命名规范?
常见的CSS命名规范有:BEM规范、SMACSS规范、OOCSS规范。
-
BEM规范:将CSS类名分为块、元素和修饰符三个部分。举个例子:
<div class="block">
<h2 class="block__title">标题</h2>
<ul class="block__list">
<li class="block__list-item">列表项1</li>
<li class="block__list-item block__list-item--highlighted">列表项2</li>
</ul>
</div>
其中block代表一个组件或UI部件,block__title和block__list代表块的子元素,block__list-item代表列表项。block__list-item--highlighted是一个修饰符,表示该列表项被突出显示。
-
SMACSS规范:SMACSS不仅仅是命名规范,还包括CSS文件结构的组织规范。SMACSS主要是将样式分成五大类,分别是Base、Layout、Module、State、Theme。其中:
-
Base类主要是基本样式规则,例如重置浏览器默认样式、设置全局的基本样式等。这些样式通常以选择器(标签选择器、通用选择器)为基础,并且适用于整个项目。 -
Layout类用于创建页面布局和网格系统,它定义了页面的整体结构、栏目布局、容器和网格样式等。 -
Module类用于定义可重复使用的模块样式。 -
State类用于定义组件的状态样式,如.btn和.btn-primary的样式。 -
Theme类主要是主题相关的样式,如.site-title和.module-title的样式。
-
OOCSS规范:OOCSS规范主要遵循结构(Structure)与外观(Skin)分离的原则,例如:
<div class="box box-red">你好</div>
<div class="box box-blue">OOCSS规范</div>
其中结构部分用.box,外观部分用.box-red来命名。
15. CSS有哪些优化手段?
CSS优化,可以从以下方面来考虑:
-
压缩CSS代码:通过删除空格、注释、冗余代码等方法,可以减小CSS文件的大小,提高加载速度,不过这些通常脚手架已经帮我们做好了。
-
合并CSS文件:将多个CSS文件合并成一个文件,减少HTTP请求次数,提高加载速度。在项目中可以用Webpack插件来实现。
-
首屏样式内联,可以减少加载CSS文件的时间,提升页面加载速度。
-
使用CSS3硬件加速,可以减少回流重绘,常见的触发硬件加速的CSS属性有:transform、opacity、filters、Will-change。
-
减少使用通配符和后代选择器:过多的通配符和后代选择器会降低选择器的匹配速度,应尽量减少使用。
-
避免使用过多的float:过多的浮动会导致页面回流和重绘,影响性能。
-
缓存:可以在服务器端设置协商缓存或者强缓存来缓存CSS请求。
日常开发中,除了开发CSS动画之外,绝大多数情况下,CSS的性能不会出现太明显的问题。所以在绝大多数情况下,只要是按照基本的规则和规范写CSS代码,问题就不大。
16. 为什么要做样式初始化?
因为浏览器有默认样式,而且不同浏览器默认样式不一样,为了让样式显示一致,要去掉这些默认样式。
常见的方案有:
-
reset.css
:将所有元素的样式都设置为相同的初始值,以消除不同浏览器之间的差异。这种方式需要注意的是,一些元素的样式可能与开发者所期望的有所不同,因此需要进行特殊处理。 -
Normalize.css
:只重置一部分元素的样式,而不是重置所有元素。这种方式可以避免一些样式上的问题,同时还可以保留一些元素的默认样式,提高代码的可维护性和可读性。
作者介绍