CSS-重新学习-20260407

3 阅读7分钟

CSS

一、CSS 选择器与优先级

1. CSS 选择器类型及优先级计算

问题:CSS 选择器有哪些类型?优先级如何计算?哪些属性可以继承?

答案CSS 选择器类型

  1. 基础选择器

    • 元素选择器:p { }
    • 类选择器:.class { }
    • ID选择器:#id { }
    • 通配符选择器:* { }
  2. 属性选择器

    • [attr]:具有指定属性
    • [attr=value]:属性等于特定值
    • [attr^=value]:属性以特定值开头
    • [attr$=value]:属性以特定值结尾
    • [attr*=value]:属性包含特定值
  3. 伪类选择器

    • 状态伪类::hover, :focus, :active, :visited, :checked
    • 结构伪类::first-child, :last-child, :nth-child(n), :nth-of-type(n)
    • 表单伪类::required, :optional, :valid, :invalid
  4. 伪元素选择器

    • ::before, ::after:生成内容
    • ::first-line, ::first-letter:文本首行/首字母
    • ::selection:用户选中部分
  5. 组合选择器

    • 后代选择器:div p
    • 子元素选择器:div > p
    • 相邻兄弟选择器:h1 + p
    • 通用兄弟选择器:h1 ~ p
    • 并集选择器:h1, h2, h3

优先级计算规则: 优先级由4个级别组成(a, b, c, d):

  • a:行内样式(1,0,0,0)
  • b:ID选择器数量(0,1,0,0)
  • c:类/属性/伪类选择器数量
  • d:元素/伪元素选择器数量

计算示例

#header .nav li.active a:hover { }
/* 计算:0,1,3,2 → 优先级:0,1,3,2 */

body div#main .content p { }
/* 计算:0,1,1,3 → 优先级:0,1,1,3 */

!important 规则

p { color: red !important; } /* 最高优先级 */

可继承属性

  1. 文本相关color, font-family, font-size, font-weight, line-height, text-align, text-indent
  2. 列表相关list-style-type, list-style-image
  3. 表格相关border-collapse, border-spacing
  4. 其他visibility, cursor, direction, letter-spacing, word-spacing

不可继承属性

  • 盒模型属性:width, height, margin, padding, border
  • 定位属性:position, top, left, float, display
  • 背景属性:background, background-color, background-image

代码示例

/* 优先级演示 */
#header .nav a { color: blue; }    /* 0,1,1,1 */
.header nav a { color: green; }    /* 0,0,2,1 */
nav a { color: red; }              /* 0,0,0,2 */
a { color: black; }                /* 0,0,0,1 */

/* 继承演示 */
.parent {
  color: #333;
  font-family: Arial;
  line-height: 1.5;
}
.child {
  /* 自动继承父级的 color, font-family, line-height */
  border: 1px solid #ccc; /* 需明确设置 */
}

补充说明

  • 避免过度使用ID选择器和!important
  • 使用类选择器提高可复用性
  • 合理使用继承减少代码重复
  • 了解CSS层叠规则:重要性 > 来源 > 优先级 > 位置

二、盒模型

2. 盒模型详解与 box-sizing

问题:CSS 盒模型是什么?包含哪些部分?W3C标准盒模型与IE盒模型区别?box-sizing属性的作用?

答案盒模型定义:CSS将每个元素视为一个矩形盒子,包含内容、内边距、边框、外边距。

盒模型组成

  1. 内容区域:width × height
  2. 内边距:padding
  3. 边框:border
  4. 外边距:margin

两种盒模型对比

模型计算方式总宽度公式特点
W3C标准盒模型 (content-box)width仅包含内容总宽度 = width + padding + border + margin默认值,符合CSS标准
IE盒模型 (border-box)width包含内容+padding+border总宽度 = width + margin更直观,易于布局控制

可视化表示

/* content-box (默认) */
元素总宽度 = width(200) + padding(20×2) + border(2×2) + margin(10×2) = 264px
内容宽度 = 200px

/* border-box */
元素总宽度 = width(200) + margin(10×2) = 220px
内容宽度 = 200 - padding(20×2) - border(2×2) = 156px

box-sizing 属性

/* 默认值:标准盒模型 */
.element {
  box-sizing: content-box;
  width: 200px;
  padding: 20px;
  border: 2px solid;
  /* 实际宽度 = 200 + 40 + 4 = 244px */
}

