目录
6.2 ::first-letter 与 ::first-line
1.前言:为什么“选择”如此重要
在 CSS 的语境里,“选择器”是连接 HTML 与样式的唯一桥梁。一条样式规则能否生效、何时生效、与多少元素匹配,完全取决于选择器的写法。选择器写得精准,代码就精简;写得随意,后期维护就会陷入“抖一抖掉一地”的泥潭。理解选择器,就是理解 CSS 的本质。
2.选择器语法总览:一条规则的三段式
每条 CSS 规则由「选择器」「属性」「值」组成:
selector { property: value; }
浏览器读取样式表时,会先用选择器在 DOM 树中定位节点,再为其应用声明块。选择器越复杂,匹配成本越高,但语义也更精细。
3.基础选择器
3.1 通配选择器 *
*{box-sizing:border-box;}
匹配所有元素,常用于全局重置。但滥用会导致性能下降,应谨慎。
3.2 元素选择器 h1
h1{margin:0;}
按标签名匹配,优先级最低,适合对语义标签做默认样式。
3.3 类选择器 .btn
.btn{padding:.5em 1em;}
以 class 属性值匹配,可复用,是现代 CSS 的核心。
3.4 ID 选择器 #header
#header{background:#111;}
以 id 属性值匹配,特异性极高,通常只用于一次性锚点或 JS 钩子,不建议大规模样式化。
3.5 属性选择器 [type="text"]
input[type="text"]{border:1px solid #aaa;}
按属性值精确、部分或前缀匹配,适合表单控件或国际化。
4.组合选择器
4.1 后代选择器 div p
选中 div 内所有后代 p,无论嵌套多深。
4.2 子选择器 ul > li
只选中 ul 的直接子 li,避免深层污染。
4.3 相邻兄弟选择器 h2 + p
选中紧跟在 h2 后的第一个 p,常用于标题与段落间距。
4.4 通用兄弟选择器 h2 ~ p
选中 h2 后所有同级 p,但不包括更前面的。
4.5 交集与并集
div.box 表示同时满足 div 标签和 box 类;
.btn, .link 表示同时匹配两种选择器,共享样式。
5.伪类选择器
伪类以单冒号 : 开头,用于描述元素在特定状态下的表现。
5.1 链接伪类
a:link{color:blue;}
a:visited{color:purple;}
5.2 行为伪类
button:hover{background:#eee;}
input:focus{outline:2px solid #0066ff;}
5.3 表单伪类
input:invalid{border-color:red;}
5.4 结构伪类
5.4.1 :nth-child()
li:nth-child(odd){background:#f5f5f5;} /* 奇数行 /
li:nth-child(3n){margin-right:0;} / 每 3 个 */
5.4.2 :nth-of-type()
section:nth-of-type(2n+1){clear:left;} /* 同类型元素计数 */
5.4.3 :only-child :empty
p:empty{display:none;}
5.5 其他伪类
:not(.is-active){opacity:.6;} /* 取反 /
:is(h1,h2,h3){line-height:1.2;} / 逻辑或 */
6.伪元素选择器
伪元素以双冒号 :: 开头,用于创建不在 DOM 中的抽象节点。
6.1 ::before 与 ::after
.clearfix::after{content:"";display:block;clear:both;}
6.2 ::first-letter 与 ::first-line
p::first-letter{float:left;font-size:3em;}
6.3 ::selection
::selection{background:#ffdb4d;color:#000;}
7.选择器优先级与层叠
7.1 特异性计算
浏览器按「千位-百位-十位-个位」计算:
• 内联样式 1000
• ID 选择器 0100
• 类、属性、伪类 0010
• 元素、伪元素 0001
例如 #nav .item a:hover 的特异性为 0-1-2-1。
7.2 !important、内联、样式表层叠
!important 强制最高优先级,但破坏层叠规则,仅在变量或工具类中使用。
8.性能与可维护性
8.1 CSS 解析与匹配原理简述
浏览器从右向左匹配,避免在关键路径上使用通配或深层嵌套。
8.2 命名策略
BEM(Block__Element--Modifier)降低特异性冲突;
OOCSS 分离结构与皮肤;
SMACSS 按布局、模块、状态划分文件。
9.未来已来:新草案与实验性选择器
9.1 :has() 伪类
section:has(h1){background:#fafafa;} /* 父选择器 */
9.2 :is() :where() 的优化
:where() 特异性为 0,适合库作者编写无侵入样式。
9.3 容器查询 @container
@container (min-width:300px){.card{padding:1rem;}} /* 基于组件容器而非视口 */
10.实战案例:构建一个可扩展的按钮系统
需求:
• 支持三种尺寸:small、default、large
• 支持三种视觉:primary、secondary、danger
• 支持禁用、加载、图标前后置
HTML:
<button class="btn btn--primary btn--large" disabled>
<a class="btn btn--secondary" href="#"><span class="btn__icon btn__icon--left">Settings
CSS:
.btn{--bg:#f5f5f5;--color:#333;padding:.5em 1em;border:0;border-radius:.25em;font:inherit;cursor:pointer;}
.btn--primary{--bg:#0066ff;--color:#fff;}
.btn--large{padding:.75em 1.5em;font-size:1.25rem;}
.btn:disabled{opacity:.5;cursor:not-allowed;}
.btn__icon{margin-inline:.25em;}
通过 BEM 命名、CSS 变量与伪类组合,实现高可维护性与主题化。
11.结语:在语义、灵活与性能之间平衡
选择器的学习曲线并非陡峭,却需要长期实践去体会其“克制之美”。写得多不如写得准,写得准不如写得可维护。愿你在下一次重构时,因为今天对选择器的理解,而少写 300 行代码,多喝一杯咖啡。