前端面试基础题:CSS选择器及其优先级
✨ CSS选择器及其优先级
基础选择器
基础选择器 | 作用 | 用法 |
---|---|---|
标签选择器 | 选出所有相同标签 | p { color: red; } |
类选择器 | 选出具有相同类名的一个或多个标签 | .nav { color: red; } |
id选择器 | 选出对应id的那一个标签 | #nav { color: red; } |
通配符选择器 | 选择所有标签 | * { color: red; } |
复合选择器
复合选择器 | 作用 | 用法 |
---|---|---|
后代选择器 | 选择后代元素(可以是子孙后代) | .nav a |
子代选择器 | 选择最近一级元素(亲儿子) | .nav > a |
并集选择器 | 选择某些相同样式的元素 | .nav, .header |
链接伪类选择器 | 选择不同状态的链接 | a:link a:visited a:hover a:active |
:focus选择器 | 选择获得光标的表单 | input:focus |
链接伪类选择器:
声明顺序:link - visited - hover - active
- a:link:选择所有未被访问的链接
- a:visited:选择所有已被访问的链接
- a:hover:选择鼠标指针位于其上的链接
- a:active:选择鼠标按下未弹起的链接
属性选择器
选择符 | 作用 |
---|---|
E[att] | 选择具有att属性的E元素 |
E[att="val"] | 选择具有att属性且属性值等于val的E元素 |
E[att^="val"] | 匹配具有att属性且值为val开头的E元素 |
E[att$="val"] | 匹配具有att属性且值以val结尾的E元素 |
E[att*="val"] | 匹配具有att属性且值中含有val的E元素 |
结构伪类选择器
选择符 | 作用 |
---|---|
E:first-child | 匹配父元素中的第一个子元素E |
E:last-child | 匹配父元素中最后一个子元素E |
E:nth-child(n) | 匹配父元素中第n个子元素E |
E:first-of-type | 指定类型E的第一个 |
E:last-of-type | 指定类型E的最后一个 |
E:nth-of-type(n) | 指定类型E的第n个 |
- nth-child和nth-of-type的区别:
nth-child对父元素里面所有孩子排序选择,先找到第n个孩子,然后看看是否和E匹配;nth-of-type对父元素里面指定子元素进行排序,先去匹配E,然后再根据E找到第n个孩子。(n如果是公式,则从0开始计算)
伪元素选择器
选择符 | 作用 |
---|---|
::before | 在元素内部的前面插入内容 |
::after | 在元素内部的后面插入内容 |
- 伪元素在文档树中是找不到的,before和after必须有content属性。
- 伪元素和伪类的区别:
- 伪元素:在内容元素的前后插入额外的元素或样式,但这些元素实际上并不在文档中生成。
- 伪类:将特殊的效果添加到特定选择器上,它是已有元素上添加类别的,不会产生新的元素。
优先级
选择器 | 优先级 |
---|---|
标签选择器、伪元素选择器 | 1 |
类选择器、伪类选择器、属性选择器 | 10 |
ID选择器 | 100 |
内联样式 | 1000 |
!important | ∞ |
- 如果优先级相同,则最后出现的样式生效(层叠性);
- 继承得到的样式的优先级最低;
- 通用选择器(*)、子选择器(>)和相邻同胞选择器(+)并不在这四个等级中,所以它们的权值都为 0 ;
- 样式表的来源不同时,优先级顺序为:内联样式 > 内部样式 > 外部样式 > 浏览器用户自定义样式 > 浏览器默认样式。
- CSS三大特性:层叠性、继承性、优先级。
✨ CSS引入方式
- 内联样式(行内样式表):控制一个标签的样式,使用标签的
style
属性; - 内部样式:控制一个页面的样式,在头部添加
<style></style>
标签; - 外部样式:可以控制多个页面的样式,通过
<link>
标签引入样式表文件。
✨ CSS属性
CSS字体属性
font-size
:字号font-family
:字体font-weight
:字体粗细(100-900,400:normal,700:bold)font-style
:字体样式(italic斜体,normal不倾斜)- 连写:
font: font-style font-weight font-size/line-height font-family
CSS文本属性
color
:文本颜色text-align
:文本对齐text-indent
:文本缩进text-decoration
:文本修饰(underline下划线,none去掉下划线)line-height
:行高
CSS背景
background-color
: 背景颜色background-image
: 背景图片background-repeat
: 是否平铺background-position
: 背景位置background-attachment
: 背景附着
边框
border: border-width border-style border-color;
border-radius: length; /* 声明顺序:左上、右上、右下、左下 */
阴影
box-shadow: h-shadow v-shadow blur spread color inset;
text-shadow: h-shadow v-shadow blur color;
h-shadow
:水平阴影位置(正值:右侧,负值:左侧)v-shadow
:垂直阴影位置(正值:下方,负值:上方)blur
:模糊距离spread
:阴影尺寸color
:阴影颜色inset
:将外部阴影(默认)改为内部阴影
✨ CSS中可继承属性
- 字体系列属性
font-family:字体系列
font-weight:字体的粗细
font-size:字体的大小
font-style:字体的风格
2. 文本系列属性
text-indent:文本缩进
text-align:文本水平对齐
line-height:行高
word-spacing:单词之间的间距
letter-spacing:中文或者字母之间的间距
text-transform:控制文本大小写(就是uppercase、lowercase、capitalize这三个)
3. 元素可见性
visibility:控制元素显示隐藏
4. 列表布局属性
list-style:列表风格,包括list-style-type、list-style-image等
5. 光标属性
cursor:光标显示为何种形态
✨ display的block、inline和inline-block的区别 (块级、行内、行内块元素的区别)
元素模式 | block | inline | inline-block |
---|---|---|---|
元素排列 | 一行只能放一个 | 一行可以放多个 | 一行可以放多个 |
设置样式 | 可以设置宽高 | 不可以设置宽高 | 可以设置宽高 |
默认宽度 | 容器100% | 本身内容宽度 | 本身内容宽度 |
包含 | 可以包含任何标签 | 可以包含文本或其他行内元素 | - |
常见元素 | <h1>-<h6>, <p>,<div>, <ul>, <ol>, <li> | <a>, <strong>, <b>, <em>, <i>, <del>, <s>, <ins>, <u>, <span> | <img>, <input>, <td> |
✨ 隐藏元素的方法
display: none
:渲染树不会包含该渲染对象,因此该元素不会在页面中占据位置,也不会响应绑定的监听事件;visibility: hidden
:元素在页面中仍占据空间,但是不会响应绑定的监听事件;opacity: 0
:将元素的透明度设置为 0,以此来实现元素的隐藏。元素在页面中仍然占据空间,并且能够响应元素绑定的监听事件。
✨ 盒子模型
CSS3中的盒模型有以下两种:标准盒子模型、IE盒子模型
盒模型都是由四个部分组成的,分别是margin、border、padding和content。
外边距margin和内边距padding声明顺序:上、右、下、左
标准盒模型和IE盒模型的区别在于设置width和height时,所对应的范围不同:
- 标准盒模型的width和height属性的范围只包含了content,
- IE盒模型的width和height属性的范围包含了border、padding和content。
可以通过修改元素的box-sizing属性来改变元素的盒模型:
box-sizing: content-box
表示标准盒模型(默认值)box-sizing: border-box
表示IE盒模型(怪异盒模型)

