:not()只能写一个简单选择器,写错则整条规则静默失效;它不取消样式,仅过滤匹配,最终样式由层叠和优先级共同决定。

DevTools里看DOM树,别猜层级
打开浏览器开发者工具,右键目标元素 →「Reveal in Elements panel」,直接观察它在 DOM 树里的真实挂载位置。如果目标元素的父节点就是你写的那个祖先选择器(比如 .card),且中间没夹任何其他标签(包括 div、section、甚至文本节点),那 .card > p 才安全;只要中间有一层不确定的包裹,就得换成 .card p。
常见翻车点:.nav > li 写得严丝合缝,但二级菜单的 li 实际在 .nav > ul > li 路径里——它的父节点是 ul,不是 .nav,所以根本不会命中。
:not() 前没加 >,禁用逻辑就漏了
比如写 .list li:not(.disabled) 本意是隐藏一级列表项里带 .disabled 的项,但这个选择器会匹配所有后代 li,包括嵌套在某个 li 里的子菜单项。结果子菜单里一个 li 被意外禁用,而你完全没意识到它被选中了。
正确做法是先用 > 锁定作用域:.list > li:not(.disabled)。这样 :not() 只作用于 .list 的直接子 li,不会穿透到下级结构。
- 错误现象:表格行里嵌了个小列表,
.table-row li:not(.hidden)导致小列表的li也被算进主行高计算 - 原因:
:not()不改变选择器的作用半径,它只修饰前面整个选择器的结果 - 修复关键:先收窄范围,再加伪类
样式“多生效”或“全不生效”,大概率是符号用反了
如果发现某段文字颜色变了,但你只改了 .card > p,而那个 p 其实藏在 .card > .content > p 里——那它根本不会被命中,属于“全不生效”。反过来,如果你写了 .card p 却发现页脚、弹窗、侧边栏的 p 全被染色了,那就是“多生效”。
这两种现象背后,往往不是 HTML 改了,而是选择器本身没对齐结构预期:
-
.card p多生效 → 你本意只想控制卡片正文,但它连.card > header > h2 > small里的small(如果它被误标为p)都管了 -
.card > p全不生效 → 真实 DOM 是<div class="card"><article><p>...</p></article></div>,p的父节点是article,不是.card - 调试时别只看样式面板,要切到 Elements 面板,逐层点开父节点确认关系
.a > .b .c 和 .a .b > .c 完全是两回事
这两个写法看着像,但浏览器解析路径完全不同:.a > .b .c 等价于 (.a > .b) .c,意思是“先找 .a 的直接子 .b,再找这个 .b 里任意深度的 .c”;而 .a .b > .c 是 (.a .b) > .c,意思是“先找 .a 里任意位置的 .b,再找这个 .b 的直接子 .c”。
这种混搭最容易在 SCSS 嵌套里出问题,比如写 & > a 编译成 .nav > a 没问题,但若手写成 .nav > ul li,其实等价于 (.nav > ul) li,它会匹配 .nav > ul 下所有后代 li,而不是你脑补的“ul 的直接子 li”。
真正容易被忽略的,是结构契约本身:用 > 不是为了快,而是为了翻车时能立刻发现 HTML 动了;用空格是信任结构稳定,一旦 DOM 多插一层,它还默默工作,直到某天 .title 在侧边栏突然变色,你才意识到它早该被隔离。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











