跳到主要内容

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 选择器#header100
类、属性、伪类.nav, [type], :hover10
元素、伪元素div, ::before1
通配符*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: 选择器不生效?

  1. 检查选择器是否正确
  2. 确认 CSS 文件是否被正确引入
  3. 检查是否有更高优先级的规则
  4. 使用浏览器开发者工具调试

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 元素 */
}

小结

本章学习了:

  1. 基本选择器:元素、类、ID、属性选择器
  2. 组合选择器:后代、子、相邻兄弟、通用兄弟
  3. 伪类选择器:状态、结构、表单伪类
  4. 伪元素选择器:::before、::after 等
  5. 优先级计算:如何确定样式的应用顺序

练习

  1. 使用不同类型的选择器选择页面元素
  2. 实现一个带斑马纹和悬停效果的表格
  3. 创建一个导航菜单,包含悬停效果
  4. 使用 nth-child 实现复杂的列表样式
  5. 计算选择器的优先级并验证