《CSS修仙传:第一篇·选择器法则篇》
楔子:!important之祸
"砰!"
青云门藏经阁内,我的茶杯突然炸裂。滚烫的茶水溅在刚写好的样式表上,墨迹晕染开来。
"又用!important?!"林惊羽师姐的剑尖抵着我的喉咙,剑身上反射着控制台的红光:"第五次了!你知道这会导致什么后果吗?"
我颤抖着看向自己写的代码:
css
复制
.button {
color: red !important;
/* 后面300行样式 */
}
.modal .button {
color: blue; /* 无效! */
}
第一章:选择器权重论道
1.1 权重计算的秘密
林师姐的剑尖在空中划出一道CSS规则:
css
复制
#main .list > li:hover {}
"看好了,这就是标准的'四段权重'计算法:"
| 选择器部分 | 权重值 | 计算原理 |
|---|---|---|
#main | 0100 | ID选择器 |
.list | 0010 | 类/属性/伪类选择器 |
> | 0000 | 组合器不计权重 |
li | 0001 | 元素/伪元素选择器 |
:hover | 0010 | 伪类 |
| 总计 | 0111 | 非十进制!256进制体系 |
"记住这个公式:"师姐的剑在空中写出金光公式:
复制
Specificity = a*256² + b*256 + c
"浏览器实际比较时会用256进制,这就是为什么11个class也打不过1个id"
1.2 伪类选择器的陷阱
正当我领悟时,藏经阁突然震动。魔教妖人用:has()伪类攻击护山大阵!
"快用:where()化解!"师姐急喝。我连忙结印:
css
复制
/* 传统写法 - 权重 0,2,0 */
div:not(.active), section:not(.active) {}
/* 高阶写法 - 权重 0,1,0 */
:where(div, section):not(.active) {}
"看好了:"师姐演示DevTools的性能分析:
复制
1000次匹配耗时:
:not()传统写法 → 12.4ms
:where()优化写法 → 8.7ms
1.3 属性选择器的正则艺术
魔教妖人祭出[data-^="btn"]攻击,师姐冷笑:"让你见识真正的属性选择器!"
css
复制
/* 精准匹配 */
[data-type="primary"] {}
/* 开头匹配 */
[data-type^="pr"] {}
/* 包含匹配 */
[data-type*="ima"] {}
/* 结尾匹配 */
[data-type$="ary"] {}
/* 空格分隔匹配 */
[data-type~="pri"] {}
/* 连字符匹配 */
[data-type|="en"] {}
"注意:"师姐突然严肃,"属性选择器在IE..."
"我知道!"我抢答,"在IE要用getAttribute()polyfill!"
第二章:Shadow DOM的破阵之法
2.1 ::part()穿透术
魔教祭出Web Component法宝,样式完全隔离。师姐咬破手指,在空中画出鲜血符咒:
css
复制
custom-element::part(inner) {
color: red;
}
对应组件内部:
html
复制
<div part="inner">可被样式穿透</div>
运行 HTML
2.2 ::slotted()传功大法
"再看这个!"师姐剑光分化:
css
复制
::slotted(.item) {
transform: scale(1.1);
}
"此术只能影响slot分发的内容,对组件内部无效"
第三章:@scope的结界之术
危急时刻,掌门道玄真人出手,施展CSS最新秘法:
css
复制
@scope (.card) to (.footer) {
:scope {
border: 1px solid;
}
p {
color: #333;
}
}
"此术可创建样式结界,避免污染全局!"
性能心诀
掌门传我四句真言:
复制
选择器右起左查
避免通配如避蛇
伪类慎用位置判
ID最快类次之
实战:重写护山大阵
最终我重写护山大阵样式:
css
复制
/* 旧式(权重 0,2,1) */
div.container ul.list > li {}
/* 新式(权重 0,1,0) */
:where([data-component="list"]:not([hidden])) > :is(li, dt) {}
/* 添加Shadow穿透 */
::part(list-item) {
--highlight: oklch(75% 0.3 145);
}
/* 作用域隔离 */
@scope (.spell-area) {
button { animation: glow 2s infinite; }
}
渡劫测验
- 计算选择器权重:
#app .list > [data-index]:not(:first-child) - 用
:where()优化:header > nav, aside > nav - 实现一个可穿透样式的Web Component按钮
- 解释为什么
[class^="btn"]比.btn-primary性能更好
(答案见GitHub仓库:github.com/css-immorta…
下篇预告:《布局真解篇》- Flex与Grid的时空法则,contain-intrinsic-size如何破解异步加载布局抖动,subgrid如何实现完美圣杯布局...