前端八股之CSS
1065
CSS基础
1. CSS选择器及其优先级
选择器 | 格式 | 优先级权重 |
---|---|---|
内联样式 | style="color:red;" | 1000 |
id选择器 | #id | 100 |
类选择器 | .class | 10 |
属性选择器 | a[ref="eee"] | 10 |
伪类选择器 | a:hover | 10 |
标签选择器 | a | 1 |
伪元素选择器 | a::before | 1 |
相邻兄弟选择器 | h1 + p | 0 |
直接子代选择器 | ul > li | 0 |
后代选择器 | ul a | 0 |
通配符选择器 | * | 0 |
2. display的block、inline和inline-block的区别
(1) block: 会独占一行,多个元素会另起一行,可以设置width、height、margin和padding属性。
(2) inline: 元素不会独占一行,设置width、height属性无效。但可以设置水平方向的margin和padding属性,不能设置垂直方向的padding和margin。
(3) inline-block: 将对象设置为inline对象,但对象的内容作为block对象呈现,之后的内联对象会被排列在同一行内。
对于行内元素和块级元素,其特点如下:
行内元素
- 设置宽高无效
- 可以设置水平方向的margin和padding属性,不能设置垂直方向的padding和margin
- 不会自动换行
块级元素
- 可以设置宽高
- 设置margin和padding都有效
- 会自动换行
- 多个块状,默认排列从上到下
3. 隐藏元素的方法有哪些
- display:none: 渲染树不会包含该渲染对象,因此该元素不会在页面中占据位置,也不会响应绑定的监听事件。
- visibility:hidden: 元素在页面中仍占据空间,但是不会响应绑定的监听事件。
- opacity:0: 将元素的透明度设置为 0,以此来实现元素的隐藏。元素在页面中仍然占据空间,并且能够响应元素绑定的监听事件。
- position:absolute: 通过使用绝对定位将元素移除可视区域内,以此来实现元素的隐藏。
- ** z-index:min**: 来使其他元素遮盖住该元素,以此来实现隐藏。
- clip/clip-path: 使用元素裁剪的方法来实现元素的隐藏,这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件。
- transform: scale(0, 0): 将元素缩放为 0,来实现元素的隐藏。这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件。
4. link和@import的区别
两者都是外部引用CSS的方式,它们的区别如下:
- link是XHTML标签,除了加载CSS外,还可以定义RSS等其他事务;@import属于CSS范畴,只能加载CSS。
- link引用CSS时,在页面载入时同时加载;@import需要页面网页完全载入以后加载。
- link支持使用Javascript控制DOM去改变样式;而@import不支持。
5. transition和animation的区别
- transition是过渡属性,强调过渡,它的实现需要触发一个事件(比如鼠标移动上去,焦点,点击等)才执行动画。
- animation是动画属性,它的实现不需要触发事件,设定好时间之后可以自己执行,且可以循环一个动画。它可以设置多个关键帧(用@keyframe定义)完成动画
6. display:none与visibility:hidden的区别
(1) 在渲染树中
display:none
会让元素完全从渲染树中小时,渲染时不会占据任何空间visibility:hidden
不会让元素从渲染树中小时,渲染的元素还会占据相应的空间,只是内容不可见 (2) ** 是否是继承属性**display:none
是非继承属性,子孙节点会随着父节点从渲染树消失,通过修改子孙节点的属性也无法显示visibility:hidden
是继承属性,子孙节点消失是由于继承了hidden,通过设置visibility:visible
可以让子孙节点显示 (3) 修改常规文档流中元素的display
通常会造成文档的重排,但是修改visibility
属性只会造成本元素的重绘
7. 伪元素和伪类的区别和作用?
- 伪元素:在内容元素的前后插入额外的元素或样式,但是这些元素实际上并不在文档中生成。它们只在外部显示可见,但不会在文档的源代码中找到它们,因此,称为“伪”元素。例如:
p::before {
content: "第一章: ";
}
p::after {
content: " END";
}
p::first-line {
background: red;
}
p::first-letter {
font-size: 30px;
}
- 伪类:将特殊的效果添加到特定选择器上。它是已有元素上添加类别的,不会产生新的元素。例如:
a:hover {
color: #ff00ff;
}
p:first-child {
color: red;
}
p: nth-child(2n) {
color: blue;
}
p:nth-child(2n+1) {
color: green;
}
8. 对requestAnimationframe
的理解
实现动画效果的方法比较多,Javascript中可以通过定时器setTimeout
来实现,CSS3 中可以使用transition
和animation
来实现,HTML5中的canvas
也可以实现。除此之外,HTML5 提供一个专门用于请求动画的API,那就是requestAnimationFrame
,顾名思义就是请求动画帧。
MDN对该方法的描述:
requestAnimationFrame()
方法告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。
语法:window.requestAnimationFrame(callback)
; 其中,callback是下一次重绘之前更新动画帧所调用的函数(即上面所说的回调函数)。该回调函数会被传入DOMHighResTimeStamp
参数,它表示requestAnimationFrame()
开始去执行回调函数的时刻。该方法属于宏任务,所以会在执行完微任务之后再去执行。
取消动画:使用cancelAnimationFrame()
来取消执行动画,该方法接收一个参数——requestAnimationFrame
默认返回的id,只需要传入这个id就可以取消动画了。
优势:
- CPU节能:使用
setInterval
实现的动画,当页面被隐藏或最小化时,仍然在后台执行动画任务,由于此时页面处于不可见或不可用状态,刷新动画是没有意义的,完全是浪费CPU资源。而RequestAnimationFrame
则完全不同,当页面处于未激活的状态下,该页面的屏幕刷新任务也会被系统暂停,因此跟着系统走的RequestAnimationFrame
也会停止渲染,当页面被激活时,动画就从上次停留的地方继续执行,有效节省了CPU开销。 - 函数节流:在高频率事件(resize,scroll等)中,为了防止在一个刷新间隔内发生多次函数执行,
RequestAnimationFrame
可保证每个刷新间隔内,函数只被执行一次,这样既能保证流畅性,也能更好的节省函数执行的开销,一个刷新间隔内函数执行多次时没有意义的,因为多数显示器每16.7ms(60hz)刷新一次,多次绘制并不会在屏幕上体现出来。 - 减少DOM操作:
requestAnimationFrame
会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。
9. 对盒模型的理解
CSS3中的盒模型有以下两种:标准盒子模型、IE盒子模型
盒模型都是由四个部分组成的,分别是margin、border、padding和content。
标准盒模型和IE盒模型的区别在于设置width和height时,所对应的范围不同:
- 标准盒模型的width和height属性的范围只包含了content
- IE盒模型的width和height属性的范围包含了border、padding和content
可以通过修改元素的box-sizing属性来改变元素的盒模型:
box-sizing: content-box
表示标准盒模型(默认值)box-sizing: border-box
表示IE盒模型(怪异盒模型)
10. 为什么有时候⽤translate来改变位置⽽不是定位?
translate
是transform
属性的⼀个值。改变transform
或opacity
不会触发浏览器重排或重绘,只会触发复合。⽽改变绝对定位会触发重新布局,进⽽触发重绘和复合。transform
使浏览器为元素创建⼀个GPU图层,但改变绝对定位会使⽤到CPU。 因此translate()
更⾼效,可以缩短平滑动画的绘制时间。但translate
改变位置时,元素依然会占据其原始空间,绝对定位就不会发⽣这种情况。
11. 对line-height
的理解及其赋值方式
(1) 概念
line-height
指一行文本的高度,包含了字间距,实际上是下一行基线到上一行基线距离- 如果一个标签没有定义
height
属性,那么其最终表现的高度由line-height
决定 - 一个容器没有设置高度,那么撑开容器高度的是
line-height
,而不是容器内的文本内容 - 把
line-height
值设置为height
一样大小的值可以实现单行文字的垂直居中 (2) 赋值方式 - 带单位:px 是固定值,而 em 会参考父元素 font-size 值计算自身的行高
- 纯数字:会把比例传递给后代。例如,父级行高为 1.5,子元素字体为 18px,则子元素行高为 1.5 * 18 = 27px
- 百分比:将计算后的值传递给后代
12. CSS 优化和提高性能的方法有哪些?
加载性能:
- css压缩:将写好的css进行打包压缩(gzip),可以减小文件体积
- 减少使用@import,建议使用link或者sass的@use,因为后者在页面加载时一起加载,前者是等待页面加载完成之后再进行加载
选择器性能:
- 如果规则拥有ID选择器作为其关键选择器,则不要为规则增加标签。过滤掉无关的规则
- 避免使用通配规则,如*{}计算次数惊人,只对需要用到的元素进行选择
- 尽量少的去对标签进行选择,而是用class
- 尽量少的去使用后代选择器,降低选择器的权重值
渲染性能:
- 慎重使用高性能属性:浮动、定位
- 尽量减少页面重排、重绘
- 属性值为0时,不加单位
- 标准化各种浏览器前缀:带浏览器前缀的在前。标准属性在后
- 不使用@import前缀,它会影响css的加载速度,使用@use等现代解决方案
- 选择器优化嵌套,尽量避免层级过深
可维护性、健壮性:
- 将具有相同属性的样式抽离出来,整合并通过class在页面中进行使用,提高css的可维护性
- 样式与内容分离:将css代码定义到外部css中
13. 单行、多行文本溢出隐藏
- 单行文本溢出
p {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
- 多行文本溢出,使用webkit浏览器的属性
p {
overflow: hidden;
textoverflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
- 多行文本溢出,使用line-height、height和after伪元素
p {
position: relative;
line-height: 20px;
height: 40px;
overflow: hidden;
}
p::after {
content: "...";
position: absolute;
bottom: 0;
right: 0;
padding: 0 20px 0 10px;
}
14. z-index属性在什么情况下会失效
通常 z-index 的使用是在有两个重叠的标签,在一定的情况下控制其中一个在另一个的上方或者下方出现。z-index值越大就越是在上层。z-index元素的position属性需要是relative,absolute或是fixed。
z-index属性在下列情况下会失效:
- 父元素position为relative时,子元素的z-index失效。解决:父元素position改为absolute或static
- 元素没有设置position属性为非static属性。解决:设置该元素的position属性为relative,absolute或是fixed中的一种
- 元素在设置z-index的同时还设置了float浮动。解决:float去除,改为display:inline-block
页面布局
1. 常见的CSS布局单位
- 像素(
px
)是页面布局的基础,一个像素表示终端(电脑、手机、平板等)屏幕所能显示的最小的区域,像素分为两种类型:CSS像素和物理像素- CSS像素: 为web开发者提供,在CSS中使用的一个抽象单位
- 物理像素: 只与设备的硬件密度有关,任何设备的物理像素都是固定的
- 百分比(
%
),当浏览器的宽度或者高度发生变化时,通过百分比单位可以使得浏览器中的组件的宽和高随着浏览器的变化而变化,从而实现响应式的效果。 - em和rem相对于px更具灵活性,它们都是相对长度单位,它们之间的区别:em相对于父元素,rem相对于根元素。
- em: 文本相对长度单位。如果当前行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸(默认16px)。(相对父元素的字体大小倍数).
- rem: rem是CSS3新增的一个相对单位,相对于根元素(html元素)的font-size的倍数。作用:利用rem可以实现简单的响应式布局。
- vw/vh是与视图窗口有关的单位,vw表示相对于视图窗口的宽度,vh表示相对于视图窗口高度,除了vw和vh外,还有vmin和vmax两个相关的单位
- vw:相对于视窗的宽度,视窗宽度是100vw
- vh:相对于视窗的高度,视窗高度是100vh
- vmin:vw和vh中的较小值
- vmax:vw和vh中的较大值
- dvw/dvh是CSS近年来引入的动态视口单位,主要用于解决移动端浏览器中视口尺寸因界面元素(如地址栏、工具栏)动态变化导致的布局问题。基于浏览器当前实际可见区域的视口尺寸计算,当用户滚动页面或浏览器界面元素(如移动端的地址栏)展开/收起时,动态视口单位会实时更新。
- 与传统vh/vw的区别:标准vh单位基于完整视口高度(包含被浏览器UI遮挡的部分),而dvh仅计算用户当前可见区域的高度,避免内容被动态UI遮挡或布局跳动。
- 在移动端开发中,使用dvh替代vh可更精准控制全屏元素的高度,适配地址栏隐藏时的场景。
- 相关单位扩展:svh/svw是小视口(Small Viewport)尺寸,表示浏览器UI元素最大展开状态时的视口尺寸;lvh/lvw是大视口(Large Viewport)尺寸,表示浏览器UI元素完全收起时的视口尺寸
2. 两栏布局的实现
一般两栏布局指的是左边一栏宽度固定,右边一栏宽度自适应,两栏布局的具体实现:
- 利用浮动,将左边元素宽度设置为200px,并且设置向左浮动。将右边元素的margin-left设置为200px,宽度设置为auto(默认为auto,撑满整个父元素)
.left {
float: left;
width: 200px;
}
.right {
margin-left: 200px;
width: auto;
}
- 利用flex布局,将左边元素设置为固定宽度200px,将右边的元素设置为flex:1。
.outer {
display: flex;
}
.left {
width: 200px;
}
.right {
flex: 1;
}
- 利用绝对定位,将父级元素设置为相对定位。左边元素宽度设置为200px,右边元素设置为绝对定位,左边定位为200px,其余方向定位为0.
.outer {
position: relative;
}
.left {
width: 200px;
}
.right {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 200px;
}
- 利用grid布局
.outer {
display: grid;
grid-template-columns 200px 1fr; /*关键代码,左栏固定200px,右栏占剩余空间 */
gap: 16px;
}
.left {}
.right {}
3. 三栏布局的实现
三栏布局一般指的是页面中一共有三栏,左右两栏宽度固定,中间自适应的布局,三栏布局的具体实现:
- 利用绝对定位,左右两栏设置为绝对定位,中间设置对应方向大小的margin的值
.outer {
position: relative;
}
.left {
position: absolute;
width: 100px;
}
.right {
position: absolute;
top: 0;
right: 0;
width: 200px;
}
.center {
margin-left: 100px;
margin-right: 200px;
}
- 利用flex布局,左右两栏设置固定大小,中间一栏设置为flex:1
.outer {
display: flex;
}
.left {
width: 100px;
}
.right {
width: 100px;
}
.center {
flex: 1;
}
- 利用grid布局
.outer {
display: grid;
grid-template-columns: 100px 1fr 200px;
gap: 0;
}
4. 对flex布局的理解及其使用场景
flex是FlexibleBox的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。任何一个容器都可以指定为flex布局。行内元素也可以使用flex布局。
采用Flex布局的元素,称为flex container,简称"容器"。它的所有子元素自动成为容器成员,称为flex item,简称"项目"。容器默认存在两根轴:主轴(main axis)和垂直的交叉轴(cross axis),项目默认沿水平主轴排列。
以下6个属性设置在容器上:
flex-direction
属性决定主轴的方向(即项目的排列方向)flex-wrap
属性定义,如果一条轴线排不下,如何换行flex-flow
属性是flex-direction
属性和flex-wrap
属性的简写形式,默认值为row nowrap
justify-content
属性定义了项目在主轴上的对齐方式align-items
属性定义项目在交叉轴上如何对齐align-content
属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用
以下6个属性设置在项目上:
order
属性定义项目的排列顺序。数值越小,排列越靠前,默认为0flex-grow
属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大flex-shrink
属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小flex-basis
属性定义了在分配多余空间之前,项目占据的主轴空间。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto
,即项目的本来大小flex
属性是flex-grow
,flex-shrink
和flex-basis
的简写,默认值为0 1 auto
align-self
属性允许单个项目有与其他项目不一样的对齐方式,可覆盖容器align-items
属性。默认值为auto
,表示继承父元素的align-items
属性
总的来说,flex布局是CSS3新增的一种布局方式,可以通过将一个元素的·属性值设置为flex从而使它成为一个flex容器,它的所有子元素都会成为它的项目。一个容器默认有两条轴:一个是水平的主轴,一个是与主轴垂直的交叉轴。可以使用flex-direction
来指定主轴的方向。可以使用justify-content
来指定元素在主轴上的排列方式,使用align-items
来指定元素在交叉轴上的排列方式。还可以使用flex-wrap
来规定当一行排列不下时的换行方式。对于容器中的项目,可以使用order
属性来指定项目的排列顺序,还可以使用flex-grow
来指定当排列空间有剩余的时候,项目的放大比例,还可以使用flex-shrink
来指定当排列空间不足时,项目的缩小比例。
定位
1. 对BFC的理解,如何创建BFC
块格式化上下文(Block Formatting Context,BFC)是Web页面的可视化CSS渲染的一部分,是布局过程中生成块级盒子的区域,也是浮动元素与其他元素的交互限定区域。
通俗来讲:BFC是一个独立的布局环境,可以理解为一个容器,在这个容器中按照一定规则进行物品摆放,并且不会影响其它环境中的物品。如果一个元素符合触发BFC的条件,则BFC中的元素布局不受外部影响
创建BFC的条件:
- 根元素:body
- 元素设置浮动:float 除 none 以外的值
- 元素设置绝对定位:position: (absolute、fixed)
- display 值为:inline-block、table-cell、table-caption、flex等
- overflow 值为:hidden、auto、scroll
BFC的作用:
- 解决margin的重叠问题:由于BFC是一个独立的区域,内部的元素和外部的元素互不影响,将两个元素变为两个BFC,就解决了margin重叠的问题
- 解决高度塌陷的问题:在对子元素设置浮动后,父元素会发生高度塌陷,也就是父元素的高度变为0。解决这个问题,只需要把父元素变成一个BFC。常用的办法是给父元素设置
overflow:hidden
。
2. 什么是margin重叠问题?如何解决?
两个块级元素的上外边距和下外边距可能会合并(折叠)为一个外边距,其大小会取其中外边距值大的那个,这种行为就是外边距折叠。需要注意的是,浮动的元素和绝对定位这种脱离文档流的元素的外边距不会折叠。重叠只会出现在垂直方向。
解决办法: (1) 兄弟之间重叠
- 底部元素变为行内盒子:
display:inline-block
- 底部元素设置浮动:
float
- 底部元素的position的值:
position: absolute/fixed
(2) 父子之间重叠 - 父元素加入:
overflow: hidden
- 父元素添加透明边框:
border:1px solid transparent
- 子元素变为行内盒子:
display: inline-block
- 子元素加入浮动属性或定位
3. 元素的层叠顺序
下面是盒模型的层叠规则:
- 背景和边框:建立当前层叠上下文元素的背景和边框
- 负的z-index:当前层叠上下文中,z-index属性值为负的元素
- 块级盒:文档流内非行内级非定位后代元素
- 浮动盒:非定位浮动元素
- 行内盒:文档流内行内级非定位后代元素
- z-index:0:层叠级数为0的定位元素
- 正z-index:z-index属性值为正的定位元素
4. position的属性有哪些,区别是什么
属性值 | 描述 |
---|---|
static | 默认值,没有定位,元素出现在正常的文档流中,会忽略 top , bottom , left , right 或者 z-index 声明,块级元素从上往下纵向排布,⾏级元素从左向右排列。 |
relative | 生成相对定位的元素,相对于其原来的位置进行定位。元素的位置通过left 、top 、right 、bottom 属性进行规定。 |
absolute | 生成绝对定位的元素,相对于static定位以外的一个父元素(通常是relative)进行定位。如果没有,相对<html> 。元素的位置通过left 、top 、right 、bottom 属性进行规定。 |
fixed | 生成绝对定位的元素,指定元素相对于屏幕视⼝的位置来指定元素位置。元素的位置在屏幕滚动时不会改变 |
inherit | 继承父元素的位置属性。 |
sticky | 元素在滚动到阈值前为relative,超过阈值后为fixed。如设置top: 0; 则滚动元素到顶部时固定。 |
场景应用
1. 实现一个三角形
CSS绘制三角形主要用到的是border属性,也就是边框。
平时在给盒子设置边框时,往往都设置很窄,就可能误以为边框是由矩形组成的。实际上,border属性是右三角形组成的,下面看一个例子:
<html>
<style>
div {
width: 0;
height: 0;
border: 100px solid;
border-color: orange blue red green;
}
</style>
<body>
<div class="div">
</div>
</body>
</html>
看两个三角形的例子:
<html>
<style>
div {
width: 0;
height: 0;
border-top: 50px solid red;
border-right: 50px solid transparent;
border-left: 50px solid transparent;
}
</style>
<body>
<div class="div">
</div>
</body>
</html>
<html>
<style>
div {
width: 0;
height: 0;
border-top: 100px solid red;
border-right: 100px solid transparent;
}
</style>
<body>
<div class="div">
</div>
</body>
</html>