✨ 单行、多行文本溢出隐藏
单行
overflow: hidden; // 溢出隐藏
text-overflow: ellipsis; // 溢出用省略号显示
white-space: nowrap; // 段落中文字不换行
多行
overflow:hidden;
text-overflow: ellipsis;
display: -webkit-box; // 作为弹性伸缩盒子模型显示
-webkit-box-orient: vertical; // 设置伸缩盒子子元素排列从上到下垂直排列
-webkit-line-clamp: 2; // 显示行数
✨ 常见CSS布局单位
- 像素(px):是页面布局的基础,一个像素表示终端(电脑、手机、平板等)屏幕所能显示的最小的区域,像素分为两种类型:CSS像素和物理像素:
- CSS像素:为web开发者提供,在CSS中使用的一个抽象单位;
- 物理像素:只与设备的硬件密度有关,任何设备的物理像素都是固定的。
- 百分比(%),当浏览器的宽度或者高度发生变化时,通过百分比单位可以使得浏览器中的组件的宽和高随着浏览器的变化而变化,从而实现响应式的效果。一般认为子元素的百分比相对于直接父元素。
- em: 文本相对长度单位。相对于当前对象内文本的字体尺寸。
- rem: rem是CSS3新增的一个相对单位,相对于根元素(html元素)的font-size的倍数。作用:利用rem可以实现简单的响应式布局,可以利用html元素中字体的大小与屏幕间的比值来设置font-size的值,以此实现当屏幕分辨率变化时让元素也随之变化。
- vw/vh和vmin/vmax:是与视图窗口有关的单位,vw表示相对于视图窗口的宽度,vh表示相对于视图窗口高度,除了vw和vh外,还有vmin和vmax两个相关的单位。
- vw:相对于视窗的宽度,1vw=1/100视窗宽度;
- vh:相对于视窗的高度,1vh=1/100视窗高度;
- vmin:vw和vh中的较小值;
- vmax:vw和vh中的较大值;
✨ 浮动
浮动的特性:
- 浮动的元素会脱离标准流,不在保留原先的位置;
- 浮动的元素会一行内显示并且按元素顶部对齐;
- 浮动的元素会具有行内块的特性。
清除浮动的方法:
容器不设高度且子元素浮动时,容器高度不能被内容撑开。 此时,内容会溢出到容器外面而影响布局。这种现象被称为浮动(溢出)。
- 给父级设置height属性;
- 额外标签法:最后一个浮动元素之后添加一个空的div标签,并添加样式
clear: both
; - 给包含浮动元素的父级标签添加
overflow: hidden
或overflow: auto
; - 单伪元素法:父级使用
::after
伪元素,由于IE6-7不支持,使用zoom: 1
触发hasLayout;
.clearfix::before {
content: '';
display: block;
clear: both;
}
.clearfix {
zoom: 1; /* IE6、7需要设置 */
}
5. 双伪元素法(伪元素添加在父节点上,插入到内部最前/后位置)
.clearfix::before, .clearfix::after {
content: '';
display: table;
}
.clearfix::after {
clear: both;
}
.clearfix {
zoom: 1; /* IE6、7需要设置 */
}
✨ 定位
- 静态定位(static):默认定位方式(无定位),静态定位按照标准流特性摆放位置,没有边偏移。
- 相对定位(relative):相对定位元素在移动位置的时候,是相对于它原来的位置来说的。原来在标准流的位置继续占有。
- 绝对定位(absolute):绝对定位元素在移动位置的时候,是相对于它祖先元素来说的。如果没有祖先元素或祖先元素没有定位,以浏览器为准定位;如果祖先元素有定位,则以最近一级有定位祖先元素为参考点移动位置。绝对定位不再占有原先位置。
- 固定定位(fixed):元素固定于浏览器可视区的位置,以浏览器的可视窗口为参照点移动元素。跟父元素没有任何关系,不随滚动条滚动。固定定位不再占有原先位置。
定位叠放次序:z-index
,数值越大,盒子越靠上,只有定位的盒子才有z-index
属性。
✨ BFC块级格式化上下文
可以把BFC看做一个容器,容器里边的元素不会影响到容器外部的元素。BFC它决定了元素如何对其内容进行定位,以及与其它元素的关系和相互作用,当涉及到可视化布局时,BFC提供了一个环境,HTML在这个环境中按照一定的规则进行布局。
特性
- BFC是一个块级元素,块级元素在垂直方向上依次排列
- BFC是一个独立的容器,内部元素不会影响容器外部的元素
- 属于同一个BFC的两个盒子,外边距margin会发生重叠,并且取最大外边距。
外边距合并问题
- 相邻块元素垂直外边距的合并
当上下两个块元素(兄弟关系)相遇时,如果上面的元素有下外边距margin-bottom,下面的元素有上外边距margin-top,则他们之间的垂直间距不是margin-bottom与margin-top之和,而是取两个值中的较大值。

