:is() / :where():把选择器体积收敛掉.lead 也命中
/* 展开写法:4 个前缀 × 3 个后缀 = 12 条 */
.card .title, .card .meta, .panel .title, .panel .meta, … { font-weight: 700; }
/* 收敛写法:一条 */
:is(.card, .panel) :is(.title, .meta) { font-weight: 700; }
/* 唯一但关键的差别:权重
:is(A, B) 的权重 = 参数里最高的那个 → (0,1,0)
:where(A, B) 的权重 = 0 → 适合写「组件默认样式、使用方随手可覆盖」 */
:where(h2, h3) { color: purple; } /* 任何 .x h2 都能盖过它 */
解析风险::is() 里出现浏览器无法解析的部分会导致整条规则失效;:where() 同样严格。所以不要把「很新的选择器」塞进 :is() 参数里当降级手段,那种情况用 @supports 或独立规则。
:has():真正的父向选择器.badge 的子项3.item:has(input:checked) { border-color: #0969da; } /* 状态上移到容器 */
.card:has(img) { padding-top: 0; } /* 有封面图的卡片去掉顶部留白 */
li:has(> ul) { font-weight: 700; } /* 「有子列表」的项加粗 */
.tr:has(.cell__total) { background: #fff8c5; }
body:has(#search:focus) .hero { opacity: .35; } /* 页面级联动:谨慎使用,性能与可读性都要克制 */
/* 参数里可以写相对关系:
:has(+ .next) 后面紧跟某元素的兄弟
:has(~ .x) 之后同级存在 .x
:has(> .x) 直接子元素 */
浏览器基线::has() 已在 Chrome / Edge / Safari / Firefox 全量支持(Firefox 121 起),属 Baseline 可用;它会让浏览器在结构变化时重算,避免在超大列表上写高成本的选择器链。
:not() 可以传多个参数/* 老写法只能一个参数,得串联 */
.btn:not(.primary):not([disabled]) { … }
/* 新写法逗号即可(等价 and) */
.btn:not(.primary, [disabled]) { … }
/* 权重仍取 :not 内部最高项(不是 0),别把它当 :where 用 */
:nth-child(An+B of S):在「某类元素里」数第几个li:nth-child(2 of .tag) { color: #bf8700; } /* 「.tag 里的第 2 个」 */
li:nth-child(odd of :is(.tag, .note)) { … } /* 在两个类的合集里奇偶交替 */
tr:nth-child(3n of td.has-total) { … } /* 常见旧需求:跳过表头后再算奇偶 */
以前要实现它只能让 JS 加类。浏览器基线:这一形态同样已是主流内核全量支持,Firefox 113 / Chrome 111 / Safari 9 一线起。
用鼠标点下面两个控件不会看到焦点环;按 Tab 键盘移动时才会出现 —— 这正是 :focus-visible 的用途。
结构类与语言类示例:下面列表的首项加粗、末两项变蓝(:first-child / :nth-last-child(-n+2));同一句话按 lang 不同走不同字形规则(:lang());点这个锚点会看到 :target 把目标条变黄。
日本語のテキスト:行間に調整が必要
中文文本:字距略微拉开更易读
:target 命中时才有的高亮条
| 选择器 | 含义 |
|---|---|
:focus-visible | 只在「浏览器认为该显示焦点环」时命中(键盘导航),替代写死的 outline: none |
:focus-within | 后代任一元素获得焦点时命中容器,做搜索框整块高亮很省 |
:valid / :invalid | 表单校验状态,但「未交互的空必填项」也算 invalid |
:user-invalid | 只在用户改过之后才判无效(Chrome 119 / Safari 16.5 / Firefox 88 一线),比 invalid 更合适做红框 |
:placeholder-shown | 浮动 label 的老配方(现在更推荐 :has() 或 :not(:placeholder-shown)) |
:checked / :default / :indeterminate | 半选状态 :indeterminate 只能由 JS 设置 |
:open | <details> 展开时命中,纯 CSS 折叠面板的状态源 |
:empty | 无子节点且无文本(注意空白字符会影响判定) |
:target | URL 的 hash 指向它时命中,做「定位高亮」零成本 |
:nth-last-child(-n+2) | 倒数两项 |
:lang(zh) | 按 lang 属性匹配,中文/日文的标点与字体差异靠它 |
calc() 与它的兄弟函数calc(100% - 2 * 16px)calc(1rem + 0.5vw)max(12px, calc((100% - 640px) / 2))calc(var(--n) * 6px)/* 混合单位必须靠 calc():100% 与 16px 不能直接相减写在声明里 */
.el { width: calc(100% - 2 * var(--gutter)); }
/* 规则:+ - 两侧要空格;* / 的数字必须是纯数字,不能带单位 */
/* 常见错:calc(10px*2) 在部分老内核里因缺空格被当成属性值解析失败 */
.el { width: calc(100% / 3 - 8px); }
.el { font-size: clamp(1rem, calc(0.9rem + 0.4vw), 1.1rem); } /* 第十三章 */
/* round()/mod()/sign()/hypot()/tan() 等数学函数已进入主流内核,用之前先 @supports 检查 */
:has() 实现「需要 JS 才能算出的业务状态」——状态本身该由 JS 写类,选择器只是表达样式。:is() 里混入不支持的选择器,导致整条规则被丢弃(见①的风险说明)。:scope、命名 @scope 做常规样式:仍在演进,写教程外的项目里请谨慎。