Skip to main content

CSS 基础

1、 BFC 简介

BFCBlock Formatting Context 的缩写,中文翻译为 块格式化上下文。它是 Web 页面 CSS 渲染的一部分,是块级盒子布局中产生的区域。你可以将 BFC 可以理解为一个容器,里面的元素不会影响到容器外的布局。

BFC 的特点:

  • 内部元素不会影响外部元素: BFC 内部的元素不会溢出到 BFC 外部,也不会影响外部元素的布局。
  • 相邻元素的 margin 会重叠: BFC 内部的相邻块级元素,它们的 margin 会在垂直方向上进行重叠。
  • 包含浮动元素: BFC 可以包含浮动元素,并计算浮动元素的高度。

哪些元素是 BFC?:

  • 根元素 (<html>)
  • 设置了 overflowhiddenscrollauto 的元素
  • 绝对定位的元素 (position: absolute)
  • 浮动元素 (float: leftfloat: rightfloat: none)
  • Flexbox 布局容器 (display: flex)
  • 网格布局容器 (display: grid)

BFC 的应用:

  • 清除浮动: BFC 最常见的用法就是清除元素内部的浮动。只要把父元素设为 BFC,就可以清理子元素的浮动了。最常见的做法就是在父元素上设置 overflow: hidden 样式。
  • 垂直对齐元素: BFC 可以用来垂直对齐元素。例如,可以使用 BFC 来垂直对齐两侧的图片。
  • 制作响应式布局: BFC 可以用来制作响应式布局。例如,可以使用 BFC 来创建左右两栏布局,并使两栏在不同屏幕尺寸下保持宽度不变。

2、 居中为什么要使用 transform

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

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

3、 flex 布局

Flex布局的原理是将容器划分为两个轴:主轴和侧轴。主轴是子元素排列的方向,可以是水平方向或垂直方向。侧轴是垂直于主轴的方向。

4、 粘性布局

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

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

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

5、 space-between 和 space-around

6、 transition 和 animation 的属性

CSS3 中的 transitionanimation 都是用于创建动画效果的属性,但它们在使用方式和功能上存在一些差异。

6.1、 transition 属性

transition 属性用于指定元素在状态变化时如何平滑过渡。它可以控制以下四个方面:

  • transition-property: 指定要添加过渡效果的 CSS 属性。默认值为 all,表示所有可以动画演示的属性都可以触发动画效果。
  • transition-duration: 定义过渡效果花费的时间。默认值为 0。
  • transition-timing-function: 指定动画的速度曲线。默认值为 ease。
  • transition-delay: 指定动画开始之前的延迟时间。默认值为 0。

例如,以下代码将使元素在 0.5 秒内从蓝色过渡到红色:

.element {
transition: background-color 0.5s ease;
background-color: blue;
}

.element:hover {
background-color: red;
}

6.2、 animation 属性

animation 属性用于指定元素应该如何动画化。它包含以下子属性:

  • animation-name: 指定要应用的动画的名称。
  • animation-duration: 指定动画持续的时间。
  • animation-timing-function: 指定动画的速度曲线。
  • animation-delay: 指定动画开始之前的延迟时间。
  • animation-iteration-count: 指定动画播放的次数。默认值为 1,表示播放一次。
  • animation-direction: 指定动画的播放方向。默认值为 normal,表示正向播放。
  • animation-fill-mode: 指定动画在播放前后如何保持状态。默认值为 none,表示保持初始状态或最终状态。

例如,以下代码将使元素在 1 秒内旋转 360 度:

.element {
animation-name: spin;
animation-duration: 1s;
}

@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}

6.3、 区别

以下是 transitionanimation 的主要区别:

  • 应用场景: transition 通常用于元素状态变化时的隐式动画,例如鼠标悬停或元素获得焦点时。animation 则用于更复杂的动画效果,例如旋转、缩放或移动元素。
  • 控制力: transition 对动画效果的控制力较弱,只能控制过渡的持续时间、速度曲线和延迟时间。animation 则可以更精细地控制动画的各个方面,例如关键帧、播放次数、播放方向和填充模式。
  • 性能: transition 的性能通常优于 animation,因为它只需要在元素状态变化时触发动画。animation 则需要在动画播放期间不断更新元素的样式,因此可能会对性能造成影响。

在实际应用中,应根据具体需求选择合适的动画属性。如果只需要简单的过渡效果,可以使用 transition 属性。如果需要更复杂的动画效果,则可以使用 animation 属性。

7、 png8、png16、png32的区别

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 算法对图片进行编码。

8、 如何优化图片

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

9、 中伪类和伪元素的区别

伪类示例:

  • :hover:鼠标悬停在元素上面时
  • :link:未访问的链接
  • :visited:已访问的链接
  • :focus:元素获得焦点时
  • :active:元素被激活时
  • :first-child:元素是其父元素的第一个子元素
  • :last-child:元素是其父元素的最后一个子元素
  • :nth-child(n):元素是其父元素的第 n 个子元素

伪元素示例:

  • :before:在元素之前插入一个虚拟元素
  • :after:在元素之后插入一个虚拟元素
  • :first-line:元素的首行文本
  • :first-letter:元素的第一个字母
  • ::selection:选中的文本
  • ::placeholder:输入框的占位符文本

10、 选择器

CSS 选择器用于指定要应用样式的HTML元素。根据选择器的类型和复杂程度,CSS 选择器具有不同的优先级。优先级决定了在多个选择器同时应用时哪个选择器生效。