/* border-box:IE盒模型 */
.element {
  box-sizing: border-box;
  width: 200px;
  padding: 20px;
  border: 2px solid;
  /* 实际宽度 = 200px,内容宽度 = 200 - 40 - 4 = 156px */
}

/* 全局设置 */
* {
  box-sizing: border-box;
}

盒模型计算示例

div {
  width: 300px;
  height: 200px;
  padding: 20px;
  border: 5px solid #333;
  margin: 15px;
  box-sizing: border-box;
}

/* 计算:
   内容宽度 = 300 - (20×2) - (5×2) = 250px
   内容高度 = 200 - (20×2) - (5×2) = 150px
   总宽度 = 300 + (15×2) = 330px
   总高度 = 200 + (15×2) = 230px
*/

实际应用场景

  1. 栅格系统
.grid-item {
  box-sizing: border-box;
  float: left;
  width: 33.33%;
  padding: 15px;
  /* 精确的三栏布局,不考虑padding影响 */
}
  1. 表单元素
input, textarea, select {
  box-sizing: border-box;
  width: 100%;
  padding: 8px 12px;
  border: 1px solid #ddd;
  /* 宽度包含padding和border,避免溢出 */
}
  1. 响应式设计
.container {
  box-sizing: border-box;
  max-width: 1200px;
  padding: 0 20px;
  margin: 0 auto;
  /* 容器宽度包含padding,便于响应式计算 */
}

浏览器兼容性

  • IE8+ 支持 box-sizing: border-box
  • 现代浏览器完全支持
  • 建议使用前缀增强兼容性:
.element {
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
}

最佳实践

  1. 全局设置
/* 重置盒模型 */
*, *::before, *::after {
  box-sizing: border-box;
}

/* 特殊情况使用content-box */
img, video, iframe {
  box-sizing: content-box;
}
  1. Flexbox和Grid布局
/* 默认使用border-box更直观 */
.container {
  display: flex;
  box-sizing: border-box;
}

.item {
  flex: 1;
  padding: 20px;
  /* 宽度计算包含padding */
}
  1. CSS自定义属性
:root {
  --box-model: border-box;
}

.element {
  box-sizing: var(--box-model);
}

常见问题解决

  1. 元素溢出
/* 问题:padding使元素溢出容器 */
.container { width: 100%; }

/* 解决方案:使用border-box */
.container { 
  width: 100%;
  box-sizing: border-box;
  padding: 20px;
}
  1. 等宽布局
/* 传统方案:计算复杂 */
.col {
  float: left;
  width: 25%;        /* 期望25% */
  padding: 10px;     /* 破坏宽度 */
  border: 1px solid;
}

/* border-box方案:简单直观 */
.col {
  float: left;
  width: 25%;
  box-sizing: border-box;
  padding: 10px;     /* 包含在25%内 */
  border: 1px solid;
}
  1. 响应式图片
img {
  max-width: 100%;
  height: auto;
  box-sizing: content-box; /* 图片通常使用content-box */
}

性能考虑

  • box-sizing 不会影响渲染性能
  • 重排/重绘优化:减少盒模型属性变更
  • 硬件加速:使用transform替代width/height动画

补充说明

  • 理解盒模型是CSS布局的基础
  • 根据项目需求选择合适的盒模型
  • 使用开发者工具检查盒模型计算
  • 结合现代布局技术(Flexbox/Grid)使用

三、Flexbox 布局

3. Flex 布局原理与应用

问题:Flex 布局的原理及使用场景?Flex 容器和项目属性有哪些?Flex 布局是如何工作的?

答案Flexbox 概述:Flexible Box布局模型,用于一维布局(行或列),提供更有效的方式分配容器内项目的空间。

核心概念

  1. Flex容器display: flexdisplay: inline-flex
  2. Flex项目:容器的直接子元素
  3. 主轴:项目的排列方向(默认水平)
  4. 交叉轴:与主轴垂直的方向

Flex容器属性

  1. display
.container {
  display: flex; /* 块级Flex容器 */
  display: inline-flex; /* 行内Flex容器 */
}
  1. flex-direction(主轴方向):
.container {
  flex-direction: row; /* 默认:水平方向,起点在左端 */
  flex-direction: row-reverse; /* 水平方向,起点在右端 */
  flex-direction: column; /* 垂直方向,起点在上端 */
  flex-direction: column-reverse; /* 垂直方向,起点在下端 */
}
  1. flex-wrap(换行):
