<p>结论:应避免全量 * { margin: 0; padding: 0; },优先重置 body、常见块级元素(h1–h6、p、ul 等)及伪元素的 box-sizing,再按需局部调整表单、图片、列表;现代项目推荐用 normalize.css 而非 reset.css,并确保重置规则最先加载。</p>

直接说结论:别用全量 * { margin: 0; padding: 0; },优先写三条关键规则,再按需补表单、图片、列表等局部重置。
为什么 body { margin: 0; } 不能解决顶部空白
页面顶部多出 20px 空白,不是 body 的 margin 没清掉,而是 h1、p、ul 这些子元素自带的 margin-top 在作祟。Chrome 和 Firefox 对 h1 的默认上边距定义不同(比如 Chrome 是 21.4px,Firefox 四舍五入为 21px),外边距还会和父容器折叠,导致视觉偏差放大。只清 body 根本没碰问题源头。
- 必须同时重置常见块级元素:
h1到h6、p、ul、ol、blockquote、pre、figure、dl、dd - 别漏伪元素:
*::before, *::after也要加box-sizing: border-box,否则用::after清浮动时高度计算会错 - 检查 DevTools 的 Computed 面板里
margin-top值来源——如果显示来自 User Agent Stylesheet,说明你的重置规则没生效或被覆盖
* { box-sizing: border-box; } 必须放在最前面
这条规则一旦被后续 CSS 覆盖,所有基于 width: 50% 的浮动或 Flex 子项都会因 padding/border 溢出而换行。尤其在引入第三方 UI 库(如 Element Plus、Ant Design)后,它们的样式表可能带权重更高的选择器,把你写的通配符干掉。
- 把它塞进项目第一个加载的 CSS 文件顶部,不要放在
@import后面 - 务必连带写上:
*::before, *::after { box-sizing: border-box; },否则伪元素不参与 border-box 计算 - 注意性能:现代浏览器对
*选择器优化较好,但若项目已用 Tailwind 或 Windi,它们内置了 normalize 逻辑,再叠一层*可能引发意外交互
表单控件和图片的默认样式最容易被 reset.css 搞崩
传统 reset.css 把 input、button、select 的 margin、padding、border 全清零,结果控件变“贴纸”——没内边距、没圆角、文字贴边、点击无反馈。这不是你想要的“干净起点”,是“废掉起点”。
立即学习“前端免费学习笔记(深入)”;
- 只重置影响布局的关键属性:
font-family、font-size、line-height、margin(仅上下)、vertical-align - 图片要加:
img { display: block; max-width: 100%; vertical-align: top; },否则在 IE/Safari 浮动时底部留白 4px - 列表必须清
list-style:ul, ol { list-style: none; },不然一个<ul></ul>就能撑高父容器,且各浏览器圆点/数字缩进位置不一致
现代项目该选 reset.css 还是 normalize.css?
如果你用的是 Vue + Vite + UnoCSS,或者 React + Next.js + Tailwind,别自己写 reset.css。这些框架/工具链底层已集成 normalize 行为,再手动引入 Eric Meyer 版本的 reset.css,反而会让 button 失去默认 focus-outline、svg 丢失 vertical-align、pre 换行异常。
- normalize.css 不清空所有 margin/padding,而是修复真实差异:比如统一
button的vertical-align、修正pre在 Safari 的换行逻辑 - 它保留语义化默认行为(如
small字体缩小、em斜体),避免你重复实现可访问性 - 真正需要“激进重置”的场景极少——只有当你接手一个老项目,里面混着大量依赖浏览器默认 margin 的 HTML,且无法重构 DOM 结构时,才考虑局部启用 reset
最常被忽略的一点:重置规则的加载顺序比内容更重要。哪怕只写三行,也要确保它们出现在所有业务 CSS 和第三方样式之前,否则在 DevTools 里看到划掉的 box-sizing 就晚了。


















