<p>不能用 * { margin: 0; padding: 0 } 局部重置,因其破坏 fieldset、textarea、details 等原生行为,且权重低易被覆盖;all: unset 更彻底但需手动补 box-sizing 和字体继承。</p>

为什么不能用 * { margin: 0; padding: 0 } 套在模块里
很多人想局部重置,就给容器加个类,再写 .module * { margin: 0; padding: 0 }——这会破坏 fieldset、textarea、details 等元素的原生行为,比如表单控件失去默认间距后错位,summary 点击无反馈,select 下拉箭头消失。更关键的是,* 在局部作用域里权重极低,一旦模块内某个组件自带 button { margin: 4px },这条规则立刻被覆盖。
all: unset 是最接近“局部重置”的标准方案
它把目标元素及其所有后代的**所有可继承和不可继承属性**都设为初始值(不是 0,而是各属性定义的 initial 或 inherit),比手动列一堆 margin/padding 更彻底,且不干扰语义结构。
- 只对指定容器生效:
.card { all: unset; }会让.card自身重置,但不会影响外部;若要重置内部所有子元素,得写.card * { all: unset; } - 注意它也会清掉
display、font-family、color等,所以通常要搭配显式声明:.card { all: unset; display: block; font-family: system-ui; } - 不支持 IE,现代项目中可在
@supports (all: unset)里兜底
真正可控的局部重置:只重置你明确知道会出问题的元素
比起“全盘清空”,更稳妥的做法是针对模块内高频出问题的元素,逐个处理。例如一个卡片组件(.card)常含标题、段落、列表、按钮:
.card h1, .card h2, .card p, .card ul, .card ol { margin: 0; padding: 0; }.card ul, .card ol { list-style: none; }.card a { text-decoration: none; color: inherit; }.card img { display: block; max-width: 100%; }- 表单控件要特别小心:
.card button, .card input, .card select { margin: 0; padding: 0.375rem 0.75rem; }——保留可操作性,只调间距
容易被忽略的关键点:box-sizing 和字体继承必须手动补
即使用了 all: unset 或逐个重置,以下两处仍大概率出问题,且不会报错:
立即学习“前端免费学习笔记(深入)”;
-
.card { box-sizing: border-box; }—— 否则width: 100%+padding会撑破容器 -
.card * { font-family: inherit; line-height: inherit; }—— 否则span、em等内联元素可能回退到浏览器默认字体,字号/行高断裂 - 如果模块要嵌套使用(如
.card里再套.panel),避免重复重置:用:not(.panel) *或直接限定层级.card > *
实际项目里,“局部重置”从来不是一劳永逸的操作。它本质是权衡:既要隔离干扰,又不能切断浏览器对语义元素的合理支持。最稳的路径,是先用 all: unset 快速归零,再按需把 display、font、padding 这几项关键样式一层层加回来。


















