CSS 选择器
选择器是 CSS 的核心概念,用于精确地选择需要样式化的 HTML 元素。本章将详细介绍各种类型的选择器。
选择器基础
选择器语法
选择器 {
属性: 值;
}
选择器决定了哪些 HTML 元素会被选中并应用样式。
基本选择器
1. 元素选择器
直接通过标签名选择元素:
/* 选择所有段落 */
p {
color: #333;
}
/* 选择所有标题 */
h1, h2, h3 {
color: #2c3e50;
}
/* 通配符选择器 - 选择所有元素 */
* {
margin: 0;
padding: 0;
}
2. 类选择器
使用点号(.)选择带有特定 class 的元素:
/* HTML: <div class="container"></div> */
.container {
width: 1000px;
}
/* HTML: <p class="intro highlight"></p> */
.intro {
font-size: 18px;
}
.highlight {
background: yellow;
}
/* 组合:同时有 intro 和 highlight */
.intro.highlight {
font-weight: bold;
}
多类名的用法:
<p class="intro highlight">同时应用两种样式</p>
<p class="intro">只应用 intro 样式</p>
3. ID 选择器
使用井号(#)选择带有特定 id 的元素:
/* HTML: <header id="main-header"></header> */
#main-header {
background-color: #3498db;
padding: 20px;
}
/* ID 选择器优先级最高 */
#unique-element {
color: red;
}
注意
- id 在页面中应该是唯一的
- 建议优先使用类选择器而非 ID 选择器
- ID 选择器在 JavaScript 中更常用
4. 属性选择器
根据元素的属性和属性值选择元素:
/* 有指定属性的元素 */
[disabled] {
opacity: 0.5;
}
/* 指定属性等于某值 */
[type="text"] {
border: 1px solid #ccc;
}
/* 指定属性包含某值 */
[class*="icon"] {
/* 选择 class 包含 "icon" 的元素 */
}
/* 指定属性以某值开头 */
[href^="https"] {
/* 选择 href 以 "https" 开头的链接 */
}
/* 指定属性以某值结尾 */
[href$=".pdf"] {
/* 选择 href 以 ".pdf" 结尾的元素 */
}
属性选择器完整列表:
| 选择器 | 说明 |
|---|---|
[attr] | 有该属性 |
[attr="value"] | 属性等于值 |
[attr~="value"] | 属性值包含(空格分隔) |
| `[attr | ="value"]` |
[attr^="value"] | 属性值开头 |
[attr$="value"] | 属性值结尾 |
[attr*="value"] | 属性值包含 |
组合选择器
1. 后代选择器(空格)
选择某元素内部的所有指定后代:
/* article 内的所有段落(包括嵌套的) */
article p {
line-height: 1.8;
}
/* nav 内的所有链接 */
nav a {
color: white;
text-decoration: none;
}
2. 子选择器(>)
只选择直接子元素:
/* article 直接子元素的段落 */
article > p {
margin-top: 20px;
}
/* nav 的直接子元素 li */
nav > ul > li {
display: inline-block;
}
对比示例:
<article>
<p>直接子元素 - 会被 > 选择器选中</p>
<div>
<p>嵌套的段落 - 不会被 > 选择器选中</p>
</div>
</article>
3. 相邻兄弟选择器(+)
选择紧接在某元素后的第一个兄弟元素:
/* h1 后紧接的第一个段落 */
h1 + p {
font-size: 18px;
color: #666;
}
4. 通用兄弟选择器(~)
选择某元素后的所有兄弟元素:
/* h2 后的所有段落 */
h2 ~ p {
color: #444;
}
伪类选择器
伪类用于选择元素的特定状态:
状态伪类
/* 未访问的链接 */
a:link {
color: blue;
}
/* 已访问的链接 */
a:visited {
color: purple;
}
/* 鼠标悬停 */
a:hover {
color: red;
}
/* 获得焦点的元素 */
input:focus {
border-color: #3498db;
}
/* 激活/点击的元素 */
button:active {
background-color: #2980b9;
}
效果预览: 当鼠标悬停在链接上时,背景颜色会变为 #3498db(蓝色),文字变白,边角变为圆角。
结构伪类
/* 第一个子元素 */
li:first-child {
border-top: none;
}
/* 最后一个子元素 */
li:last-child {
border-bottom: none;
}
/* 唯一的子元素 */
p:only-child {
/* 只有一个子元素的 p */
}
/* 第 n 个子元素 */
tr:nth-child(odd) {
background: #f9f9f9;
}
tr:nth-child(2n) {
/* 偶数行 */
}
tr:nth-child(2n+1) {
/* 奇数行 */
}
/* 倒数第 n 个子元素 */
li:nth-last-child(2) {
/* 倒数第二个 li */
}
nth-child 表达式:
| 表达式 | 说明 |
|---|---|
:nth-child(2) | 第2个 |
:nth-child(even) | 偶数 |
:nth-child(odd) | 奇数 |
:nth-child(3n) | 3的倍数 |
:nth-child(n+3) | 从第3个开始 |
:nth-child(-n+3) | 前3个 |
:nth-child(2n+1) | 奇数(等价于 odd) |
表单伪类
/* 启用的输入框 */
input:enabled {
background: white;
}
/* 禁用的输入框 */
input:disabled {
background: #eee;
}
/* 选中的复选框/单选框 */
input:checked {
outline: 2px solid #3498db;
}
/* 有必填标记的输入框 */
input:required {
border-color: red;
}
/* 通过验证的输入框 */
input:valid {
border-color: green;
}
/* 未通过验证的输入框 */
input:invalid {
border-color: red;
}
其他伪类
/* 空的元素 */
div:empty {
display: none;
}
/* 不是指定元素的元素 */
p:not(.intro) {
/* 所有不是 .intro 的段落 */
}
/* 没有子元素的容器(忽略文本节点) */
ul:empty::after {
content: "暂无内容";
}
/* 指定语言的元素 */
p:lang(zh) {
/* 中文段落 */
}
伪元素选择器
伪元素用于样式化元素的特定部分:
::before 和 ::after
/* 在元素内容前插入 */
h1::before {
content: "★ ";
color: gold;
}
/* 在元素内容后插入 */
h1::after {
content: " ★";
color: gold;
}
/* 实用示例:清除浮动 */
.clearfix::after {
content: "";
display: block;
clear: both;
}
/* 实用示例:添加特殊标记 */
.required::after {
content: "*";
color: red;
}
其他伪元素
/* 首字母 */
p::first-letter {
font-size: 2em;
font-weight: bold;
}
/* 首行 */
p::first-line {
text-transform: uppercase;
}
/* 选择文本时的高亮 */
::selection {
background: #3498db;
color: white;
}
/* 占位符文字 */
input::placeholder {
color: #999;
}
选择器优先级
优先级计算
CSS 选择器的优先级( specificity )由以下三部分组成:
| 等级 | 选择器 | 优先级 |
|---|---|---|
| 内联样式 | style="..." | 1000 |
| ID 选择器 | #header | 100 |
| 类、属性、伪类 | .nav, [type], :hover | 10 |
| 元素、伪元素 | div, ::before | 1 |
| 通配符 | * | 0 |
/* 优先级:0,1,0 = 10 */
div { }
/* 优先级:0,1,1 = 11 */
div::first-letter { }
/* 优先级:0,1,1 = 11 */
div:hover { }
/* 优先级:0,2,0 = 20 */
.nav:hover { }
/* 优先级:0,1,2 = 12 */
nav ul li { }
/* 优先级:0,1,1 = 11 */
.nav a { }
/* 优先级:0,1,2 = 12 */
.nav a:hover { }
/* 优先级:1,0,0 = 100 */
#header { }
/* 优先级:1,0,2 = 102 */
#header nav a { }
/* 优先级:1,1,0 = 110 */
#header.nav { }
!important 规则
/* 最高优先级,会覆盖其他所有规则 */
.element {
color: red !important;
}
慎用 !important
- 它会打破 CSS 的正常优先级规则
- 使代码难以维护
- 只有在万不得已时使用
选择器组合示例
完整导航菜单
/* 基础链接样式 */
.nav a {
display: block;
padding: 10px 15px;
color: #333;
text-decoration: none;
}
/* 悬停效果 */
.nav a:hover,
.nav a:focus {
background: #3498db;
color: white;
}
/* 当前页面链接 */
.nav a.current {
background: #2c3e50;
color: white;
}
/* 下拉菜单 */
.nav li:hover > ul {
display: block;
}
表格样式
/* 基本表格 */
table {
width: 100%;
border-collapse: collapse;
}
/* 表头 */
thead th {
background: #2c3e50;
color: white;
font-weight: bold;
}
/* 斑马纹 - 奇数行 */
tbody tr:nth-child(odd) {
background: #f9f9f9;
}
/* 悬停行 */
tbody tr:hover {
background: #e8f4fc;
}
/* 表格单元格 */
th, td {
padding: 12px;
border: 1px solid #ddd;
text-align: left;
}
/* 第一列 */
td:first-child {
font-weight: bold;
}
实用技巧
1. CSS Reset
/* 简单版 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* 现代版(推荐) */
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
margin: 0;
}
2. 调试选择器
/* 临时给所有元素加边框 */
* {
outline: 1px solid red;
}
/* 只给特定区域加边框 */
.debug-section * {
outline: 1px solid red;
}
3. 高效选择器
/* 推荐:使用 class */
.button { }
/* 避免:深层嵌套 */
.nav ul li a span { }
/* 推荐:限制层级 */
.nav-link { }
/* 推荐:组合选择器 */
.nav-item,
.footer-item { }
常见问题
Q: 选择器不生效?
- 检查选择器是否正确
- 确认 CSS 文件是否被正确引入
- 检查是否有更高优先级的规则
- 使用浏览器开发者工具调试
Q: nth-child 和 nth-of-type 的区别?
/* nth-child: 按元素位置计算 */
div p:nth-child(2) {
/* 第2个子元素,且是 p 元素 */
}
/* nth-of-type: 只计算指定类型的元素 */
div p:nth-of-type(2) {
/* 第2个 p 元素 */
}
小结
本章学习了:
- 基本选择器:元素、类、ID、属性选择器
- 组合选择器:后代、子、相邻兄弟、通用兄弟
- 伪类选择器:状态、结构、表单伪类
- 伪元素选择器:::before、::after 等
- 优先级计算:如何确定样式的应用顺序
练习
- 使用不同类型的选择器选择页面元素
- 实现一个带斑马纹和悬停效果的表格
- 创建一个导航菜单,包含悬停效果
- 使用 nth-child 实现复杂的列表样式
- 计算选择器的优先级并验证