解决方法:尽量只给一个盒子添加margin值
2. 嵌套块元素垂直外边距塌陷
对于两个嵌套关系(父子关系)的块元素,父元素有上外边距同时子元素也有上外边距,此时父元素会塌陷较大的外边距值。

解决方法:可以为父元素定义上边距,可以为父元素定义上内边距,可以为父元素添加overflow: hidden。
如何创建BFC
- overflow: hidden;
- display: flex;
- display: inline-flex;
- display: inline-block;
- position: absolute;
- position: fixed;
BFC作用
- 解决当父级元素没有高度时,子级元素浮动会使父级元素高度塌陷的问题(给父元素添加
overflow: hidden;
) - 解决子级元素外边距会使父级元素塌陷的问题(给父元素添加
overflow: hidden;
)
✨ CSS布局
水平居中
text-align: center
,针对行内元素margin: 0 auto
- 绝对定位方法
#parent {
height: 200px;
width: 200px;
position: relative;
}
#son {
position: absolute;
left: 50%;
transform: translateX(-50%);
height: 100px;
width: 100px;
}
4. flex布局
#parent {
display: flex;
justify-content: center;
}
垂直居中
line-height: height
,针对行内内容vertical-align: middle
- 绝对定位方法
#parent {
display: relative;
height: 150px;
}
#son {
position: absolute;
top: 50%;
transform: translateY(-50%);
height: 50px;
}
4. flex布局
/* 方法1 */
#parent {
display: flex;
align-items: center;
}
/* 方法2 */
#parent {
display: flex;
flex-direction: column;
justify-content: center;
}
/* 方法3 */
#parent {
display: flex;
}
#son {
align-self: center;
}
两列布局:左列定宽,右列自适应
- 左浮动 +
margin-left
#left {
float:left;
width: 100px;
height: 500px;
}
#right {
height: 500px;
margin-left: 100px;
}
2. table布局
#parent {
display: table;
width: 100%;
height: 500px;
}
#left {
width: 100px;
}
#left, #right {
display: table-cell;
}
3. 绝对定位 + left偏移量
#parent {
position: relative;
}
#left {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 500px;
}
#right {
position: absolute;
top: 0;
left: 100px;
right: 0;
height: 500px;
}
4. flex布局
#parent {
display: flex;
width: 100%;
height: 500px;
}
#left {
width: 100px;
}
#right {
flex: 1;
}
三列布局:两侧定宽,中间自适应
1. 双飞翼布局
<div id="header"></div>
<div id="center">
<div id="center_inbox"></div>
</div>
<div id="left"></div>
<div id="right"></div>
<div id="footer"></div>
#header {
height: 60px;
background-color: #ccc;
}
#left {
float: left;
width: 100px;
height: 500px;
margin-left: -100%; /* 百分比相对于父元素 */
background-color: #f00;
opacity: 0.5;
}
#center {
height: 500px;
float: left;
width: 100%;
background-color: #eeff2b;
}
#center {
height: 500px;
float: left;
width: 100%;
background-color: #eeff2b;
}
#center_inbox{
height: 480px;
border: 1px solid #000;
margin: 0 220px 0 120px; /* 左右边界等于左右盒子的宽度,多出来的为盒子间隔 */
}
#right {
float: left;
width: 200px;
height: 500px;
margin-left: -200px; /* 使right到指定的位置,值等于自身宽度 */
background-color: #0f0;
opacity: 0.5;
}
#footer {
clear: both; /*注意清除浮动!!*/
height: 60px;
background-color: #ccc;
}

