你以为 details/select/dialog 打开状态只能靠 JS 监听?今天 :open 一个伪类把这件事彻底原生化了
写过表单的人都踩过这个坑——每次想给 details 展开、select 打开、dialog 弹出时加点样式,都要靠 JS 监听状态变化,再联动 class,一套下来几十行。今天这件事被一个伪类彻底原生化了。
:open 是 Selectors Level 4 新出的伪类,专门匹配「当前处于打开状态」的元素。哪些元素有打开状态?details(展开/折叠)、select(下拉打开)、dialog(弹窗显示)、input(日期/颜色选择器等 picker)。一个选择器全覆盖,不需要属性选择器,不需要 JS。
基础用法三行替代几十行 JS。details 展开时让 summary 变蓝:
details:open > summary {
color: #2563eb;
font-weight: bold;
}
select 打开时背景变亮、箭头翻转:
select:open {
background-color: #f8f2dc;
}
select:open ~ .arrow {
transform: rotate(180deg);
}
dialog 弹窗打开时加动画入场:
@starting-style {
dialog:open { opacity: 0; }
}
dialog:open {
animation: fade-in 0.3s ease;
}
你可能说这和 [open] 属性选择器有什么区别?区别大了。[open] 匹配的是元素有没有这个属性,:open 匹配的是元素的语义状态。select 打开时的 picker 界面没有 open 属性,但 :open 能匹配;dialog 用 show() 打开时元素有 open 属性,但用 showModal() 打开时 :modal 比 :open 更精确。三套选择器各司其职。
浏览器支持方面,Chrome 133/Firefox 136/Safari 26.5 全部支持,2026 年 2 月进 Baseline,全球覆盖约 85%。渐进增强写法:
@supports not selector(:open) {
details[open] > summary { /* fallback */ }
}
下一个可落地的事:打开任意一个带 details 的页面,F12 试一条 details:open { border-color: var(--brand); },你会发现展开内容的那一刻样式自己变了,不需要任何 JS。
评论区
0 条评论
登录后可评论。