.container {
  flex-wrap: nowrap; /* 默认:不换行 */
  flex-wrap: wrap; /* 换行,第一行在上方 */
  flex-wrap: wrap-reverse; /* 换行,第一行在下方 */
}
  1. flex-flow(简写):
.container {
  flex-flow: row nowrap; /* flex-direction 和 flex-wrap 的简写 */
}
  1. justify-content(主轴对齐):
.container {
  justify-content: flex-start; /* 默认:起点对齐 */
  justify-content: flex-end; /* 终点对齐 */
  justify-content: center; /* 居中对齐 */
  justify-content: space-between; /* 两端对齐,项目间间隔相等 */
  justify-content: space-around; /* 每个项目两侧间隔相等 */
  justify-content: space-evenly; /* 项目与项目、项目与边框间隔相等 */
}
  1. align-items(交叉轴对齐):
.container {
  align-items: stretch; /* 默认:拉伸占满容器高度 */
  align-items: flex-start; /* 起点对齐 */
  align-items: flex-end; /* 终点对齐 */
  align-items: center; /* 居中对齐 */
  align-items: baseline; /* 基线对齐 */
}
  1. align-content(多行对齐):
.container {
  align-content: stretch; /* 默认:拉伸占满容器 */
  align-content: flex-start; /* 起点对齐 */
  align-content: flex-end; /* 终点对齐 */
  align-content: center; /* 居中对齐 */
  align-content: space-between; /* 两端对齐 */
  align-content: space-around; /* 每个项目两侧间隔相等 */
}

Flex项目属性

  1. order(排序):
.item {
  order: 0; /* 默认:按照HTML顺序 */
  order: 1; /* 数值越大,排列越靠后 */
}
  1. flex-grow(放大比例):
.item {
  flex-grow: 0; /* 默认:不放大 */
  flex-grow: 1; /* 有剩余空间时,项目放大 */
}
  1. flex-shrink(缩小比例):
.item {
  flex-shrink: 1; /* 默认:空间不足时,项目缩小 */
  flex-shrink: 0; /* 空间不足时,不缩小 */
}
  1. flex-basis(基准大小):
.item {
  flex-basis: auto; /* 默认:项目原本大小 */
  flex-basis: 100px; /* 设置基准宽度 */
  flex-basis: 50%; /* 百分比基准 */
  flex-basis: 0; /* 无内容影响的基础大小 */
}
  1. flex(简写):
.item {
  flex: none; /* 0 0 auto,不伸缩 */
  flex: auto; /* 1 1 auto,自动填充 */
  flex: 1; /* 1 1 0%,等分剩余空间 */
  flex: 0 0 200px; /* 固定200px,不伸缩 */
}
  1. align-self(项目自身对齐):
.item {
  align-self: auto; /* 默认:继承align-items */
  align-self: flex-start; /* 起点对齐 */
  align-self: flex-end; /* 终点对齐 */
  align-self: center; /* 居中对齐 */
  align-self: stretch; /* 拉伸 */
}

Flex布局工作原理

  1. 分配空间

    • 计算剩余空间 = 容器大小 - 所有项目flex-basis总和
    • 根据flex-grow分配剩余空间
    • 空间不足时根据flex-shrink缩小项目
  2. 对齐项目

    • 主轴对齐:justify-content
    • 交叉轴对齐:align-items / align-self
    • 多行对齐:align-content

常见布局模式

  1. 水平居中
.container {
  display: flex;
  justify-content: center;
}
  1. 垂直居中
.container {
  display: flex;
  align-items: center;
}
  1. 完全居中
.container {
  display: flex;
  justify-content: center;
  align-items: center;
}
  1. 圣杯布局