10.1、 优先级

选择器类型的优先级是递增的:

  • 类型选择器(例如,h1)和伪元素(例如,::before)
  • 类选择器(例如,.example),属性选择器(例如,[type="radio"])和伪类(例如,:hover
  • ID 选择器(例如,#example)。

10.2、 选择器的类型

  • 类型选择器:根据元素的类型选择元素,例如 h1pdiv 等。
  • ID 选择器:根据元素的 ID 选择元素,例如 #header#footer 等。
  • 类选择器:根据元素的类选择元素,例如 .main.nav 等。
  • 属性选择器:根据元素的属性选择元素,例如 a[href]img[alt] 等。
  • 伪类选择器:根据元素的状态选择元素,例如 :hover:link 等。
  • 伪元素选择器:选择元素的特定部分,例如 ::before::after 等。
  • 后代选择器:选择元素的所有后代元素,例如 div pul li 等。
  • 子代选择器:选择元素的直接子代元素,例如 div > pul > li 等。
  • 相邻兄弟选择器:选择元素的相邻兄弟元素,例如 p + spanli ~ ul 等。
  • 通用选择器:选择所有元素,例如 *

10.3、 优先级计算

优先级 = a * 1000 + b * 100 + c * 10 + d

其中:

  • a 是选择器中 ID 的数量。
  • b 是选择器中类、属性和伪类的数量。
  • c 是选择器中类型选择器和伪元素选择器的数量。
  • d 是选择器在样式表中的位置。

例如,选择器 #header.main 的优先级计算如下:

优先级 = 1 * 1000 + 1 * 100 + 0 * 10 + 0 = 1100

选择器 div.content:hover 的优先级计算如下:

优先级 = 0 * 1000 + 1 * 100 + 1 * 10 + 1 = 111

特殊情况:

  • !important 关键字可以强制提高选择器的优先级。
  • 行内样式的优先级高于所有外部样式表的样式。

11、 属性继承

可继承的属性

  1. 文字相关属性: font-family、font-size、font-weight、font-style 等。
  2. 颜色属性: color、background-color。
  3. 文本相关属性: line-height、text-align、text-transform 等。
  4. 链接相关属性: text-decoration、link、visited、hover、active 等。
  5. 列表属性: list-style-type、list-style-image 等。
  6. 表格属性: border-collapse、border-spacing 等。
  7. 元素显示属性: display、visibility。
  8. 百分比属性: 某些属性(如 padding、margin)中的百分比值可以继承。

12、 grid 布局

网格布局(Grid)是最强大的 CSS 布局方案。

Flex 布局是轴线布局,只能指定"项目"针对轴线的位置,可以看作是一维布局。Grid 布局则是将容器划分成"行"和"列",产生单元格,然后指定"项目所在"的单元格,可以看作是二维布局。Grid 布局远比 Flex 布局强大。

12.1、 示例

<style>
.box {
display: grid;
/* 指定了一个三行三列的网格,列宽和行高都是50px */
grid-template-columns: 50px 50px 50px;
grid-template-rows: 50px 50px 50px;
}

.item {
font-size: 2em;
text-align: center;
border: 1px solid #e5e4e9;
}

.item-1 {
background-color: #ef342a;
}

.item-2 {
background-color: #f68f26;
}

.item-3 {
background-color: #4ba946;
}

.item-4 {
background-color: #0376c2;
}

.item-5 {
background-color: #c077af;
}

.item-6 {
background-color: #f8d29d;
}

.item-7 {
background-color: #b5a87f;
}

.item-8 {
background-color: #d0e4a9;
}

.item-9 {
background-color: #4dc7ec;
}
</style>
<div class="box">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
<div class="item item-4">4</div>
<div class="item item-5">5</div>
<div class="item item-6">6</div>
<div class="item item-7">7</div>
<div class="item item-8">8</div>
<div class="item item-9">9</div>
</div>

12.2、 repeat函数

.box {
display: grid;
grid-template-columns: repeat(3,1fr);
grid-template-rows: repeat(3, 50px);
}

使用repeat可以免去重复写3个50px

查看效果

12.3、 固定一列宽度

.box {
display: grid;
grid-template-columns: 100px 1fr 1fr;
grid-template-rows: repeat(3, 50px);
}

12.4、 区间范围函数:minmax

.box {
display: grid;
grid-template-columns: minmax(300px, 1fr) 1fr 1fr;
grid-template-rows: repeat(3, 50px);
}

查看效果

12.5、 独立设置单元格的范围

设置起始边界范围

.item-1 {
background-color: #ef342a;
grid-column-start: 1;
grid-column-end: 4;
}

也可以使用如下缩写

.item-1 {
background-color: #ef342a;
grid-column: 1 / 4;
}

12.6、 grid-area控制单元格范围

使用 grid-area 实现博客的经典布局

.box {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 1fr 3fr 1fr;
height: 100%;
grid-template-areas:
"h h h h h h h h h h h h"
"s s c c c c c c c c c c"
"f f f f f f f f f f f f";
}

.item {
font-size: 2em;
text-align: center;
border: 1px solid #333;
}

.item-1 {
background-color: #ef342a;
grid-area: h;
}

.item-2 {
background-color: #f68f26;
grid-area: s;
}

.item-3 {
background-color: #4ba946;
grid-area: c;
}

.item-4 {
background-color: #0376c2;
grid-area: f;
}

13、 Flex 弹性布局