2. 圣杯布局
<div id="header"></div>
<div id="parent">
<div id="center"></div>
<div id="left"></div>
<div id="right"></div>
</div>
<div id="footer"></div>
#header{
height: 60px;
background-color: #ccc;
}
#parent {
box-sizing: border-box;
height: 500px;
padding: 0 215px 0 115px; /* 左右padding分别等于左右盒子的宽,可以结合左右盒子相对定位的left调整间距 */
}
#center {
float: left;
width: 100%; /* 由于parent的padding,达到自适应的目的 */
height: 500px;
box-sizing: border-box;
border: 1px solid #000;
background-color: #eeff2b;
}
#left {
margin-left: -100%; /*使left上去一行*/
position: relative;
left: -115px;
float: left;
width: 100px;
height: 500px;
background-color: #f00;
opacity: 0.5;
}
#right {
position: relative;
left: 215px;
width: 200px;
height: 500px;
margin-left: -200px; /*使right上去一行*/
float: left;
background-color: #0f0;
opacity: 0.5;
}
#footer{
height: 60px;
background-color: #ccc;
}

3. table
#parent {
width: 100%;
height: 500px;
display: table;
}
#left {
display: table-cell;
width: 100px;
background-color: #f00;
}
#center {
display: table-cell;
background-color: #eeff2b;
}
#right {
display: table-cell;
width: 200px;
background-color: #0f0;
4. flex布局
#parent {
height: 500px;
display: flex;
}
#left {
width: 100px;
background-color: #f00;
}
#center {
flex: 1;
background-color: #eeff2b;
}
#right {
width: 200px;
background-color: #0f0;
}
5. 定位
#parent {
position: relative;
}
#left {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 500px;
background-color: #f00;
}
#center {
height: 500px;
margin-left: 100px;
margin-right: 200px;
background-color: #eeff2b;
}
#right {
position: absolute;
top: 0;
right: 0;
width: 200px;
height: 500px;
background-color: #0f0;
✨ 浏览器解析渲染页面