.container {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.header {
  flex: 0 0 auto;
}

.main {
  flex: 1 0 auto;
  display: flex;
}

.content {
  flex: 1;
}

.sidebar {
  flex: 0 0 200px;
}

.footer {
  flex: 0 0 auto;
}
  1. 等分导航
.nav {
  display: flex;
}

.nav-item {
  flex: 1;
  text-align: center;
}
  1. 流式布局
.container {
  display: flex;
  flex-wrap: wrap;
}

.item {
  flex: 1 0 200px; /* 最小200px,自动换行 */
  margin: 10px;
}
  1. 输入组
.input-group {
  display: flex;
}

.input-group input {
  flex: 1;
}

.input-group button {
  flex: 0 0 auto;
}

使用场景

  1. 导航栏:水平/垂直导航,响应式菜单
  2. 卡片布局:等高卡片,流式排列
  3. 表单布局:标签对齐,按钮组
  4. 媒体对象:图片+文字组合
  5. 网格系统:响应式栅格
  6. 居中内容:水平和垂直居中
  7. 页面布局:头部、内容、页脚

Flexbox vs 传统布局

需求传统方案Flexbox方案
垂直居中定位 + transformalign-items: center
等分布局float + 计算宽度flex: 1
等高列JS计算高度align-items: stretch
顺序控制修改HTMLorder属性
自适应空间媒体查询flex-grow/flex-shrink

浏览器兼容性

  • IE10+ 部分支持(需-ms-前缀)
  • IE11+ 较好支持
  • 现代浏览器完全支持
  • 前缀使用:
.container {
  display: -webkit-flex; /* Safari */
  display: -ms-flexbox;  /* IE10 */
  display: flex;         /* 标准 */
}

性能考虑

  • Flexbox渲染性能优于传统浮动布局
  • 避免过度嵌套Flex容器
  • 使用flex-basis替代width/height
  • 硬件加速优化动画

补充说明

  • 理解主轴和交叉轴概念
  • 合理使用flex简写属性
  • 结合Grid布局实现复杂二维布局
  • 使用开发者工具调试Flexbox

四、Grid 布局

4. Grid 布局特点与应用场景

问题:Grid 布局的特点和应用场景是什么?Grid 布局如何工作?

答案CSS Grid 概述:二维网格布局系统,可同时处理行和列,适合复杂布局。

核心概念

  1. Grid容器display: griddisplay: inline-grid
  2. Grid项目:容器的直接子元素
  3. 网格线:划分网格的线条
  4. 网格轨道:行或列
  5. 网格单元格:行和列的交叉区域
  6. 网格区域:一个或多个单元格组成的矩形区域

Grid容器属性

  1. grid-template-columns / grid-template-rows
.container {
  /* 定义3列:100px 自适应 200px */
  grid-template-columns: 100px 1fr 200px;
  
  /* 定义2行:100px 自适应 */
  grid-template-rows: 100px 1fr;
  
  /* repeat()函数 */
  grid-template-columns: repeat(3, 1fr); /* 3等分 */
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  
  /* 命名网格线 */
  grid-template-columns: [start] 1fr [middle] 1fr [end];
}
  1. grid-template-areas
.container {
  grid-template-areas:
    "header header header"
    "sidebar content content"
    "footer footer footer";
}
.item-header { grid-area: header; }
.item-sidebar { grid-area: sidebar; }
.item-content { grid-area: content; }
.item-footer { grid-area: footer; }
  1. grid-template(简写):
.container {
  grid-template:
    "header header" 80px
    "sidebar content" 1fr
    "footer footer" 60px
    / 200px 1fr; /* 列定义 */
}
  1. gap(间距):
.container {
  gap: 20px; /* 行和列间距20px */
  row-gap: 10px; /* 行间距 */
  column-gap: 15px; /* 列间距 */
}
  1. justify-items / align-items
.container {
  justify-items: stretch; /* 默认:水平拉伸 */
  align-items: stretch; /* 默认:垂直拉伸 */
  justify-items: center; /* 水平居中 */
  align-items: center; /* 垂直居中 */
}
  1. justify-content / align-content
.container {
  justify-content: start; /* 水平对齐 */
  align-content: start; /* 垂直对齐 */
}
  1. grid-auto-columns / grid-auto-rows
.container {
  grid-auto-rows: 100px; /* 隐式行高 */
  grid-auto-columns: 1fr; /* 隐式列宽 */
}
  1. grid-auto-flow
.container {
  grid-auto-flow: row; /* 默认:按行排列 */
  grid-auto-flow: column; /* 按列排列 */
  grid-auto-flow: dense; /* 密集排列,填充空白 */
}

Grid项目属性

  1. grid-column / grid-row
.item {
  /* 跨2列 */
  grid-column: span 2;
  
  /* 指定位置:从第2列到第4列 */
  grid-column: 2 / 4;
  
  /* 命名网格线 */
  grid-column: start / middle;
  
  /* 简写 */
  grid-area: 1 / 1 / 3 / 3; /* row-start / column-start / row-end / column-end */
}
  1. grid-area
.item {
  /* 指定区域 */
  grid-area: 2 / 2 / 4 / 4;
  
  /* 使用命名区域 */
  grid-area: content;
}
  1. justify-self / align-self
.item {
  justify-self: start; /* 项目水平对齐 */
  align-self: center; /* 项目垂直对齐 */
}

Grid布局特点

  1. 二维布局:同时控制行和列
  2. 精确控制:任意项目可放置在任何位置
  3. 响应式设计:易于创建响应式网格
  4. 区域命名:直观的布局定义
  5. 对齐控制:强大的对齐功能
  6. 间距控制:内置gap属性

应用场景

  1. 网页整体布局
.container {
  display: grid;
  grid-template:
    "header header header" 80px
    "nav    main   aside"  1fr
    "footer footer footer" 60px
    / 200px 1fr 200px;
  min-height: 100vh;
}
  1. 卡片网格
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 20px;
}
  1. 表单布局
