CSS 高频考点(1)

8 阅读6分钟

1. CSS 选择器优先级:不是谁写得多,而是谁“说了算”

你有没有遇到过这种情况:引入了一个 UI 框架,想改个按钮样式,结果发现自己的 CSS 根本没生效?打开开发者工具一看,你的样式被划掉了。这时候,问题往往出在——优先级不够

CSS 的优先级,本质上是一场“权力斗争”。多个规则作用于同一个元素时,浏览器得有个标准来决定用哪个。这个标准,就是“特异性”(Specificity)。

我们可以把优先级想象成一个“权重打分系统”,从高到低大致是:

!important > 内联样式(style 属性) > ID 选择器 > 类/属性/伪类选择器 > 标签/伪元素选择器

但面试官如果只让你背这个顺序,那太浅了。真正关键的是理解“权重怎么算”。

举个例子:

/* 权重:100(ID) */
#header .nav a { color: blue; }

/* 权重:20(两个类) */
.sidebar .menu a { color: red; }

虽然第二个选择器更长,但它的权重只有 20,而第一个是 100,所以蓝色会胜出。

再比如:

/* 权重:111(1个ID + 1个类 + 1个标签) */
#main .btn span { font-weight: bold; }

/* 权重:100(只有ID) */
#main { font-weight: normal; }

即便 #main 更“全局”,但具体到 span 上,前者的权重更高,粗体依然生效。

⚠️ 面试加分点:别滥用 !important

!important 虽然能强行获胜,但它就像“核武器”——用一次,代码的可维护性就下降一分。一旦项目里到处都是 !important,你就进入了“重要性战争”,最后谁写得晚谁赢,完全失控。

更优雅的做法是:

  • 提高选择器的具体性(比如加个父级类)
  • 利用 CSS 的层叠顺序(后引入的样式优先级更高)
  • 或者在框架允许的情况下,使用 CSS 变量scoped 样式

2. CSS 单位:px、em、rem、vw、vh——选对单位,布局事半功倍

单位是 CSS 中最灵活也最容易踩坑的部分。不同的单位适用于不同的场景,选错了,响应式就变成“错位式”。

我们一个一个来看:

px(像素)——绝对中的“相对”

px 是最熟悉的单位,它是“绝对单位”,但在高分辨率屏幕(比如 Retina 屏)上,1 个 CSS 像素可能对应多个物理像素(DPR > 1)。所以你写的 1px 边框在 iPhone 上看起来特别粗。如果要做真正的“高清 1px”,得用 transform: scale(0.5)viewport 缩放。

em——相对当前字体,但会“层层放大”

em 的基准是当前元素的 font-size。它的好处是能和字体保持比例,比如按钮的 padding 用 em,字体变大时,按钮也自动变大。但它的坑在于继承和嵌套:如果父元素 font-size: 1.2em,子元素再 1.2em,结果就是 1.44em,容易“滚雪球”式放大。

rem——基于根元素,响应式排版的利器

rem 的“r”代表 root,它的基准是 <html> 元素的 font-size。无论嵌套多深,1rem 永远等于根字体大小。这使得 rem 成为实现全局响应式的首选。比如我可以在不同屏幕宽度下动态设置:

/* 手机端 */
html { font-size: 14px; }

/* 桌面端 */
@media (min-width: 768px) {
  html { font-size: 16px; }
}

整个页面的字体和间距就会等比缩放,非常优雅。

vw / vh——视口单位,流式布局的好帮手

1vw = 视口宽度的 1%1vh = 视口高度的 1%。它们特别适合做全屏背景、流式容器。但有个大坑:在 iOS Safari 上,地址栏会动态显示/隐藏,导致视口高度变化。你写的 100vh 可能比实际可用空间还大,造成页面滚动或布局抖动。

解决方案

  • 使用 dvh(dynamic viewport height,现代浏览器支持)
  • 或用 JavaScript 动态计算并设置高度

3. 隐藏元素的几种方式:不只是“看不见”那么简单

面试官常问:“怎么隐藏一个元素?它们有啥区别?” 这题看似简单,但能看出你对布局和交互的理解。

方法占文档流响应事件典型场景
display: none❌ 不占空间❌ 不可点击彻底隐藏,比如 Tab 切换
visibility: hidden✅ 占空间❌ 不可点击隐藏但保留位置,比如 loading 占位
opacity: 0✅ 占空间✅ 可点击做淡入淡出动画,避免布局跳动
width: 0; height: 0❌ 不占空间❌ 不可点击内容收起,比如折叠面板
clip-path: polygon(...)✅ 占空间❌ 不可点击精确裁剪,动画友好

💡 实战建议:

  • 动画时优先用 opacity,因为它不触发重排,性能好。
  • 彻底移除空间用 display: none
  • 如果只是想让用户看不见但保留布局,用 visibility: hidden

4. 盒模型(Box Model):每个元素都是一个盒子,但“盒子”有两种理解

在 CSS 中,每个元素都由 content、padding、border、margin 构成。但关键在于:widthheight 到底包含哪些部分?

📦 标准盒模型(content-box,默认)

  • width / height 只包含 content
  • 实际占用宽高 = content + padding + border + margin
  • 优点:符合 W3C 标准
  • 缺点:布局时要手动减去 padding 和 border,容易出错

📦 怪异盒模型(border-box

  • width / height 包含 content + padding + border
  • 实际占用宽高 = width/height + margin
  • 优点:布局直观,width: 300px 就是 300px
  • 缺点:与标准模型不一致

🛠 实战建议:

我几乎在每个项目初始化时都会写:

* {
  box-sizing: border-box;
}

这能避免大量尺寸计算错误,减少重绘和重排,提升开发效率和页面性能。同时记住:

  • 背景色只延伸到 padding 区域
  • margin 会发生折叠(垂直方向相邻元素的 margin 会合并)

5. BFC(块级格式化上下文):CSS 布局的“隔离舱”

BFC(Block Formatting Context)是 CSS 中一个非常重要的概念,它是一个独立的渲染区域,里面的元素布局不会影响外面。

🔧 什么情况下会触发 BFC?

  • float 不为 none
  • overflowhiddenautoscroll
  • displayinline-blockflexgridtable-cell
  • positionabsolutefixed

🎯 BFC 的核心特性:

  • 内部盒子垂直排列
  • 防止与浮动元素重叠(可用于清除浮动)
  • 计算高度时包含浮动子元素(解决父容器高度塌陷)
  • 外部 margin 不与内部 margin 合并(解决外边距塌陷)

💼 典型应用场景:

  • 清除浮动:给父容器加 overflow: hidden
  • 避免文字环绕浮动图片:给文字容器触发 BFC
  • 解决 margin 合并:给相邻元素加 BFC

6. 移动端适配实战技巧:不只是 rem

结合上面的知识,移动端适配的核心思路是:

✅ 使用 rem + 动态 html 字体

// 根据屏幕宽度动态设置 font-size
function setRootFontSize() {
  const width = Math.min(window.innerWidth, 750);
  document.documentElement.style.fontSize = `${width / 7.5}px`;
}
window.addEventListener('resize', setRootFontSize);
setRootFontSize();

✅ 配合 vw 做流式容器

.container {
  width: 90vw; /* 占视口 90% */
  max-width: 750px;
}

✅ 解决 iOS Safari 100vh 抖动

// 动态设置高度,避免地址栏影响
document.documentElement.style.setProperty('--vh', window.innerHeight * 0.01 + 'px');
.full-height {
  height: calc(var(--vh, 1vh) * 100);
}