- 解析HTML,生成DOM树,解析CSS,生成CSSOM树;
- 将DOM树和CSSOM树结合,生成渲染树(Render Tree)(渲染树只包含可见节点);
- Layout(回流):根据生成的渲染树,进行回流,得到节点的几何信息(位置,大小);
- Painting(重绘):根据渲染树以及回流得到的几何信息,得到节点的绝对像素;
- Display:将像素发送给GPU,显示在页面上。
Reflow和Repaint
- Reflow:回流(重排)。一般意味着元素的内容、结构、位置或尺寸发生了变化,需要重新计算样式和渲染树。
- Repaint:即重绘。意味着元素发生的改变只是影响了元素的一些外观之类的时候(例如,背景色,边框颜色,文字颜色等),此时只需要应用新样式绘制这个元素就可以了。
- 回流的成本开销要高于重绘,而且一个节点的回流往往会导致子节点以及同级节点的回流, 所以优化方案中一般都包括,尽量避免回流。回流一定导致重绘,但重绘不一定会导致回流。
✨动画
前端实现动画效果的几种方式:
- JavaScript:通过定时器(
setTimeout
,setInterval
)来改变元素样式,或者使用requestAnimationFrame
; - CSS3:
transition
、animation
; - HTML5:使用HTML5提供的绘图方式(canvas,svg,webgl)。
requestAnimationFrame
setInterval
和setTimeout
会出现执行时机不准的问题,requestAnimationFrame
在浏览器每次刷新下一帧之前执行,动画效果更流畅。- 一般的浏览器的刷新率为60Hz,也就是说,1秒钟就会刷新60次,也就是说,大概每过
16.6ms
浏览器会渲染一帧画面。 requestAnimationFrame
翻译过来就是请求动画帧,还是帧动画。它告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。requestAnimationFrame
使用一个回调函数作为参数,这个回调函数会在浏览器下一次重绘之前调用,由于功效只是一次性的,所以想实现连续的动效,需要递归调用。该方法属于宏任务。cancelAnimationFrame
方法用于取消重绘。
<div id="demo" style="position:absolute; width:100px; height:100px; background:#ccc; left:0; top:0;"></div>
<script>
var demo = document.getElementById('demo');
function render(){
//每一帧向右移动1px
demo.style.left = parseInt(demo.style.left) + 1 + 'px';
}
requestAnimationFrame(function(){
render();
//当超过300px后才停止
if(parseInt(demo.style.left) <= 300)
requestAnimationFrame(arguments.callee);
});
</script>
arguments.callee 在哪一个函数中运行,它就代表哪一个函数。 一般用在匿名函数中。在匿名函数中有时会需要自己调用自己,但是由于是匿名函数,没有名子,无名可调。这时就可以用arguments.callee来代替匿名的函数。
定时器动画和requestAnimationFrame:
requestAnimationFrame解决了定时器动画时间间隔不稳定的问题。因为定时器为宏任务,必须等同步任务执行完成,以及等微任务执行完成才会执行其中的回调——导致规定的间隔实际上是不稳定的不准确的。requestAniamationFrame
的执行步伐是跟着系统走的,如果系统的绘制频率是60Hz,那么回调函数就每16.7ms被执行一次--这样不会引起丢帧现象也不会卡顿。
requestAnimationFrame优点:
requestAnimationFrame
会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率;- 在隐藏或不可见的元素中,
requestAnimationFrame
将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。
transition
- transition 属性允许块级元素中的属性在指定的时间内平滑的改变
transition: property duration timing-function delay;
值 | 描述 |
---|---|
transition-property | 规定设置过渡效果的CSS属性名称 (none / all / property) |
transition-duration | 规定完成过渡效果需要多少毫秒 |
transition-timing-function | 规定速度效果的速度曲线 (linear / ease / ease-in / ease-out / ease-in-out / cubic-bezier(n, n, n)) |
transition-delay | 定义过渡效果何时开始 |
#demo {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
left: 0;
top: 0;
transition: all 1s;
}
#demo:hover {
width: 300px;
height: 300px;
background-color: pink;
}
Animation
Animation作用于元素本身而不是样式属性,可以使用关键帧的概念,实现更自由的动画效果。
animation: name duration timing-function delay iteration-count direction;
值 | 描述 |
---|---|
animation-name | 规定要绑定到选择器的keyframe名称 |
animation-duration | 规定完成动画所花费的时间 |
animation-timing-function | 规定动画的速度曲线 |
animation-delay | 规定动画开始之前的延迟 |
animation-iteration-count | 规定动画应该播放的次数 |
animation-direction | 规定是否应该轮流反向播放动画(normal,alternate) |
#demo {
animation-name: slide;
animation-duration: 2s;
animation-delay: 1s;
position: absolute;
top: 100px;
left: 100px;
width: 100px;
height: 100px;
background-color: red;
}
@keyframes slide {
0% {
left: 0;
top: 0;
}
50% {
left: 100px;
top: 0;
}
100% {
left: 100px;
top: 100px;
}
}
transition和animation的区别
- transition需要事件触发,不会在页面加载时自动触发;
- transition是一次性的,不能重复发生,除非不断触发事件;
- transition只能定义开始状态和结束状态,不能定义中间状态。
JS动画和CSS动画的区别
CSS动画是定义不同时间的状态,然后它进行补间动画,而JS实现为了保证其过程流畅,是帧动画。
对于帧速表现不好的低版本浏览器,CSS动画可以做到自然降级,而JS则需要撰写额外代码。
✨ CSS优化和提高性能的方法
- CSS压缩:将CSS文件打包压缩,减小文件体积
- CSS单一样式:相比于
margin: top 0 bottom 0;
,margin-top: top; margin-bottom: bottom;
执行效率更高 - 减少使用
@import
,使用<link>
代替 - 尽量少用通配符选择器,标签选择器,后代选择器,将选择器的深度降到最低
- 减少页面重排重绘
- 慎重使用高性能属性:浮动、定位
- CSS精灵图(雪碧图):减少页面请求次数
✨ CSS3新特性
- 边框:
border-radius
、box-shadow
、border-image
、box-sizing
- 背景:
background-size
、background-origin
、background-clip
- 渐变:
linear-gradient
、radial-gradient
- 过渡:
transition
- 动画:
animation
- 2D转换:
transform: translate(x, y) rotate(deg) scale(x, y)
- 3D转换:
transform: translate3d(x, y, x) rotate3d(x, y, z, deg) scale3d(x, y, z)