.form {
  display: grid;
  grid-template-columns: 120px 1fr;
  gap: 15px;
  align-items: center;
}

.form label {
  text-align: right;
}
  1. 杂志式布局
.magazine {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(3, 200px);
  gap: 10px;
}

.featured {
  grid-column: span 2;
  grid-row: span 2;
}
  1. 仪表盘
.dashboard {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 20px;
}

Grid vs Flexbox

特性GridFlexbox
维度二维(行和列)一维(行或列)
方向同时控制行列单一方向
对齐更强大的对齐控制基本的对齐功能
定位任意定位项目顺序流排列
使用场景整体布局、复杂网格组件内部、一维布局

实际项目示例

示例1:响应式网格系统

.grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 20px;
}

.col-4 { grid-column: span 4; }
.col-6 { grid-column: span 6; }
.col-12 { grid-column: span 12; }

/* 响应式 */
@media (max-width: 768px) {
  .col-4, .col-6 { grid-column: span 12; }
}

示例2:瀑布流布局

.masonry {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  grid-auto-rows: 50px; /* 基础行高 */
  gap: 15px;
}

.item {
  /* 随机高度效果 */
  grid-row: span var(--row-span, 2); /* 自定义属性控制 */
}

示例3:棋盘布局

.chessboard {
  display: grid;
  grid-template-columns: repeat(8, 60px);
  grid-template-rows: repeat(8, 60px);
  gap: 0;
}

.square {
  width: 60px;
  height: 60px;
}

.square:nth-child(16n + 1),
.square:nth-child(16n + 3),
.square:nth-child(16n + 5),
.square:nth-child(16n + 7),
.square:nth-child(16n + 10),
.square:nth-child(16n + 12),
.square:nth-child(16n + 14),
.square:nth-child(16n + 16) {
  background: #000;
}

浏览器兼容性

  • IE10-11:部分支持(旧语法)
  • Edge 16+、Chrome 57+、Firefox 52+、Safari 10.1+:完全支持
  • 前缀使用:
.container {
  display: -ms-grid; /* IE10-11 */
  display: grid;     /* 标准 */
}

性能优化

  • 避免过度复杂的网格定义
  • 使用 grid-template-areas 提高可读性
  • 结合CSS自定义属性动态调整网格
  • 考虑移动端性能

补充说明

  • Grid适合整体页面布局
  • Flexbox适合组件内部布局
  • 两者可结合使用
  • 使用开发者工具调试网格线
  • 学习Grid命名和区域功能提高效率

五、响应式设计

5. 响应式设计实现方法

问题:如何实现移动端适配?响应式设计如何实现?媒体查询的使用方法?

答案响应式设计原则

  1. 移动优先:先设计移动端,再逐步增强
  2. 流体网格:使用百分比而非固定宽度
  3. 弹性图片:图片随容器缩放
  4. 媒体查询:根据设备特性应用不同样式

核心实现方法

1. 媒体查询

/* 基础样式(移动端) */
body { font-size: 14px; }

/* 平板设备 */
@media (min-width: 768px) {
  body { font-size: 16px; }
}

/* 桌面设备 */
@media (min-width: 1024px) {
  body { font-size: 18px; }
}

/* 断点系统 */
/* 移动端:< 768px */
/* 平板:768px - 1023px */
/* 桌面:≥ 1024px */

2. 视口设置

<meta name="viewport" content="width=device-width, initial-scale=1">

3. 流体网格

.container {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
}

.col {
  float: left;
  width: 100%; /* 移动端:单列 */
}

@media (min-width: 768px) {
  .col { width: 50%; } /* 平板:双列 */
}

