reset.css 和 normalize.css 不能共存,因目标相反:前者暴力清零,后者温和修复;混用会导致样式冲突,必须择一并在所有样式前作为首个生效样式表加载。

Reset CSS 和 Normalize.css 不能共存
二者目标相反:Reset 是暴力清零,Normalize 是温和修复。同时引入会导致样式冲突,比如 normalize.css 里给 button 设的默认内边距,会被 reset.css 的 * { padding: 0; } 覆盖,结果是按钮文字挤在角落、点击区域变小——这不是 bug,是叠加导致的不可预测行为。
选一个就行,别混用。目前主流项目几乎都选 normalize.css,因为它保留语义化标签表现(article、aside 有合理默认),不破坏 strong 加粗、sub 基线偏移等有用特性。
必须作为第一个生效的样式表加载
无论选哪个,它必须是 HTML 中第一个 <link rel="stylesheet">,且前面不能有任何其他样式介入:
- ❌ 错误:在
index.html里把业务 CSS 放在前面,normalize.css放后面 - ❌ 错误:用
@import把normalize.css写在main.css中间或末尾 - ❌ 错误:在 Vue/React 组件的
<style></style>块里@import 'normalize.css'—— Webpack/Vite 会把它打进组件 chunk,SSR 时可能重复注入、顺序错乱 - ✅ 正确:在
index.html的顶部,第一行就写<link rel="stylesheet" href="/css/normalize.css">
用 CSS-in-JS 时容易漏掉 prepend
Emotion、Styled Components 等库默认把动态生成的 <style></style> 插入到 末尾,如果没显式设置 prepend: true,那它们生成的样式就会盖在 normalize.css 上面,等于白加。
例如 Emotion 的配置要这样写:
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
<p>const cache = createCache({
key: 'css',
prepend: true, // ← 关键!不加这句,normalize.css 就失效
});
</p>
没设 prepend: true 的后果很隐蔽:表单控件字体变小、input 行高塌陷、button 边框消失——这些都不是你写的样式问题,而是 normalize.css 根本没起效。
Reset.css 的 font-size 强制 100% 是个坑
Eric Meyer 的经典 Reset 里有一句 font-size: 100%;,它切断了字体继承链。如果父容器(比如 body)没显式设 font-size,那 button、input 就会回落到 UA 默认字号(Chrome 是 13.33px,Safari 可能是 16px),而且不响应 rem 或根字体变化。
现象就是:button 文字比周围段落小一圈,光标紧贴上边缘,select 下拉箭头位置错乱。
解决办法只有两个:
- 改用
normalize.css(它不设font-size: 100%,而是让表单控件自然继承) - 如果非用 Reset,必须在它之后立即补一句
button, input, select, textarea { font-size: 1rem; }
真正难处理的不是“怎么加”,而是“加了但没生效”——顺序错、被动态样式覆盖、或 reset 自身的 font-size 断链,这三类问题在现场调试时最难一眼定位。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











