Skip to content

CSS面试题汇总

2026年最新版 - 涵盖盒模型、布局、现代CSS新特性、响应式设计、动画与性能优化

📋 目录


基础概念

1. 什么是CSS盒模型?

每个HTML元素都是一个矩形盒子,由四部分组成:content(内容)padding(内边距)border(边框)margin(外边距)

两种盒模型:

模型box-sizing宽度计算
标准盒模型content-box(默认)width = 内容宽度
IE盒模型border-boxwidth = 内容 + padding + border
css
/* 推荐全局使用 border-box */
*, *::before, *::after {
  box-sizing: border-box;
}

/* 标准盒模型:实际宽度 = 200 + 20*2 + 1*2 = 242px */
.content-box {
  box-sizing: content-box;
  width: 200px;
  padding: 20px;
  border: 1px solid #ccc;
}

/* IE盒模型:实际宽度 = 200px(内容自动缩小) */
.border-box {
  box-sizing: border-box;
  width: 200px;
  padding: 20px;
  border: 1px solid #ccc;
}

2. 什么是BFC?如何触发?

BFC(Block Formatting Context,块级格式化上下文) 是一个独立的渲染区域,内部元素的布局不会影响外部元素。

触发BFC的条件:

  • overflow 值不为 visible(如 hiddenautoscroll
  • display 值为 flow-rootflexgridinline-block
  • position 值为 absolutefixed
  • float 值不为 none

BFC的应用场景:

css
/* 1. 清除浮动 —— 推荐使用 display: flow-root */
.clearfix {
  display: flow-root;
}

/* 2. 阻止外边距合并 */
.parent {
  display: flow-root;
}
.child {
  margin-top: 20px; /* 不会与父元素的margin合并 */
}

/* 3. 阻止元素被浮动元素覆盖 */
.float-left {
  float: left;
  width: 200px;
}
.content {
  overflow: hidden; /* 创建BFC,不会环绕浮动元素 */
}

3. margin合并和margin塌陷是什么?

margin合并:相邻块级元素的上下外边距会合并为较大的那个值。

margin塌陷:父元素和第一个/最后一个子元素的外边距会合并。

css
/* margin合并:两个p之间的间距是30px,不是50px */
.p1 { margin-bottom: 20px; }
.p2 { margin-top: 30px; }

/* 解决margin塌陷 */
.parent {
  /* 方案1: 触发BFC */
  display: flow-root;
  /* 方案2: 添加border或padding */
  /* border-top: 1px solid transparent; */
  /* padding-top: 1px; */
}

4. 元素隐藏的方式有哪些?区别是什么?

方式占据空间可交互触发重排子元素可见
display: none
visibility: hidden✅(设置visible
opacity: 0
position: absolute + 移出视口
clip-path: inset(50%)
css
/* 屏幕阅读器可见的隐藏方式(无障碍推荐) */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

选择器与优先级

5. CSS选择器优先级如何计算?

优先级从高到低:

优先级类型示例
!importantcolor: red !important
1000内联样式style="color: red"
100ID选择器#header
10类/伪类/属性选择器.nav, :hover, [type="text"]
1元素/伪元素选择器div, ::before
0通配符/关系选择器*, >, +, ~
css
/* 优先级: 0-1-0 (一个类) */
.title { color: blue; }

/* 优先级: 1-0-0 (一个ID) */
#title { color: red; }

/* 优先级: 1-1-1 (一个ID + 一个类 + 一个元素) */
#header .nav a { color: green; }

/* :where() 优先级为0,:is() 取参数中最高优先级 */
:where(.card, #main) { color: gray; }  /* 优先级: 0-0-0 */
:is(.card, #main) { color: gray; }     /* 优先级: 1-0-0 */

6. :has() 选择器是什么?(2026重点)

:has() 被称为CSS的**"父选择器"**,可以根据子元素或后续兄弟元素的状态来选择父元素。

css
/* 选择包含图片的卡片 */
.card:has(img) {
  grid-template-rows: auto 1fr;
}

/* 选择没有图片的卡片 */
.card:not(:has(img)) {
  padding: 2rem;
}

/* 表单验证:输入框无效时,改变label样式 */
label:has(+ input:invalid) {
  color: red;
}

/* 标题后面紧跟段落时,减少下边距 */
h1:has(+ p) {
  margin-bottom: 0.25em;
}

/* 列表包含子列表时,添加左边框 */
ul:has(> li > ul) {
  border-left: 2px solid #667eea;
}

/* 页面级状态控制:body包含dialog[open]时调暗背景 */
body:has(dialog[open]) {
  overflow: hidden;
}

7. 伪类和伪元素的区别?

  • 伪类:):选择处于特定状态的元素,如 :hover:focus:first-child
  • 伪元素::):创建DOM中不存在的虚拟元素,如 ::before::after::placeholder
css
/* 伪类 - 选中特定状态 */
a:hover { color: #667eea; }
li:nth-child(odd) { background: #f5f5f5; }
input:focus-visible { outline: 2px solid #667eea; }

/* 伪元素 - 创建虚拟元素 */
.quote::before {
  content: '"';
  font-size: 2rem;
  color: #667eea;
}

/* 2026新伪元素 */
select::picker(select) {
  appearance: base-select;
  border-radius: 12px;
}

布局

8. Flexbox布局详解

Flexbox 是一维布局模型,适合处理行或列方向的元素排列。

css
.container {
  display: flex;

  /* 主轴方向 */
  flex-direction: row;          /* row | row-reverse | column | column-reverse */
  
  /* 换行 */
  flex-wrap: wrap;              /* nowrap | wrap | wrap-reverse */

  /* 主轴对齐 */
  justify-content: center;     /* flex-start | flex-end | center | space-between | space-around | space-evenly */

  /* 交叉轴对齐 */
  align-items: center;         /* flex-start | flex-end | center | stretch | baseline */

  /* 多行对齐 */
  align-content: space-between;

  /* 间距(推荐替代margin方案) */
  gap: 16px;
}

.item {
  /* 放大比例 */
  flex-grow: 1;
  /* 缩小比例 */
  flex-shrink: 0;
  /* 基础尺寸 */
  flex-basis: 200px;
  /* 简写: flex: grow shrink basis */
  flex: 1 0 200px;
  /* 单独对齐 */
  align-self: flex-end;
}

经典面试题:实现水平垂直居中

css
/* 方案1: Flexbox(最常用) */
.center-flex {
  display: flex;
  justify-content: center;
  align-items: center;
}

/* 方案2: Grid(最简洁) */
.center-grid {
  display: grid;
  place-items: center;
}

/* 方案3: 绝对定位 + transform */
.center-absolute {
  position: relative;
}
.center-absolute > .child {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

9. Grid布局详解

Grid 是二维布局模型,同时处理行和列

css
.grid-container {
  display: grid;

  /* 定义列 */
  grid-template-columns: repeat(3, 1fr);
  /* 定义行 */
  grid-template-rows: auto 1fr auto;
  /* 间距 */
  gap: 20px;

  /* 区域模板 */
  grid-template-areas:
    "header header header"
    "sidebar main   main"
    "footer footer footer";
}

.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main    { grid-area: main; }
.footer  { grid-area: footer; }

/* 自适应列数 */
.auto-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 20px;
}

10. Subgrid是什么?(2026重点)

Subgrid 允许子网格继承父网格的轨道定义,解决嵌套网格对齐问题。

css
.grid {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;
  gap: 1rem;
}

/* 子元素继承父网格的列轨道 */
.card {
  display: grid;
  grid-column: 1 / -1;              /* 跨越所有父列 */
  grid-template-columns: subgrid;   /* 继承父网格列定义 */
}

/* 实际应用:卡片列表对齐 */
.card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
}

.card {
  display: grid;
  grid-row: span 3;                 /* 每个卡片占3行 */
  grid-template-rows: subgrid;      /* 继承父网格行定义 */
}

/* 卡片内部元素(标题、内容、按钮)自动跨卡片对齐 */
.card h3 { /* 第1行 */ }
.card p   { /* 第2行 */ }
.card .btn { /* 第3行 */ align-self: end; }

11. Flex和Grid如何选择?

场景推荐原因
导航栏Flex单行水平排列
表单字段Flex简单的标签-输入对齐
卡片列表Grid二维自适应网格
整体页面布局Grid复杂的行列结构
垂直居中都可以Grid 更简洁 (place-items: center)
css
/* 导航栏 - 用Flex */
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

/* 仪表盘 - 用Grid */
.dashboard {
  display: grid;
  grid-template-columns: 250px 1fr;
  grid-template-rows: 60px 1fr;
  min-height: 100dvh;
}

现代CSS新特性

12. CSS原生嵌套(2026重点)

不再需要Sass/Less等预处理器来实现嵌套,CSS原生支持嵌套语法。

css
/* CSS 原生嵌套 */
.card {
  padding: 1rem;
  border: 1px solid var(--border);
  border-radius: 8px;

  /* 嵌套子元素 */
  & h3 {
    margin: 0 0 0.5rem;
    font-size: 1.25rem;
  }

  & p {
    color: #666;
    line-height: 1.6;
  }

  /* 嵌套伪类 */
  &:hover {
    border-color: #667eea;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  }

  /* 嵌套媒体查询 */
  @media (max-width: 768px) {
    padding: 0.75rem;
  }
}

/* 对比 Sass 写法 —— 现在CSS原生即可 */

13. 容器查询(Container Queries)是什么?(2026重点)

容器查询让组件根据父容器尺寸(而非视口)响应式调整,实现真正的组件级响应式设计

css
/* 1. 声明容器 */
.card-wrapper {
  container-type: inline-size;   /* 开启容器宽度查询 */
  container-name: card;          /* 可选命名 */
}

/* 2. 根据容器宽度调整布局 */
@container card (min-width: 400px) {
  .card {
    display: grid;
    grid-template-columns: 200px 1fr;
    gap: 1rem;
  }
}

@container card (min-width: 600px) {
  .card {
    grid-template-columns: 250px 1fr auto;
  }
  .card .actions {
    display: flex;
    flex-direction: column;
  }
}

/* 3. 容器查询单位 */
.card-title {
  font-size: clamp(1rem, 3cqw, 1.5rem);  /* cqw = 容器宽度的1% */
  padding: 2cqi;                           /* cqi = 容器内联尺寸的1% */
}

容器查询 vs 媒体查询:

特性媒体查询 @media容器查询 @container
基于视口尺寸父容器尺寸
组件复用不同上下文需调整自动适配
粒度页面级组件级
使用场景整体布局组件内部布局

14. @starting-style 和离散属性动画(2026重点)

@starting-style 让元素在首次渲染时也能有过渡动画,解决了 display: nonedisplay: block 无法动画的历史难题。

css
/* 弹窗淡入淡出 */
dialog {
  opacity: 1;
  transform: translateY(0);
  transition: opacity 0.3s, transform 0.3s,
              display 0.3s allow-discrete,
              overlay 0.3s allow-discrete;
}

/* 初始状态 —— 元素首次出现时的样式 */
@starting-style {
  dialog[open] {
    opacity: 0;
    transform: translateY(-20px);
  }
}

/* 关闭状态 */
dialog:not([open]) {
  opacity: 0;
  transform: translateY(-20px);
}

/* Popover 进出动画 */
[popover] {
  opacity: 1;
  scale: 1;
  transition: opacity 0.25s, scale 0.25s,
              display 0.25s allow-discrete,
              overlay 0.25s allow-discrete;
}

@starting-style {
  [popover]:popover-open {
    opacity: 0;
    scale: 0.9; 
  }
}

15. 滚动驱动动画(Scroll-Driven Animations)是什么?(2026重点)

纯CSS实现基于滚动位置的动画,无需JavaScript或第三方库。

css
/* 1. 页面滚动进度条 */
.progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  height: 3px;
  background: #667eea;
  transform-origin: left;
  animation: grow-progress linear;
  animation-timeline: scroll();      /* 绑定到页面滚动 */
}

@keyframes grow-progress {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* 2. 元素滚动进入视口时的淡入效果 */
.section {
  view-timeline: --reveal block;
}

.fade-in {
  animation: slide-up 1s ease both;
  animation-timeline: --reveal;
  animation-range: entry 0% cover 40%;
}

@keyframes slide-up {
  from {
    opacity: 0;
    transform: translateY(30px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 3. 横向滚动图片视差效果 */
.parallax-image {
  animation: parallax linear;
  animation-timeline: scroll(root);
}

@keyframes parallax {
  from { transform: translateY(-50px); }
  to   { transform: translateY(50px); }
}

16. Anchor Positioning(锚点定位)是什么?(2026重点)

CSS原生锚点定位,让Tooltip、下拉菜单等元素相对于触发器精准定位,无需JavaScript计算。

css
/* 触发器声明锚点 */
.trigger {
  anchor-name: --btn;
}

/* tooltip定位到触发器下方 */
.tooltip {
  position: absolute;
  position-anchor: --btn;
  inset-area: bottom;
  margin-top: 0.5rem;
}

/* 带自动翻转的下拉菜单 */
.dropdown-menu {
  position: absolute;
  position-anchor: --btn;
  inset-area: bottom span-right;
  
  /* 如果下方空间不足,自动翻转到上方 */
  position-try-fallbacks: flip-block;
}

17. 自定义Select样式(appearance: base-select)(2026重点)

终于可以用纯CSS自定义原生 <select> 的样式,同时保留原生可访问性和键盘交互。

css
/* 开启可自定义模式 */
select,
select::picker(select) {
  appearance: base-select;
}

/* 自定义下拉面板样式 */
select::picker(select) {
  border-radius: 12px;
  border: 1px solid #e0e0e0;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
  padding: 0.5rem;
}

/* 选项样式 */
option {
  padding: 0.75rem 1rem;
  border-radius: 8px;
  transition: background 0.2s;
}

option:hover {
  background: #f0f0ff;
}

/* 配合 sibling-index() 实现交错动画 */
option {
  transition: opacity 0.25s ease, translate 0.3s ease;
  transition-delay: calc(0.05s * (sibling-index() - 1));
}

@starting-style {
  option {
    opacity: 0;
    translate: 20px 0;
  }
}

响应式设计

18. 媒体查询的用法和最佳实践?

css
/* 移动优先:从小屏开始,逐步增强 */
.container {
  padding: 1rem;
}

/* 平板 */
@media (min-width: 768px) {
  .container {
    padding: 2rem;
    max-width: 720px;
    margin: 0 auto;
  }
}

/* 桌面 */
@media (min-width: 1024px) {
  .container {
    max-width: 960px;
  }
}

/* 大屏 */
@media (min-width: 1280px) {
  .container {
    max-width: 1200px;
  }
}

/* 偏好查询 */
@media (prefers-color-scheme: dark) {
  :root { --bg: #1a1a2e; --text: #eee; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; }
}

/* 高分辨率屏幕 */
@media (min-resolution: 2dppx) {
  .logo { background-image: url('logo@2x.png'); }
}

19. 新视口单位 dvh、svh、lvh 是什么?(2026重点)

解决移动端 100vh 被浏览器地址栏遮挡的经典问题。

css
/*
  svh (Small Viewport Height) - 浏览器UI完全展开时的视口高度
  lvh (Large Viewport Height)  - 浏览器UI完全收起时的视口高度
  dvh (Dynamic Viewport Height) - 动态跟随浏览器UI变化
*/

/* Hero区域 - 使用dvh */
.hero {
  min-height: 100dvh;    /* 动态适应地址栏显隐 */
  display: grid;
  place-items: center;
}

/* 固定底部按钮 - 使用svh确保始终可见 */
.bottom-bar {
  position: fixed;
  bottom: 0;
  height: calc(100svh - 100dvh + 60px);
  /* ... */
}

/* 兼容写法 */
.full-height {
  min-height: 100vh;     /* 回退 */
  min-height: 100dvh;    /* 现代浏览器 */
}

20. 响应式字体和间距的最佳方案?

css
/* clamp() 实现流式响应 */
.title {
  /* clamp(最小值, 首选值, 最大值) */
  font-size: clamp(1.5rem, 4vw, 3rem);
}

.container {
  padding: clamp(1rem, 3vw, 3rem);
  gap: clamp(0.5rem, 2vw, 2rem);
}

/* 结合容器查询单位 */
.card-title {
  font-size: clamp(1rem, 3cqw, 1.5rem);
}

/* 现代流式排版系统 */
:root {
  --step-0: clamp(1rem, 0.5rem + 1vw, 1.25rem);
  --step-1: clamp(1.25rem, 0.75rem + 1.5vw, 1.75rem);
  --step-2: clamp(1.5rem, 1rem + 2vw, 2.5rem);
  --step-3: clamp(2rem, 1.25rem + 3vw, 3.5rem);
  
  --space-s: clamp(0.5rem, 0.25rem + 1vw, 1rem);
  --space-m: clamp(1rem, 0.5rem + 2vw, 2rem);
  --space-l: clamp(2rem, 1rem + 4vw, 4rem);
}

h1 { font-size: var(--step-3); }
h2 { font-size: var(--step-2); }
p  { font-size: var(--step-0); }

颜色与主题

21. 现代CSS颜色函数有哪些?(2026重点)

css
:root {
  /* oklch - 感知均匀的颜色空间,2026推荐 */
  --brand: oklch(0.72 0.18 250);
  --brand-light: oklch(0.85 0.12 250);
  --brand-dark: oklch(0.55 0.20 250);
}

/* color-mix() - 颜色混合 */
.card {
  /* 将品牌色与白色按60%:40%混合 */
  border-color: color-mix(in oklab, var(--brand) 60%, white);
}

.card:hover {
  /* 相对颜色语法 - 降低亮度10% */
  background: oklch(from var(--brand) calc(l - 0.1) c h / 0.12);
}

/* light-dark() - 根据color-scheme自动切换 */
:root {
  color-scheme: light dark;
}

.button {
  background: light-dark(#fff, #1a1a2e);
  color: light-dark(#333, #eee);
  border-color: light-dark(#ddd, #444);
}

/* 传统暗色模式对比 */
/* 旧写法:需要两套媒体查询 */
@media (prefers-color-scheme: dark) {
  .button { background: #1a1a2e; color: #eee; }
}
/* 新写法:light-dark() 一行搞定 */

22. CSS自定义属性(变量)的高级用法?

css
:root {
  --color-primary: #667eea;
  --color-secondary: #764ba2;
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 16px;
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.15);
}

/* 组件级变量 + 回退值 */
.button {
  --btn-bg: var(--color-primary);
  --btn-radius: var(--radius-md);

  background: var(--btn-bg);
  border-radius: var(--btn-radius);
  padding: var(--btn-padding, 0.5rem 1rem); /* 带回退 */
}

/* 变体通过覆盖变量实现 */
.button--danger {
  --btn-bg: #e53e3e;
}
.button--rounded {
  --btn-radius: 999px;
}

/* 在JavaScript中操作CSS变量 */
javascript
// 读取
getComputedStyle(document.documentElement)
  .getPropertyValue('--color-primary');

// 设置
document.documentElement.style
  .setProperty('--color-primary', '#ff6b6b');

动画与过渡

23. transition和animation的区别?

特性transitionanimation
触发方式需状态变化触发自动/自定义触发
关键帧仅起始和结束可定义多个
循环不支持infinite
方向单方向(可回弹)alternate
控制简单丰富
css
/* transition 示例 */
.btn {
  background: #667eea;
  transition: background 0.3s ease, transform 0.2s ease;
}
.btn:hover {
  background: #5a67d8;
  transform: translateY(-2px);
}

/* animation 示例 */
.loading-dot {
  animation: bounce 1.4s ease-in-out infinite both;
}

.loading-dot:nth-child(1) { animation-delay: 0s; }
.loading-dot:nth-child(2) { animation-delay: 0.16s; }
.loading-dot:nth-child(3) { animation-delay: 0.32s; }

@keyframes bounce {
  0%, 80%, 100% {
    transform: scale(0);
  }
  40% {
    transform: scale(1);
  }
}

24. View Transitions(视图过渡)API是什么?(2026重点)

实现页面/状态切换的平滑过渡动画,支持SPA和MPA。

css
/* 1. 基础视图过渡 */
::view-transition-old(root) {
  animation: fade-out 0.3s ease;
}

::view-transition-new(root) {
  animation: fade-in 0.3s ease;
}

@keyframes fade-out {
  to { opacity: 0; }
}

@keyframes fade-in {
  from { opacity: 0; }
}

/* 2. 命名视图过渡 - 特定元素过渡 */
.hero-image {
  view-transition-name: hero;
}

::view-transition-group(hero) {
  animation-duration: 0.5s;
}

/* 3. MPA跨页面过渡 */
@view-transition {
  navigation: auto;
}
javascript
// SPA中使用
document.startViewTransition(() => {
  // 更新DOM
  updateContent();
});

25. sibling-index() 和 sibling-count() 是什么?(2026重点)

CSS树计数函数,获取元素在兄弟中的索引和总数,实现动态交错动画。

css
/* 交错动画 - 无需手动设置每个元素的延迟 */
.list-item {
  opacity: 0;
  animation: slide-in 0.3s ease forwards;
  /* sibling-index() 返回元素在兄弟中的位置(1-based) */
  animation-delay: calc(0.08s * (sibling-index() - 1));
}

@keyframes slide-in {
  from {
    opacity: 0;
    transform: translateX(-20px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

/* 基于总数的自适应布局 */
.grid-item {
  /* sibling-count() 返回兄弟元素总数 */
  flex-basis: calc(100% / sibling-count());
}

/* 彩虹色列表 */
.color-item {
  background: oklch(0.75 0.15 calc(360 / sibling-count() * sibling-index()));
}

CSS工程化

26. Cascade Layers(级联层)@layer 是什么?(2026重点)

@layer 让开发者显式控制CSS的级联顺序,解决大型项目中的优先级冲突。

css
/* 1. 定义层级顺序(后面的层优先级更高) */
@layer reset, base, components, utilities;

/* 2. 在各层中编写样式 */
@layer reset {
  *, *::before, *::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
}

@layer base {
  body {
    font-family: system-ui, sans-serif;
    line-height: 1.6;
    color: var(--text);
  }

  a { color: var(--link); }
}

@layer components {
  .btn {
    padding: 0.5rem 1rem;
    border-radius: 8px;
    background: var(--color-primary);
    color: white;
  }

  .card {
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 1.5rem;
  }
}

@layer utilities {
  .sr-only { /* 屏幕阅读器专用 */ }
  .text-center { text-align: center; }
  .hidden { display: none; }
}

/* 无层级的样式优先级最高 */
.override { color: red; }

27. @scope 是什么?

@scope 限制样式的作用范围,避免全局污染。

css
/* 样式只在 .card 内部生效 */
@scope (.card) {
  h3 {
    margin: 0 0 0.5rem;
    font-size: 1.25rem;
  }

  p {
    color: #666;
  }

  a {
    color: #667eea;
  }
}

/* 指定上下界 - 样式在 .card 内生效,但不影响 .card-footer 内的元素 */
@scope (.card) to (.card-footer) {
  p {
    font-size: 1rem;
    line-height: 1.8;
  }
}

28. CSS变量 vs Sass变量 vs CSS-in-JS?

特性CSS变量Sass变量CSS-in-JS
运行时✅ 动态❌ 编译时✅ 动态
继承✅ 级联继承取决于实现
JS访问
作用域选择器作用域块作用域组件作用域
性能中等
主题切换✅ 原生支持需多文件
css
/* 2026推荐:CSS变量 + @layer 的组合 */
@layer tokens {
  :root {
    --color-primary: oklch(0.65 0.2 260);
    --space-unit: 0.25rem;
    --space-xs: calc(var(--space-unit) * 2);
    --space-sm: calc(var(--space-unit) * 4);
    --space-md: calc(var(--space-unit) * 8);
    --space-lg: calc(var(--space-unit) * 16);
  }

  [data-theme="dark"] {
    --color-primary: oklch(0.75 0.18 260);
  }
}

性能优化

29. 哪些CSS属性会触发重排(reflow)和重绘(repaint)?

重排(Reflow)→ 重绘(Repaint)→ 合成(Composite)
成本:  高              中              低
操作触发示例属性
改变几何属性重排+重绘width, height, margin, padding, top, left
改变外观属性重绘color, background, box-shadow, visibility
合成层属性仅合成transform, opacity, filter, will-change
css
/* ❌ 差 - 触发重排 */
.animate-bad {
  transition: left 0.3s, top 0.3s;
}
.animate-bad:hover {
  left: 100px;
  top: 50px;
}

/* ✅ 好 - 仅触发合成 */
.animate-good {
  transition: transform 0.3s;
}
.animate-good:hover {
  transform: translate(100px, 50px);
}

/* will-change 提示浏览器提前优化 */
.will-animate {
  will-change: transform, opacity;
}

/* content-visibility 跳过屏幕外元素的渲染 */
.long-list-item {
  content-visibility: auto;
  contain-intrinsic-size: 0 80px;  /* 预估高度 */
}

30. contain 和 content-visibility 属性的作用?

css
/* contain - 限制元素的渲染影响范围 */
.widget {
  contain: layout;   /* 内部布局变化不影响外部 */
  contain: paint;    /* 内部绘制不溢出 */
  contain: size;     /* 不依赖子元素确定尺寸 */
  contain: strict;   /* 同时启用 layout + paint + size */
  contain: content;  /* 同时启用 layout + paint */
}

/* content-visibility - 跳过屏幕外内容的渲染 */
.below-fold {
  content-visibility: auto;          /* 不在视口中时跳过渲染 */
  contain-intrinsic-size: auto 500px; /* 预估尺寸防止滚动条跳动 */
}

/* 实际应用:长列表优化 */
.list-section {
  content-visibility: auto;
  contain-intrinsic-size: auto 200px;
}

31. 如何优化CSS加载性能?

html
<!-- 1. 关键CSS内联 -->
<style>
  /* 首屏必要样式 */
  .hero { display: grid; place-items: center; min-height: 100dvh; }
</style>

<!-- 2. 非关键CSS异步加载 -->
<link rel="stylesheet" href="non-critical.css" media="print" onload="this.media='all'">
<noscript><link rel="stylesheet" href="non-critical.css"></noscript>

<!-- 3. 预加载关键CSS -->
<link rel="preload" href="critical.css" as="style">
css
/* 4. 避免使用 @import(阻塞渲染) */
/* ❌ */ @import url('other.css');
/* ✅ 使用 <link> 标签替代 */

/* 5. 使用 CSS @layer 组织代码,减少优先级冲突 */
@layer base, components, utilities;

/* 6. 合理使用 font-display */
@font-face {
  font-family: 'CustomFont';
  src: url('font.woff2') format('woff2');
  font-display: swap; /* 先显示系统字体,加载后切换 */
}

/* 7. 使用 CSS containment 减少渲染开销 */
.card {
  contain: content;
}

进阶深入

32. @property 注册自定义属性是什么?

@property 让CSS变量拥有类型检查、默认值和继承控制,是 CSS Houdini 的一部分。

css
/* 注册一个有类型的自定义属性 */
@property --progress {
  syntax: '<percentage>';
  inherits: false;
  initial-value: 0%;
}

/* 核心用途:让自定义属性可以被动画! */
.progress-bar {
  --progress: 0%;
  background: linear-gradient(to right, #4caf50 var(--progress), #eee var(--progress));
  transition: --progress 0.5s ease;
}
.progress-bar:hover {
  --progress: 80%;
  /* ✅ 渐变现在可以平滑过渡了! */
  /* 没有 @property 注册,transition 对自定义属性无效 */
}

/* 实现颜色循环动画 */
@property --hue {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}

.rainbow {
  --hue: 0deg;
  background: hsl(var(--hue), 80%, 60%);
  animation: hue-cycle 3s linear infinite;
}

@keyframes hue-cycle {
  to { --hue: 360deg; }
}

/* 实现数字计数器动画 */
@property --num {
  syntax: '<integer>';
  inherits: false;
  initial-value: 0;
}

.counter {
  --num: 0;
  animation: count-up 2s ease forwards;
  counter-reset: num var(--num);
}
.counter::after {
  content: counter(num);
}

@keyframes count-up {
  to { --num: 100; }
}

@property syntax 支持的类型:

  • <length>, <percentage>, <number>, <integer>
  • <color>, <angle>, <time>
  • <image>, <url>, <transform-function>
  • <custom-ident>, *(任意值)

33. CSS逻辑属性是什么?为什么重要?

逻辑属性用书写方向无关的方式替代物理方向属性(top/right/bottom/left),对国际化(i18n) 至关重要。

css
/* 物理属性 → 逻辑属性 */
/* 水平方向(inline轴) */
margin-leftmargin-inline-start
margin-rightmargin-inline-end
padding-leftpadding-inline-start
padding-rightpadding-inline-end
width         → inline-size

/* 垂直方向(block轴) */
margin-topmargin-block-start
margin-bottommargin-block-end
height        → block-size

/* 简写 */
margin-inline: 0 auto;    /* 等价于 margin-left: 0; margin-right: auto; */
padding-block: 16px 24px;  /* 等价于 padding-top: 16px; padding-bottom: 24px; */
inset-inline: 0;           /* 等价于 left: 0; right: 0; */

/* 边框和圆角 */
border-inline-start: 2px solid red;  /* 在LTR中是左边框,RTL中是右边框 */
border-start-start-radius: 8px;      /* LTR中是左上角 */

/* 实际应用:RTL自适应布局 */
.sidebar {
  inline-size: 280px;          /* 宽度 */
  padding-inline: 16px;        /* 左右内边距 */
  border-inline-end: 1px solid #ddd; /* 分隔线 */
  margin-inline-start: auto;   /* 自动靠一边 */
}
/* 在 dir="rtl" 下,所有方向自动镜像,无需额外CSS */

34. CSS架构方法论有哪些?怎么选?

css
/* 1. BEM(Block Element Modifier) */
/* 命名规范:block__element--modifier */
.card { }
.card__title { }
.card__image { }
.card__button--primary { }
.card__button--disabled { }

/* 优点:清晰、无嵌套冲突、可维护性好 */
/* 缺点:类名较长 */

/* 2. Utility-First(Tailwind CSS 风格) */
/* <div class="flex items-center gap-4 p-6 bg-white rounded-lg shadow-md"> */

/* 3. CSS Modules */
/* 自动生成唯一类名,天然隔离 */
/* .title → .Title_title__3xk2a */

/* 4. CSS-in-JS(styled-components / Emotion) */
/* 与组件绑定,动态样式,自动作用域 */

/* 5. 2026推荐:@layer + CSS变量 + 原生嵌套 */
@layer base, components, utilities;

@layer base {
  :root {
    --color-primary: oklch(65% 0.25 260);
    --radius: 8px;
    --spacing: 16px;
  }
}

@layer components {
  .card {
    border-radius: var(--radius);
    padding: var(--spacing);
    
    & .title {
      font-size: 1.25rem;
      font-weight: 600;
    }
    
    &:hover {
      box-shadow: 0 4px 12px oklch(0% 0 0 / 10%);
    }
  }
}
方案适用场景隔离性工具依赖
BEM传统项目、多人协作约定式
CSS ModulesReact/Vue组件化项目编译隔离构建工具
Tailwind快速开发、设计系统原子类PostCSS
CSS-in-JSReact动态样式运行时隔离JS库
@layer + Nesting2026现代项目原生级联控制

35. text-wrap: balance 和 pretty 是什么?

css
/* text-wrap: balance - 让标题文本行宽更均匀 */
h1, h2, h3 {
  text-wrap: balance;
  /* 之前: "这是一个非常长的标题"
     第一行:这是一个非常长的标
     第二行:题

     之后 balance:
     第一行:这是一个非常
     第二行:长的标题         ← 行宽更均匀 */
}

/* text-wrap: pretty - 避免段落末尾出现孤字(orphans) */
p {
  text-wrap: pretty;
  /* 浏览器会调整换行位置,避免最后一行只有一个字 */
}

/* white-space-collapse: 控制空白处理 */
pre {
  white-space-collapse: preserve;  /* 保留空白 */
}
.normalize {
  white-space-collapse: collapse;  /* 折叠连续空白 */
}

36. 如何实现瀑布流布局?(Masonry Layout)

css
/* 方法1: CSS Grid Masonry(实验性,2026+ Firefox已支持) */
.masonry-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: masonry; /* ✨ 原生瀑布流 */
  gap: 16px;
}

/* 方法2: CSS columns(现已广泛支持) */
.masonry-columns {
  columns: 3 240px;
  column-gap: 16px;
}
.masonry-columns .item {
  break-inside: avoid;
  margin-bottom: 16px;
}

/* 方法3: Flexbox 模拟(竖向排列) */
.masonry-flex {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  height: 800px; /* 需要固定高度 */
  gap: 16px;
}

37. CSS自定义高亮(Custom Highlight API)是什么?

javascript
// 创建自定义高亮 - 替代传统的包裹<span>方案
const text = document.querySelector('p').firstChild;

// 创建Range
const range = new Range();
range.setStart(text, 5);
range.setEnd(text, 10);

// 注册高亮
const highlight = new Highlight(range);
CSS.highlights.set('search-result', highlight);
css
/* 用CSS设置高亮样式 */
::highlight(search-result) {
  background-color: #ffeb3b;
  color: #000;
}

/* 多种高亮可共存 */
::highlight(spell-error) {
  text-decoration: wavy underline red;
}
::highlight(grammar-error) {
  text-decoration: wavy underline blue;
}

优势: 不修改DOM结构、性能好、支持大量高亮、不破坏事件绑定。

38. CSS field-sizing 属性是什么?(2026新特性)

css
/* 让表单元素自动根据内容调整尺寸 */
textarea, input, select {
  field-sizing: content;
  /* textarea 会随输入内容自动增长高度
     input 会随文本宽度自动扩展
     select 会适配最长选项的宽度 */
}

/* 配合 min/max 使用 */
textarea {
  field-sizing: content;
  min-block-size: 3lh;    /* 最小3行高 */
  max-block-size: 10lh;   /* 最大10行高 */
}

总结

2026年CSS面试重点:

  1. 盒模型与BFC - 经典必考,理解触发条件和应用场景
  2. Flexbox & Grid & Subgrid - 布局三件套,Subgrid是新热点
  3. :has() 选择器 - CSS最受欢迎的新特性,使用率最高
  4. 容器查询 - 组件级响应式设计,替代部分媒体查询场景
  5. CSS原生嵌套 - 告别Sass嵌套依赖
  6. 滚动驱动动画 - 纯CSS实现滚动动效
  7. @starting-style - 解决 display 动画难题
  8. @layer 级联层 - 大型项目CSS架构必备
  9. 现代颜色函数 - oklch、color-mix()、light-dark()
  10. 性能优化 - content-visibility、contain、合成层动画

学习建议:

  • 经典布局(盒模型、BFC、Flex、Grid)仍是面试基础,必须扎实
  • 重点掌握 :has()、容器查询、CSS嵌套等已全面支持的新特性
  • 了解 @starting-style、滚动驱动动画、Anchor Positioning 等前沿特性
  • 关注 CSS 工程化趋势:@layer + CSS变量 + 原生嵌套的组合