@media (min-width: 1024px) {
  .col { width: 25%; } /* 桌面:四列 */
}

4. 弹性图片

img, video {
  max-width: 100%;
  height: auto;
}

/* 背景图片响应式 */
.banner {
  background-image: url('banner-small.jpg');
  background-size: cover;
}

@media (min-width: 768px) {
  .banner {
    background-image: url('banner-medium.jpg');
  }
}

@media (min-width: 1200px) {
  .banner {
    background-image: url('banner-large.jpg');
  }
}

5. 断点定义策略

// 常用断点
$breakpoints: (
  'xs': 320px,   // 小手机
  'sm': 576px,   // 大手机
  'md': 768px,   // 平板
  'lg': 992px,   // 小桌面
  'xl': 1200px,  // 大桌面
  'xxl': 1400px  // 超大桌面
);

// 混合宏
@mixin respond-to($breakpoint) {
  @if map-has-key($breakpoints, $breakpoint) {
    @media (min-width: map-get($breakpoints, $breakpoint)) {
      @content;
    }
  }
}

// 使用
.container {
  padding: 1rem;
  
  @include respond-to('md') {
    padding: 2rem;
  }
}

6. 响应式布局技术

Flexbox响应式

.container {
  display: flex;
  flex-wrap: wrap;
}

.item {
  flex: 1 0 100%; /* 移动端:单列 */
}

@media (min-width: 768px) {
  .item {
    flex: 1 0 50%; /* 平板:双列 */
  }
}

@media (min-width: 1024px) {
  .item {
    flex: 1 0 25%; /* 桌面:四列 */
  }
}

Grid响应式

.container {
  display: grid;
  grid-template-columns: 1fr; /* 移动端:单列 */
  gap: 20px;
}

@media (min-width: 768px) {
  .container {
    grid-template-columns: repeat(2, 1fr); /* 平板:双列 */
  }
}

@media (min-width: 1024px) {
  .container {
    grid-template-columns: repeat(3, 1fr); /* 桌面:三列 */
  }
}

7. 响应式字体

/* 基础字体 */
body { font-size: 14px; }

/* 视口单位 */
h1 {
  font-size: clamp(1.5rem, 5vw, 3rem);
}

/* 媒体查询调整 */
@media (min-width: 768px) {
  body { font-size: 16px; }
  h1 { font-size: 2.5rem; }
}

@media (min-width: 1200px) {
  body { font-size: 18px; }
  h1 { font-size: 3rem; }
}

8. 响应式图片技术

srcset 和 sizes

<img src="image-800.jpg"
     srcset="image-400.jpg 400w,
             image-800.jpg 800w,
             image-1200.jpg 1200w"
     sizes="(max-width: 480px) 400px,
            (max-width: 1024px) 800px,
            1200px"
     alt="响应式图片">

picture 元素

<picture>
  <source media="(min-width: 1200px)" 
          srcset="large.jpg">
  <source media="(min-width: 768px)" 
          srcset="medium.jpg">
  <source media="(max-width: 767px)" 
          srcset="small.jpg">
  <img src="fallback.jpg" alt="描述">
</picture>

9. 响应式表格

/* 移动端表格:转为块状 */
@media (max-width: 767px) {
  table.responsive {
    display: block;
  }
  
  table.responsive thead {
    display: none;
  }
  
  table.responsive tbody,
  table.responsive tr,
  table.responsive td {
    display: block;
  }
  
  table.responsive td {
    padding: 10px;
    border: none;
    border-bottom: 1px solid #eee;
    position: relative;
    padding-left: 50%;
  }
  
  table.responsive td::before {
    content: attr(data-label);
    position: absolute;
    left: 10px;
    width: 45%;
    padding-right: 10px;
    font-weight: bold;
    text-align: left;
  }
}

10. 响应式导航

汉堡菜单模式

/* 移动端:隐藏菜单,显示汉堡按钮 */
.nav-menu {
  display: none;
}

.menu-toggle {
  display: block;
}

/* 桌面端:显示菜单,隐藏汉堡按钮 */
@media (min-width: 768px) {
  .nav-menu {
    display: flex;
  }
  
  .menu-toggle {
    display: none;
  }
}

/* 汉堡按钮样式 */
.hamburger {
  width: 30px;
  height: 3px;
  background: #333;
  position: relative;
}

.hamburger::before,
.hamburger::after {
  content: '';
  position: absolute;
  width: 30px;
  height: 3px;
  background: #333;
}

