先有卡片和复选框
<article class="choice"> 是整张卡片;内部的 input 是复选框。label 包裹复选框和文字,因此点击“参加唱腔赏析”也能切换选中状态。
.choice 设置卡片的默认样式:padding 留出内边距,border 设置灰色实线边框。
勾选“参加唱腔赏析”,观察整张卡片的边框和背景;再取消勾选,看看它们怎样变化。
<style>
.choice {
padding: 22px;
border: 3px solid #aebfc2;
}
.choice:has(input:checked) {
border-color: teal; /* 青绿色 */
background: #def3e9; /* 浅绿色 */
}
</style>
<article class="choice">
<label>
<input type="checkbox"> 参加唱腔赏析
</label>
<p>周三 14:00 · A208</p>
</article>
<article class="choice"> 是整张卡片;内部的 input 是复选框。label 包裹复选框和文字,因此点击“参加唱腔赏析”也能切换选中状态。
.choice 设置卡片的默认样式:padding 留出内边距,border 设置灰色实线边框。
input:checked 匹配当前已勾选的复选框。.choice:has(input:checked) 可以读作:“选中内部包含已勾选复选框的 .choice 卡片”。
样式作用于整张卡片,不是复选框。:has(...) 中的内容是筛选条件,外面的 .choice 才是本例的样式目标。
勾选后,第二条规则匹配卡片:border-color: teal 把边框改为青绿色,background: #def3e9 把背景改为浅绿色。
取消勾选后,第二条规则不再匹配,卡片恢复默认的灰色边框和原背景。这项变色效果由 CSS 完成,不需要 JavaScript 处理点击事件。
把规则改成 .choice input:checked { background: teal; },是否仍会让整张卡片变色?
不会。后代选择器直接匹配 input,:has() 则在筛选外层 .choice。样式施加在哪个元素上,要看整个选择器的匹配目标,而不是只看条件中出现了谁。
现代关系选择器::has()。它扩展匹配条件,不负责保存报名或提交数据。
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>关系伪类 :has():根据勾选状态改变卡片样式</title>
<style>
body { margin:16px; color:#183347; background:white; font:20px/1.5 "Times New Roman",SimSun,serif; }
h1,h2 { font-family:"Times New Roman",SimHei,sans-serif; }
button,input,select { font:inherit; max-width:100%; }
button { margin:4px 0; cursor:pointer; }
pre { white-space:pre-wrap; overflow-wrap:anywhere; font:18px/1.5 Consolas,SimSun,monospace; }
:focus-visible { outline:3px solid #b56220; outline-offset:3px; }
.choice { padding:22px; border:3px solid #aebfc2; }
.choice:has(input:checked) { border-color:teal; background:#def3e9; }
</style>
</head>
<body>
<article class="choice">
<label>
<input type="checkbox"> 参加唱腔赏析</label>
<p>周三 14:00 · A208</p>
</article>
<p id="support">
</p>
<script>
document.querySelector('#support').textContent = CSS.supports('selector(:has(*))') ? '当前浏览器支持 :has()。' : '当前浏览器不支持 :has(),复选框仍可选择。';
</script>
</body>
</html>