CSS面试记录
如何实现一个元素的水平垂直居中?
要求对行内元素、块状元素及不定宽高的块状元素均可适用:
css3 有哪些新特性?
- rgba 和 透明度
- background-image、background-origin、background-size、background-repeat
- word-wrap: break-word(对长的不可分割的单词换行)
- 文字阴影 text-shadow
- font-face属性,定义自己的字体
- border-radius
- 边框图片 border-image
- 盒阴影 box-shadow
- 媒体查询:定义多套 css,当浏览器尺寸发生变化时采用不同的属性
style 标签写在 body 后与 body 前有什么区别?
- 写在 body 标签前有利于浏览器逐步渲染: resources downloading –> cssDOM + DOM –> Render Tree –> layout –> paint
- 写在 body 标签后: 由于浏览器以逐行方式对 HTML 文档进行解析,当解析到写在尾部的样式表(外联或写在 style 标签)会导致浏览器停止之前的渲染,等待加载且解析样式完成后重新渲染;在 windows 的 IE 下可能出现样式失效导致的页面闪烁问题。
CSS选择器及优先级
- 选择器
- id选择器(#myid)
- 类选择器(.myclass)
- 属性选择器(a[rel=”external”])
- 伪类选择器(a:hover, li:nth-child)
- 标签选择器(div, h1, p)
- 伪元素选择器(p::first-line)
- 相邻选择器(h1 + p)
- 子选择器(ul > li)
- 后代选择器(li a)
- 通配符选择器(*)
- 优先级
!important
- 内联样式(1000)
- ID选择器(0100)
- 类选择器 / 属性选择器 / 伪类选择器(0010)
- 标签选择器 / 伪元素选择器(0001)
- 关系选择器 / 通配符选择器(0000)
带 !important
标记的样式属性优先级最高;样式表的来源相同时:!important > 行内样式> ID选择器 > 类选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性
rgba() 和 opacity 设置透明度的区别是什么?
rgba()
和opacity
都能实现透明效果,但最大的不同是 opacity 作用于元素,以及元素内的所有内容的透明度
;而 rgba()
只作用于元素的颜色或其背景色,设置 rgba()
透明的元素的子元素不会继承透明效果。
浏览器是如何解析 css 选择器等?
从右向左解析的。
若从左向右匹配,发现不符合规则,需要回溯,会损失很多性能。若从右向左匹配,先找到所有的最后节点,对于每一个节点,向上寻找其父节点直到查找至根元素或满足条件的匹配规则,则结束这个分支的遍历。
在 css 解析完毕后,需将解析结果 css 规则树和 DOM Tree 一起进行分析建立一颗 Render Tree,最终用来进行绘图。
display: none 和 visibility: hidden 两者的区别
display: none
隐藏后不占用文档流;而visibility: hidden
会占用文档流。visibility
具有继承性,给父元素设置visibility: hidden
,子元素也会继承该属性,但如果重新给子元素设置visibility: visible
,则子元素又会显示出来。visibility: hidden
不会影响计数器的计数,虽然隐藏了,但计数器依然运行着。- 在 css3 中
transition
支持visibility
属性,但不支持display
。因为transition
可以延迟执行,因此配合 visibility 使用纯 css 延时显示效果可以提高用户体验。 display: none
会引起回流(重排)和重绘;visibility: hidden 会引起重绘。
简述 transform,transition,animation 的作用
transform
:描述了元素的静态样式,本身不会呈现动画效果,可以对元素进行旋转 rotate、扭曲 skew、缩放 scale 和移动 translate 以及矩阵变形 matrix。transition
和animation
两者都能实现动画效果。transform
常配合transition
和animation
使用。transition
:样式过渡,从一种效果逐渐改变为另一种效果,它是一个合写属性。transition: transition-property transition-duration transition-timing-function transition-delay 从左到右,依次是:过渡效果的css属性名称、过渡效果花费时间、速度曲线、过渡开始的延迟时间transition
通常和 hover 等事件配合使用,需要由事件来触发过渡。animation
:动画,有@keyframes
来描述每一帧
的样式。—–关键帧
区别:
transform
仅描述元素的静态样式,常配合transition
和animation
使用。transition
通常和 hover 等事件配合使用;animation
是自发的,立即播放。animation
可以设置循环次数。animation
可以设置每一帧的样式和时间,transition
只能设置头尾。transition
可以与js
配合使用,js
设定要变化的样式,transition
负责动画效果。
line-height 如何继承?
- 父元素的
line-height
是具体数值,则子元素line-height
继承该值。 - 父元素的
line-height
是比例值,如’2’,则子元素line-height
继承该比例。 - 父元素的
line-height
是百分比,则子元素line-height
继承的是父元素的 font-size * 百分比 计算出来的值。
如何让 chrome 支持 10px 的文字?
- font-size: 12px; -webkit-transform: scale(0.84);
- font-size: 20px; -webkit-transform: scale(0.5);
position 属性的值有哪些?
static
:默认定位。元素出现在正常的文档流中(忽略top,bottom,left,right 或 z-index声明)relative
:相对定位。如果对一个元素进行相对定位,将出现在它所在的位置上。然后,可以通过设置垂直或水平位置,使其“相对于”它的起点进行移动。使用相对定位时,无论是否移动,元素仍然占据原来的空间;移动元素会导致其覆盖其他元素。absolute
:绝对定位。元素的位置相对于最近的已定位的父元素,如果元素没有已定位的父元素,则相对于根元素(即 html 元素)定位。绝对定位的元素会脱离文档流,不占据空间,会与其他元素重叠。fixed
:固定定位。元素的位置相对于浏览器窗口是固定位置,即使窗口滚动它也不会移动。固定定位的元素会脱离文档流,不占据空间,会与其他元素重叠。sticky
:粘性定位。粘性定位可以被认为是相对定位和固定定位的混合,元素在跨越特定阈值前为相对定位,之后为固定定位。top,right,buttom,left,必须指定这四个阈值中的一个,才可以使粘性定位生效,否则行为与其相对定位相同。inherit
:规定应该从父元素继承 position 属性的值。
盒模型:box-sizing
盒模型都是由四个部分组成的,分别是margin
、border
、padding
和content
。
标准盒模型和IE盒模型的区别在于设置width
和height
时,对应的范围不同。
- 标准盒模型的
width
、height
只包含了content
- IE盒模型的的
width
、height
除了content
本身,还包含了border
、padding
通过修改元素的box-sizing
属性来改变元素的盒模型:
box-sizeing: content-box
表示标准盒模型(默认值)box-sizeing: border-box
表示IE盒模型(IE盒模型)inherit
,继承父元素的box-sizing
值。
BFC
(块级格式上下文)
- 概念:
BFC(Block Formatting Context)
,块级格式上下文。BFC
是CSS
布局的一个概念,是一个独立的渲染区域,规定了内部box
如何布局,且这个区域内的子元素不会影响到外面的元素。 - 布局规则:
- 内部的
box
会在垂直方向一个接一个的放置 box
垂直方向的距离由margin
决定,同一个BFC
相邻的box
的margin
会发生重叠- 每个 box 的 margin 左边,与包含块的左 border 相接触(对于从左往右的格式化,否则相反)
BFC
的区域不会与 float box 重叠BFC
是一个独立容器,容器内的子元素不会影响到外面的元素- 计算
BFC
高度时,浮动元素也参与计算高度
- 如何创建
BFC
?
- 根元素,即
html
元素 float
值不为none
position
值为absolute 或 fixed
display
的值为inline-block、tabl-cell、table-caption
overflow
的值不为visible
BFC
的使用场景
去除边距重叠问题
清除浮动(让父元素的高度包含子浮动元素)
阻止元素被浮动元素覆盖
让一个元素水平/垂直居中
水平居中
- 行内元素:
text-align: center;
- 对于
确定宽度的块级元素
- width 和 margin 实现:
mragin: 0 auto;
- 绝对定位和 margin-left 实现:
margin-left: (父width - 子 width)/2;
(前提是父元素相对定位)
- width 和 margin 实现:
- 对于
宽度未知的块级元素
- table 标签配合 margin 左右 auto 实现
- inline-block 实现:
display: inline-block; text-align: center;
- 绝对定位和 transform 实现, translateX 可以移动本身元素的50%
- flex 布局
justify-content: center
垂直居中
- 纯文字类,设置 line-height 等于 height
- 子绝父相,子元素通过 margin 实现自适应居中
- 子绝父相,通过位移 transform 实现
- flex 布局,
align-items: center;
- table 布局,父级通过转换为表格形式,子级设置 vertical-align 实现
flex 布局
flex
是一种弹性盒布局模型,给子元素提供了空间分布和对齐能力,由container
(容器)及item
(项目)组成。该布局模型提供了一种更加高效的方式来对容器中的项目进行布局、对齐和分配空间。适用于在不同尺寸的屏幕中创建可自动扩展和收缩布局,通常可用于水平/垂直居中
,两栏
、三栏布局
等的场景里。
常用的属性:
flex-direction
属性决定主轴的方向(即项目的排列方向)。flex-wrap
属性定义,如果一条轴线排不下,如何换行。flex-flow
属性是flex-direction
属性和flex-wrap
属性的简写形式,默认值为row nowrap
。justify-conten
t属性定义了项目在主轴上的对齐方式。align-items
属性定义项目在交叉轴上如何对齐。align-content
属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
其中flex
属性是flex-grow
,flex-shrink
和flex-basis
的简写,默认值为0 1 auto
。该属性有两个快捷值:auto (1 1 auto)
和 none (0 0 auto)
。
flex-grow
:定义项目的放大比例,默认值为 0,即如果存在剩余空间,也不放大。如果所有项目的flex-grow
属性都为 1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow
属性为 2,其他项目都为 1,则前者占据的剩余空间将比其他项多一倍。flex-shrink
:项目的缩小比例,默认为 1,即如果空间不足,项目将缩小。如果所有项目的flex-shrink
属性都为 1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink
属性为 0,其他项目都为 1,则空间不足时,前者不缩小。flex-basis
:定义了在分配多余空间之前,项目占据的主轴空间。浏览器会根据该属性,计算主轴是否有多余空间。它的默认值为 auto,即项目的本来大小。当设置为 0 的是,会根据内容撑开。也可以设为跟width
或height
属性一样的值(比如 350px),则项目将占据固定空间。
flex
常用的属性值:
- flex: 1 –> flex: 1 1 0%:
flex-grow flex-shrink flex-basis
- flex: 2 –> flex: 2 1 0:
flex-grow=2 flex-shrink flex-basis
- flex: auto –> flex: 1 1 auto
- flex: none –> flex: 0 0 auto【常用于固定尺寸不伸缩】
清除浮动
- 使用
clear:both
- 使用伪元素清除浮动:在父元素上面添加
::after
——-最推荐的做法
- 使用
overflow
属性:在父元素上面使用这个属性(hidden,auto,scroll
) - 使用
Flexbox布局或者Grid布局
css 中优雅降级和渐进增强有什么区别?
优雅降级和渐进增强是随着 css3
流出来的一个概念。由于低级浏览器不支持 css3, 但 css3 的效果又很优秀不忍放弃,所以在高级浏览器中使用 css3 ,而在低级浏览器只保证最基本的功能。二者最关键的区别是它们所侧重的内容,以及这种不同所造成的工作流程的差异。
优雅降级
:一开始就构建完整的功能,然后针对浏览器测试和修复。渐进增强
:一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能以达到更好的体验。
img 的 alt 和 title 的异同?实现图片懒加载的原理?
alt
是图片加载失败时显示在网页上的替代文字;title
是鼠标放在图片上面时显示的文字,是对图片的进一步描述和说明。alt
是 img 的必要属性;title
不是。- 对于网站 SEO 优先来说,搜索引擎对图片意思的判断,主要是靠
alt
属性,所以在图片alt
属性中以简要文字说明,同时包含关键字,也是页面优化的一部分。
懒加载原理
:先设置图片的 data-set
属性值(也可以是其他任意的,只要不发生 http 请求就可以,作用是为了存取值)为图片路径,由于不是 src
属性,故不会发生 http 请求。然后计算出页面的 scrollTop 的高度和浏览器的高度之和,如果图片距页面顶端距离小于前两者之和,说明图片要显示出来了,这时将 data-set
属性替换为 src
属性即可。
CSS主题切换
link标签动态引入
优点:
- 实现了按需加载,提高了首屏加载时的性能
缺点:
- 动态加载样式文件,如果文件过大网络情况不佳的情况下可能会有加载延迟,导致样式切换不流畅
- 如果主题样式表内定义不当,会有优先级问题
- 各个主题样式是写死的,后续针对某一主题样式表修改或者新增主题也很麻烦
提前引入所有主题样式,做类名切换
优点:
- 不用重新加载样式文件,在样式切换时不会有卡顿
缺点:
- 首屏加载时会牺牲一些时间加载样式资源
- 如果主题样式表内定义不当,也会有优先级问题
- 各个主题样式是写死的,后续针对某一主题样式表修改或者新增主题也很麻烦。
CSS变量+类名切换
优点:
- 不用重新加载样式文件,在样式切换时不会有卡顿
- 在需要切换主题的地方利用var()绑定变量即可,不存在优先级问题
- 新增或修改主题方便灵活,仅需新增或修改CSS变量即可,在var()绑定样式变量的地方就会自动更换
缺点:
- IE兼容性(忽略不计)
- 首屏加载时会牺牲一些时间加载样式资源
Vue3新特性(v-bind)
虽然这种方式存在局限性只能在Vue
开发中使用,但是为Vue
项目开发者做动态样式更改提供了又一个不错的方案。
优点:
- 不用重新加载样式文件,在样式切换时不会有卡顿
- 在需要切换主题的地方利用v-bind绑定变量即可,不存在优先级问题
- 新增或修改主题方便灵活,仅需新增或修改JS变量即可,在v-bind()绑定样式变量的地方就会自动更换
缺点:
- IE兼容性(忽略不计)
- 首屏加载时会牺牲一些时间加载样式资源
- 这种方式只要是在组件上绑定了动态样式的地方都会有对应的编译成哈希化的CSS变量,而不像方案3统一地就在:root上设置(不确定在达到一定量级以后的性能),也可能正是如此,Vue官方也并未采用此方式做全站的主题切换
SCSS + mixin + 类名切换
主要是运用SCSS的混合+CSS类名切换,其原理主要是将使用到mixin混合的地方编译为固定的CSS以后,再通过类名切换去做样式的覆盖。
优点:
- 不用重新加载样式文件,在样式切换时不会有卡顿
- 在需要切换主题的地方利用mixin混合绑定变量即可,不存在优先级问题
- 新增或修改主题方便灵活,仅需新增或修改SCSS变量即可,经过编译后会将所有主题全部编译出来
缺点:
- 首屏加载时会牺牲一些时间加载样式资源
CSS变量+动态setProperty
优点:
- 不用重新加载样式文件,在样式切换时不会有卡顿
- 仔细琢磨可以发现其原理跟方案4利用Vue3的新特性v-bind是一致的,只不过此方案只在
:root
上动态更改CSS变量而Vue3中会将CSS变量绑定到任何依赖该变量的节点上。 - 需要切换主题的地方只用在
:root
上动态更改CSS变量值即可,不存在优先级问题 - 新增或修改主题方便灵活
缺点:
- IE兼容性(忽略不计)
- 首屏加载时会牺牲一些时间加载样式资源(相对于前几种预设好的主题,这种方式的样式定义在首屏加载基本可以忽略不计)
CSS单位总结
rem:根节点
em:父节点
vh:视窗高度
vw:视窗宽度
px:像素点
块级元素和行内元素
块级元素
特性:
- 默认占据完整的容器宽度(即独占一行),无论其实际内容大小。
- 可以设置宽度(
width
)、高度(height
)、内边距(padding
)、边框(border
)和外边距(margin
)。 - 默认从新行开始,结束后也会创建一个新行。
常见的块级元素:
<div>
:通用容器元素,没有特定的语义含义。<p>
:段落元素。<h1>
、<h2>
、<h3>
、<h4>
、<h5>
、<h6>
:标题元素。<ol>
、<ul>
:有序和无序列表容器。<li>
:列表项元素。<table>
:表格元素。<header>
、<footer>
、<section>
、<article>
等:HTML5引入的语义化容器元素。
行内元素
特性:
- 宽度仅足够包围其内容,不能通过
width
和height
属性直接设置大小。 - 不会导致文本换行,通常用于文本或图片等内容内部,可以包含在块级元素内。
- 可以设置水平方向的内边距(
padding-left
、padding-right
)、边框和外边距,但垂直方向的内边距、边框和外边距可能不会影响布局。
- 宽度仅足够包围其内容,不能通过
常见的行内元素:
<span>
:通用的行内容器,没有特定的语义含义。<a>
:超链接元素。<img>
:图像元素。<strong>
、<em>
:文本强调元素。<br>
:换行元素。<input>
、<label>
:表单控件元素。
CSS中的display
属性
通过CSS的display
属性,可以改变元素的默认显示方式。例如,可以将行内元素显示为块级元素,反之亦然。
- 把行内元素转换为块级元素:
display: block;
- 把块级元素转换为行内元素:
display: inline;
- 把元素设为行内块级元素(inline-block),结合了行内元素和块级元素的特性:
display: inline-block;
了解和区分这两种元素的特性对于理解Web布局和实现精确的页面设计至关重要。
CSS sprites (雪碧图/精灵图)
css sprites 就是把网页中一些小图片整合到一张图片文件中,再利用 css 的 background-image、background-repeat、background-position 的组合进行背景定位。
优点: 减少图片体积;减少 http 请求次数
缺点:维护比较麻烦;不能随便改变大小,会失真模糊
什么是字体图标?
字体图标简单的说,就是一种特殊的字体,通过这种字体,显示给用户的就像一个个图片一样。字体图标最大的好处,在于它不会变形和加载速度快。字体图标可以像文字一样,随意通过 css 来控制它的大小和颜色,非常方便。
主流浏览器内核私有属性 css 前缀?
- mozilla(firefox、flock等): -moz
- webkit 内核(safari、chrome等): -webkit
- opera 内核(opera浏览器): -o
- trident 内核(ie 浏览器): -ms
如何放大图片并保证宽高比不变
只设置宽或高的其中一项,另一项设置为auto(或者不设置,默认就是auto),这样是不会改变图片宽高比的。
1 | img { |
使用 object-fit
,其中 cover
属性和 container
属性都可以保持宽高比不变,其区别在于
object-fit: cover;
:被替换的内容在保持其宽高比的同时填充元素的整个内容框。如果对象的宽高比与容器不同,那么该对象将被剪裁以填充容器。(容器内不会留下任何空白)object-fit: contain;
:被替换的内容在保持其宽高比的同时,将被缩放,并尽可能地将其内容在填充元素的内容框中。在保持宽高比的同时缩放图片,意味着某些方向上可能无法完全填充容器(即,如果图片的宽高比与容器的宽高比不同,那么会在容器的一个方向上留下空白)。
通过 zoom
或者 transform:scale
直接缩放图片
1 | img { |
移动端适配
在移动端开发中,适配不同的设备尺寸和分辨率是非常重要的一环。由于移动设备的屏幕大小、分辨率和像素密度差异较大,CSS 移动端适配的目标是确保网页在各种设备上都能提供良好的用户体验。以下是几种常见的移动端适配方案:
媒体查询(Media Queries)
媒体查询是最常见的移动端适配方式之一,通过定义不同的样式规则针对不同屏幕宽度、分辨率等条件进行适配。
1 | /* 针对小屏幕设备 */ |
- 优点:简单、灵活,可以根据设备尺寸、分辨率和屏幕方向等进行精细化适配。
- 缺点:当设备种类繁多时,需要编写大量的媒体查询规则,维护起来可能较为复杂。
弹性布局(Flexbox)
Flexbox 是 CSS 的一种布局模式,能够创建自适应的页面结构。通过 flex
属性,布局可以根据屏幕大小进行动态调整。
1 | .container { |
- 优点:布局灵活,能够很好的应对不同屏幕宽度的变化,常用于实现响应式网格布局。
- 缺点:需要对 Flexbox 布局模式有一定的了解。
视口单位(Viewport Units)
视口单位(vw
, vh
, vmin
, vmax
)是根据视口(viewport)尺寸来定义的相对单位,能够根据屏幕大小自动缩放。
1vw
:等于视口宽度的 1%。1vh
:等于视口高度的 1%。1vmin
:等于视口宽度和高度较小者的 1%。1vmax
:等于视口宽度和高度较大者的 1%。
1 | body { |
- 优点:自动根据视口大小调整元素的尺寸,适合创建适配性强的布局。
- 缺点:在某些特定场景下,过大的
vw
或vh
可能导致布局问题。
弹性盒模型(REM 和 EM 单位)
REM 和 EM 是相对单位,适用于实现自适应的字体和间距。rem
基于根元素(html
元素)的字体大小,而 em
基于父元素的字体大小。
1 | html { |
- 优点:能实现页面中不同部分基于根元素字体大小或父元素字体大小的相对调整,适合做整体响应式布局。
- 缺点:需要考虑不同的继承关系,使用不当可能导致层级复杂时调整困难。
百分比布局(Percentage Layouts)
使用 百分比 单位定义元素的宽度、间距等属性,使得元素能够相对于其父元素进行缩放。
1 | .container { |
- 优点:基于父容器的尺寸进行适配,能够自适应不同屏幕尺寸。
- 缺点:需要在多层嵌套的布局中处理好宽度和高度的百分比关系,否则可能出现布局不稳定。
栅格布局(Grid Layout)
CSS Grid 是一种强大的二维布局系统,能够轻松实现响应式的布局设计。通过定义网格,可以让元素自动根据屏幕宽度调整位置和大小。
1 | .container { |
- 优点:特别适合复杂的响应式布局,能够精确控制布局的各个部分。
- 缺点:浏览器支持需要较新版本,但现代浏览器已经普遍支持。
视口元标签(Viewport Meta Tag)
通过设置 <meta>
标签的 viewport
属性,可以控制页面的视口缩放,防止页面在移动端被默认放大。
1 | <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> |
**
width=device-width
**:设置视口宽度为设备屏幕宽度。**
initial-scale=1.0
**:设置页面的初始缩放比例为 1.0。**
maximum-scale=1.0
**:禁止用户放大页面。**
user-scalable=no
**:禁止用户手动缩放页面。优点:控制页面的缩放行为,防止页面在移动设备上出现不必要的缩放。
缺点:仅是设置页面的缩放属性,还需结合其他方案进行适配。
响应式图片(Responsive Images)
对于不同屏幕尺寸的设备,加载合适大小的图片可以显著优化性能。使用 HTML 的 <picture>
元素和 srcset
属性,可以提供不同尺寸的图片给不同的设备。
1 | <picture> |
- 优点:针对不同的屏幕分辨率提供合适的图片,减少不必要的资源浪费,提升页面性能。
- 缺点:需要额外生成多张不同尺寸的图片,增加了开发和维护的工作量。
动态 REM 设置(根据视口宽度动态调整 REM 基值)
通过 JavaScript 动态计算 rem
的基准值,使得 rem
单位能够根据视口宽度动态调整,适用于需要更精确控制页面比例的场景。
1 | (function() { |
- 优点:能够根据屏幕宽度动态调整字体大小和布局比例,保证页面在不同设备上保持一致的比例。
- 缺点:需要引入 JavaScript 来动态计算和更新,增加了页面复杂度。
移动端优先设计(Mobile-First Design)
移动端优先设计是一种设计策略,即首先设计适用于小屏幕设备的布局,再根据需要添加针对大屏幕设备的样式。结合媒体查询可以让设计更加简洁、可维护。
1 | /* 移动端优先设计 */ |
- 优点:简化了媒体查询的使用,减少了不必要的样式覆盖,适应了
移动端为主的设计趋势。
- 缺点:需要从设计和开发开始就贯彻移动端优先的原则。
总结
移动端适配需要根据具体需求选取合适的方案。对于大多数项目来说,媒体查询、视口元标签 和 弹性布局 是基础;而对于需要处理复杂布局的项目,CSS Grid 和 Flexbox 则提供了更灵活的方案。同时,响应式图片 和 动态 REM 也能在提升页面性能和用户体验上发挥重要作用。
选择适合的技术方案并进行合理组合,才能有效应对不同设备和屏幕尺寸的挑战。