.hamburger::before { top: -8px; }
.hamburger::after { top: 8px; }

11. 响应式实用类

/* 显示/隐藏类 */
.hidden-mobile {
  display: none;
}

.hidden-desktop {
  display: block;
}

@media (min-width: 768px) {
  .hidden-mobile {
    display: block;
  }
  
  .hidden-desktop {
    display: none;
  }
}

/* 间距调整 */
.p-1 { padding: 0.5rem; }
.p-2 { padding: 1rem; }

@media (min-width: 768px) {
  .p-md-3 { padding: 1.5rem; }
  .p-md-4 { padding: 2rem; }
}

12. 响应式设计测试要点

  1. 设备测试

    • 真实设备测试
    • 模拟器测试
    • 浏览器开发者工具
  2. 断点测试

    • 检查每个断点的布局
    • 过渡区域测试
    • 横屏/竖屏测试
  3. 性能测试

    • 移动端加载速度
    • 图片优化
    • 代码分割
  4. 可用性测试

    • 触摸目标大小
    • 字体可读性
    • 导航易用性

13. 现代响应式技术

容器查询

.card-container {
  container-type: inline-size;
}

@container (min-width: 400px) {
  .card {
    display: flex;
    flex-direction: row;
  }
}

CSS自定义属性

:root {
  --base-font-size: 14px;
  --container-width: 100%;
}

@media (min-width: 768px) {
  :root {
    --base-font-size: 16px;
    --container-width: 720px;
  }
}

.container {
  width: var(--container-width);
  font-size: var(--base-font-size);
}

补充说明

  • 移动优先设计简化开发流程
  • 使用相对单位(em, rem, %, vw, vh)
  • 测试所有目标设备
  • 关注核心性能指标(LCP, FID, CLS)
  • 渐进增强,优雅降级

六、CSS 动画与过渡

6. animation、transition、transform 区别与应用

问题:CSS 动画与过渡的区别?如何使用 CSS3 实现动画?animation、transition、transform 有什么区别?

答案三者的核心区别

特性transitiontransformanimation
作用状态过渡元素变换复杂动画
触发需要事件触发立即应用自动或触发
控制简单过渡静态变换多关键帧
循环不支持循环不支持循环支持循环
关键帧仅开始结束无关键帧多关键帧
性能优秀优秀(硬件加速)优秀

详细说明

1. transition(过渡)

.element {
  /* 定义过渡 */
  transition: property duration timing-function delay;
  
  /* 示例:所有属性过渡0.3秒 */
  transition: all 0.3s ease;
  
  /* 多个属性不同过渡 */
  transition: 
    width 0.3s ease,
    height 0.5s ease-in-out,
    opacity 0.2s linear;
}

.element:hover {
  width: 200px; /* 触发过渡 */
  opacity: 0.8;
}

可过渡属性

  • 尺寸:width, height, max-width, etc.
  • 颜色:color, background-color, border-color
  • 位置:top, left, right, bottom
  • 变换:transform
  • 其他:opacity, visibility, box-shadow

2. transform(变换)

.element {
  /* 2D变换 */
  transform: translate(100px, 50px); /* 位移 */
  transform: rotate(45deg);          /* 旋转 */
  transform: scale(1.5);             /* 缩放 */
  transform: skew(20deg, 10deg);     /* 倾斜 */
  
  /* 3D变换 */
  transform: translate3d(0, 0, 100px);
  transform: rotate3d(1, 1, 1, 45deg);
  transform: scale3d(1.5, 1.5, 1.5);
  
  /* 多重变换 */
  transform: translate(50px, 50px) rotate(45deg) scale(1.2);
  
  /* 变换原点 */
  transform-origin: 0 0; /* 左上角 */
  transform-origin: center; /* 中心 */
}

3. animation(动画)

/* 定义关键帧 */
@keyframes slide-in {
  0% {
    transform: translateX(-100%);
    opacity: 0;
  }
  60% {
    transform: translateX(20px);
  }
  100% {
    transform: translateX(0);
    opacity: 1;
  }
}

/* 应用动画 */
.element {
  animation-name: slide-in;
  animation-duration: 0.5s;
  animation-timing-function: ease-out;
  animation-delay: 0.2s;
  animation-iteration-count: 1;
  animation-direction: normal;
  animation-fill-mode: forwards;
  animation-play-state: running;
  
  /* 简写 */
  animation: slide-in 0.5s ease-out 0.2s 1 normal forwards;
}

/* 多个动画 */
.element {
  animation: 
    slide-in 0.5s ease-out,
    fade-in 0.3s ease-in;
}

动画属性详解

  • animation-name:关键帧名称
  • animation-duration:动画时长
  • animation-timing-function:时间函数
    • linear:匀速
    • ease:慢快慢(默认)
    • ease-in:慢开始
    • ease-out:慢结束
    • ease-in-out:慢开始慢结束
    • cubic-bezier:贝塞尔曲线
  • animation-delay:延迟开始
  • animation-iteration-count:重复次数
    • 数字:1, 2, 3
    • infinite:无限循环
  • animation-direction:播放方向
    • normal:正常播放
    • reverse:反向播放
    • alternate:交替播放
    • alternate-reverse:反向交替
  • animation-fill-mode:动画前后样式
    • none:默认
    • forwards:保留最后帧
    • backwards:应用第一帧
    • both:前后都应用
  • animation-play-state:播放状态
    • running:运行中
    • paused:暂停

性能优化

  1. 使用transform和opacity
/* 性能好(硬件加速) */
.element {
  transform: translateX(100px);
  opacity: 0.5;
}

/* 性能差(触发重排) */
.element {
  left: 100px;
  width: 200px;
}
  1. will-change 提示
.element {
  will-change: transform, opacity;
}
  1. 减少动画数量
/* 避免过多同时动画 */
.container:hover .element {
  animation: bounce 0.3s;
}

实际应用示例

示例1:按钮悬停效果

.btn {
  background: #4285f4;
  color: white;
  padding: 12px 24px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.btn:hover {
  background: #3367d6;
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}

.btn:active {
  transform: translateY(0);
  transition-duration: 0.1s;
}

示例2:加载动画

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

.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid rgba(0,0,0,0.1);
  border-left-color: #4285f4;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

示例3:卡片入场动画

@keyframes card-enter {
  0% {
    opacity: 0;
    transform: translateY(30px) scale(0.95);
  }
  100% {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

.card {
  animation: card-enter 0.6s cubic-bezier(0.22, 0.61, 0.36, 1);
  animation-fill-mode: backwards;
}

/* 交错动画 */
.card:nth-child(1) { animation-delay: 0.1s; }
.card:nth-child(2) { animation-delay: 0.2s; }
.card:nth-child(3) { animation-delay: 0.3s; }

示例4:打字机效果

@keyframes typing {
  from { width: 0; }
  to { width: 100%; }
}

@keyframes blink-caret {
  from, to { border-color: transparent; }
  50% { border-color: #000; }
}

.typewriter {
  overflow: hidden;
  border-right: 3px solid;
  white-space: nowrap;
  animation: 
    typing 3.5s steps(40, end),
    blink-caret 0.75s step-end infinite;
}

示例5:3D翻转卡片

.card {
  width: 200px;
  height: 300px;
  perspective: 1000px;
}

.card-inner {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transition: transform 0.8s;
}

.card:hover .card-inner {
  transform: rotateY(180deg);
}

.card-front,
.card-back {
  position: absolute;
  width: 100%;
  height: 100%;
  backface-visibility: hidden;
}

.card-back {
  transform: rotateY(180deg);
}

浏览器兼容性

  • transform:IE9+(需-ms-前缀)
  • transition:IE10+
  • animation:IE10+
  • 3D变换:IE10+(部分支持)

前缀使用

.element {
  -webkit-transform: translateX(100px);
      -ms-transform: translateX(100px);
          transform: translateX(100px);
  
  -webkit-transition: all 0.3s;
          transition: all 0.3s;
  
  -webkit-animation: slide-in 0.5s;
          animation: slide-in 0.5s;
}

最佳实践

  1. 移动端优化
/* 减少移动端动画 */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
  1. 性能监测
// 检测动画性能
const element = document.querySelector('.animated');
element.addEventListener('animationstart', () => {
  console.time('animation');
});
element.addEventListener('animationend', () => {
  console.timeEnd('animation');
});
  1. GPU加速
.element {
  transform: translateZ(0); /* 触发GPU加速 */
  will-change: transform;   /* 性能提示 */
}

补充说明

  • CSS动画性能优于JavaScript动画 3D变换需要硬件支持
  • 复杂动画考虑使用Web Animations API
  • 测试动画在不同设备的性能表现