# css 选择器
[toc]
## 1. 简单选择器
### 1.1 种类
| 序号 | 选择器 | 描述 | 举例 |
| ---- | ---------- | --------------------------- | ---------------- |
| 1 | 元素选择器 | 根据元素标签名称进行匹配 | `div {...}` |
| 2 | 群组选择器 | 同时选择多个不同类型的元素 | `h1,h2,h3{...}` |
| 3 | 通配选择器 | 选择全部元素,不区分类型 | `* {...}` |
| 4 | 属性选择器 | 根据元素属性进行匹配 | `*[...]` |
| 5 | 类选择器 | 根据元素 class 属性进行匹配 | `*.active {...}` |
| 6 | id 选择器 | 根据元素 id 属性进行匹配 | `*#top {...}` |
- 元素是使用**标签和属性**进行描述,所以使用标签和属性来选择元素非常自然和直观
- 以上 6 种,其实可分为二类: 元素选择器和属性选择器, 其它的只是二者的特例罢了
- 最常用的是: **元素选择器, 类选择器, id 选择器**
- 当 class,id 选择器不限定被修改的元素类型时, 星号"`*`"可以省略
### 1.2 示例
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>简单选择器</title>
<style>
/* 使用九宫格演示选择器 */
/* 以下grid, flex布局实现一个九宫格,语法未学到请先忽略 */
/* 类选择器 */
.container {
width: 300px;
height: 300px;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 5px;
}
.item {
font-size: 2rem;
background-color: lightskyblue;
display: flex;
justify-content: center;
align-items: center;
}
/* 简单选择器 */
/* 元素选择器 */
body {
background-color: lightcyan;
}
/* 多类选择器 */
.item.center {
background-color: lightgreen;
}
/* id选择器 */
*#first {
background-color: lime;
}
/* id,class默认可添加到所有元素上,所以可省略*/
/* 特别提示: id唯一性由用户保证,浏览器不检查,应确保唯一,防止JS获取失败 */
#first {
background-color: lightpink;
}
/* 为什么id前添加class选择器仍然有效呢,这是选择器的权重: class > 元素 */
.item#first {
background-color: lemonchiffon;
}
/* id的优先级大于class */
#first.item {
background-color: violet;
}
/* 样式权重优先级: 元素 < 类样式 < ID */
</style>
</head>
<body>
<div class="container">
<div class="item" id="first">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item center">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
</div>
</body>
</html>
```
---
## 2. 上下文选择器
- html 文档,看上去就像一颗倒置的"树",所以是有层级结构的
- 每一个元素, 在文档中, 都有自己的位置,即上下文关系
- 所以, 完全可以根据元素的上下文关系,来获取到它们
### 2.1 一个元素的四种角色
| 序号 | 角色 | 描述 |
| ---- | -------- | ------------------------------------- |
| 1 | 祖先元素 | 拥有子元素,孙元素等所有层级的后代元素 |
| 2 | 父级元素 | 仅拥有子元素层级的元素 |
| 3 | 后代元素 | 与其它层级元素一起拥有共同祖先元素 |
| 4 | 子元素 | 与其它同级元素一起拥有共同父级元素 |
### 2.2 四种上下文选择器
| 序号 | 选择器 | 操作符 | 描述 | 举例 |
| ---- | -------------- | ------ | ------------------------------ | ----------------- |
| 1 | 后代选择器 | `空格` | 选择当前元素的所有后代元素 | `div p`, `body *` |
| 2 | 父子选择器 | `>` | 选择当前元素的所有子元素 | `div > h2` |
| 3 | 同级相邻选择器 | `+` | 选择拥有共同父级且相邻的元素 | `li.red + li` |
| 4 | 同级所有选择器 | `~` | 选择拥有共同父级的后续所有元素 | `li.red ~ li` |
### 2.3 示例
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>上下文选择器</title>
<style>
/* 使用九宫格演示选择器 */
/* 以下grid, flex布局实现一个九宫格,语法未学到请先忽略 */
.container {
width: 300px;
height: 300px;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 5px;
}
.item {
font-size: 2rem;
background-color: lightskyblue;
display: flex;
justify-content: center;
align-items: center;
}
/* 后代选择器 */
.container div {
border: 1px solid coral;
}
/* 父子选择器,只有外层容器div受影响,内部单元格div不受影响 */
body > div {
border: 3px solid green;
}
/* 同级相邻选择器 */
/* 当前是第5个,相邻的下一个就是第6个单元格 */
.item.center + .item {
background-color: lightgreen;
}
/* 同级所有选择器 */
.item.center ~ .item {
background-color: lightsalmon;
}
</style>
</head>
<body>
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item center">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
</div>
</body>
</html>
```
---
## 3. 伪类选择器
- 学习之前,先分析上下文选择器的局限性,例如选择同一个父级下的第二个子元素,就没那么简单
- 而伪类就正好弥补了上下文选择器的短板, 所以伪类,大多数是基于文档中元素结构的
- **伪**: 本意是假的,不存在的意思, 这里是特指, 不需要在元素上添加额外的属性来获取元素
- **类**: 暗指伪类的级别, 仍然是属于"class"级别, 仍然属于属性选择器范畴,级别高于元素选择器
我们重点放在伪类最重要的应用场景:
| 场景 | 描述 |
| -------- | ---------------------------- |
| 结构伪类 | 根据子元素的位置特征进行选择 |
| 表单伪类 | 根据表单控件状态特征进行选择 |
### 3.1 结构伪类
#### 3.1.1 不分组匹配
| 序号 | 选择器 | 描述 | 举例 |
| ---- | -------------------- | ------------------------ | ------------------------ |
| 1 | `:first-child` | 匹配第一个子元素 | `div :first-child` |
| 2 | `:last-child` | 匹配最后一个子元素 | `div :last-child` |
| 3 | `:only-child` | 选择元素的唯一子元素 | `div :only-child` |
| 4 | `:nth-child(n)` | 匹配任意位置的子元素 | `div :nth-child(n)` |
| 5 | `:nth-last-child(n)` | 匹配倒数任意位置的子元素 | `div :nth-last-child(n)` |
示例代码:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>结构伪类选择器: 不分组匹配</title>
<style>
/* 使用九宫格演示选择器 */
/* 以下grid, flex布局实现一个九宫格,语法未学到请先忽略 */
.container {
width: 300px;
height: 300px;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 5px;
}
.item {
font-size: 2rem;
background-color: lightskyblue;
display: flex;
justify-content: center;
align-items: center;
}
/* 省略父元素,则是给'html'元素的子元素添加背景,html只有2个子元素:head,body */
:first-child {
background-color: wheat;
}
/* 匹配第一个子元素 */
/* 不指定具体父元素, 则会从html开始依次查询每一个子元素*/
/* 从html开始依次递归获取每一个元素的第一个子元素并添加背景 */
/*<head>, div.container, 第一个div.item 会选中*/
* > :first-child {
background-color: yellow;
}
/* 为防止这种递归设置, 应该在具体父元素上调用 */
.container > :first-child {
background-color: lightgreen;
}
/* 伪类前默认为通用选择器* */
.container > *:first-child {
background-color: lightgreen;
}
/* 可以在伪类前指定具体元素 */
/* 因为大家都有.item类,指不指定无所谓,但权重大于默认的**/
.container > .item:first-child {
background-color: lightgrey;
}
/* 匹配最后一个子元素 */
.container > :last-child {
background-color: lightpink;
}
/* 匹配任意位置的子元素 */
/* 索引是从1开始计数 */
/* 该伪类就是用来获取子元素, 所以选择器中间的 ">"可省略 */
.container :nth-child(3) {
background-color: limegreen;
}
/* :nth-child()的参数可以使用表达式 */
/* 例如选中所有的偶数单元格: 表达式中的 "n" 是从 "0" 开始的整数,且必须写到前面*/
/* 返回的必须是有效的索引,即在(1-9)之间 */
.container :nth-child(2n) {
background-color: magenta;
}
/* (2n)可用关键字even代替 */
.container :nth-child(even) {
background-color: magenta;
}
/* 选中所有的奇数单元格*/
.container :nth-child(2n-1) {
background-color: lightcoral;
}
/* (2n-1)可用关键字odd代替 */
.container :nth-child(odd) {
background-color: lightcoral;
}
/* 为什么第一个奇数单元格会变色,原因是:first-child前用了类选择器,权重高于默认的通用选择器* */
/* 去掉.item:first-child 前面的.item, 背景就会变成"lightcoral" */
/* 也可只选择一部分,例如前三个 */
.container .item:nth-child(-n + 3) {
background-color: lightseagreen;
}
/* 选择倒数第2个 */
.container .item:nth-last-child(2) {
background-color: lime;
}
/* 选择最后3个 */
.container .item:nth-last-child(-n + 3) {
background-color: lime;
}
/* 从指定位置开始选择 */
/* 从第4个单元格开始选择剩下所有元素 */
.container .item:nth-child(n + 4) {
background-color: lightgray;
}
</style>
</head>
<body>
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
</div>
</body>
</html>
```
#### 3.1.2 分组匹配
| 序号 | 选择器 | 描述 | 举例 |
| ---- | --------------------- | ------------------------------------ | -------------------------- |
| 1 | `:first-of-type` | 匹配按类型分组后的第一个子元素 | `div :first-of-type` |
| 2 | `:last-of-type` | 匹配按类型分组后的最后一个子元素 | `div :last-of-type` |
| 3 | `:only-of-type` | 匹配按类型分组后的唯一子元素 | `div :only-of-type` |
| 4 | `:nth-of-type()` | 匹配按类型分组后的任意位置的子元素 | `div :nth-of-type(n)` |
| 5 | `:nth-last-of-type()` | 匹配按类型分组后倒数任意位置的子元素 | `div :nth-last-of-type(n)` |
- 允许使用表达式来匹配一组元素,表达式中的"n"是从"0"开始计数,且必须写到前面
- "-n"表示获取前面一组元素,正数表示从指定位置获取余下元素
示例代码:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>结构伪类选择器: 分组匹配</title>
<style>
/* 使用九宫格演示选择器 */
/* 以下grid, flex布局实现一个九宫格,语法未学到请先忽略 */
.container {
width: 300px;
height: 300px;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 5px;
}
.item {
font-size: 2rem;
background-color: lightskyblue;
display: flex;
justify-content: center;
align-items: center;
}
/* 选中第一个span元素: 匹配不上 */
.container span:first-child {
background-color: violet;
}
/* 换成first-of-type, 就匹配上了 */
.container span:first-of-type {
background-color: violet;
}
/*
所谓分组匹配其实有二步:
第一步: 对满足条件的元素进行分组
第二步: 在分组中根据位置匹配元素
*/
/* 匹配分组中的最后一个 */
.container span:last-of-type {
background-color: violet;
}
/* 匹配任何一个 */
.container span:nth-of-type(3) {
background-color: violet;
}
/* 支持表达式: 匹配前3个 */
.container span:nth-of-type(-n + 3) {
background-color: lightgrey;
}
/* 匹配最后2个 */
.container span:nth-last-of-type(-n + 2) {
background-color: limegreen;
}
</style>
</head>
<body>
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<!-- 修改dom结构,最后二排使用span元素 -->
<span class="item">4</span>
<span class="item">5</span>
<span class="item">6</span>
<span class="item">7</span>
<span class="item">8</span>
<span class="item">9</span>
</div>
</body>
</html>
```
### 3.2 表单伪类
| 序号 | 选择器 | 描述 |
| ---- | ---------------- | ------------------------------- |
| 1 | `input:enabled` | 选择每个启用的 `<input>` 元素 |
| 2 | `input:disabled` | 选择每个禁用的 `<input>` 元素 |
| 3 | `:checked` | 选择每个被选中的 `<input>` 元素 |
| 4 | `:required` | 包含`required`属性的元素 |
| 5 | `:optional` | 不包含`required`属性的元素 |
| 6 | `:valid` | 验证通过的表单元素 |
| 7 | `:invalid` | 验证不通过的表单 |
| 8 | `:read-only` | 选择只读表单元素 |
示例代码:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>表单伪类选择器</title>
<style>
form {
display: flex;
flex-flow: column nowrap;
}
/*表单伪类选择器*/
/*选择所有有效的input表单元素*/
/*下拉列表虽有效,但不是input,所以未选中*/
/*警告信息是禁用项, 所以未选中*/
/*保存密码项实际上选中的, 通过检查元素可以查询*/
input:enabled {
background-color: blanchedalmond;
}
/*选择禁用元素*/
input:disabled {
background-color: lightgray;
}
/*选择所有必选项*/
input:required {
background-color: yellow;
}
/*更多选项, 供大家上机练习*/
</style>
</head>
<body>
<h3>用户登录</h3>
<form action="" method="post">
<div>
<label for="email">邮箱:</label>
<input type="email" id="email" name="email" required placeholder="example@email.com" />
</div>
<div>
<label for="password">密码:</label>
<input type="password" id="password" name="password" required placeholder="不得少于6位" />
</div>
<div>
<label for="save">保存密码:</label>
<input type="checkbox" id="save" name="save" checked readonly />
</div>
<div>
<label for="save_time">保存期限:</label>
<select name="save_time" id="save_time">
<option value="7" selected>7天</option>
<option value="30">30天</option>
</select>
</div>
<div>
<input type="hidden" name="login_time" value="登陆时间戳" />
</div>
<div>
<label for="warning">警告:</label>
<input type="text" id="warning" value="一天内仅允许登录三次" style="border:none" disabled />
</div>
<script>
// js未学,暂时忽略,只须知道功能即可: 自动生成时间戳,填充到表单隐藏域中
document.querySelector('[type="hidden"]').value = new Date().getTime();
</script>
</form>
</body>
</html>
```
### 3.3 其它伪类
| 序号 | 选择器 | 描述 |
| ---- | ---------- | -------------------------------------- |
| 1 | `:active` | 向被激活的元素添加样式 |
| 2 | `:focus` | 向拥有键盘输入焦点的元素添加样式 |
| 3 | `:hover` | 当鼠标悬浮在元素上方时,向元素添加样式 |
| 4 | `:link` | 向未被访问的链接添加样式 |
| 5 | `:visited` | 向已被访问的链接添加样式 |
| 5 | `:root` | 根元素,通常是`html` |
| 5 | `:empty` | 选择没有任何子元素的元素(含文本节点) |
| 5 | `:not()` | 排除与选择器参数匹配的元素 |
示例代码:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>其它伪类</title>
<style>
/*根元素*/
:root {
background-color: lightcyan;
}
/*排除元素*/
nav * {
/*background-color: lightgreen;*/
}
/*排除掉第一个:首页*/
nav :not(:first-child) {
background-color: lightgreen;
}
/*空元素*/
nav :empty {
display: inline-block;
height: 20px;
width: 100px;
background-color: yellow;
}
/*链接伪类*/
a:hover {
background-color: #444444;
color: white;
}
a:active,
a:focus {
background-color: red;
}
a:visited {
background-color: yellow;
color: red;
}
</style>
</head>
<body>
<nav>
<a href="">首页</a>
<a href="">视频教程</a>
<a href="">社区问答</a>
<a href="">工具软件</a>
<!-- <a href=""></a>-->
</nav>
</body>
</html>
```
### 3.4 伪元素
- 伪元素, 顾名思义, HTML 源码并不存在, 而是通过 CSS 添加的
- 主要用于修饰某些元素,添加效果,但又不希望占用元素资源
- 通常与`content`属性配合使用
| 序号 | 选择器 | 描述 |
| ---- | ---------- | ------------------ |
| 1 | `::after` | 在当前元素之后添加 |
| 2 | `::before` | 在当前元素之前添加 |
示例代码:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>伪元素</title>
<style>
/*不会出现在DOM结构中, 不占用页面空间*/
a::before {
content: "Hello ";
}
a::after {
/*content: ' 欢迎您~~';*/
}
/*可调用当前元素的属性*/
a::after {
content: "--" attr(href) "--";
}
/*可以插入图片*/
a:before {
content: url("1.jpg");
/*图片样式可使用JS修改*/
}
</style>
</head>
<body>
<a href="htts://www.php.cn">php中文网</a>
</body>
</html>
```
- 教学大纲
- HTML5基础
- 1-html基础知识
- 2-语义化结构元素
- 3-语义化文本元素
- 4-链接/列表/图像元素
- 5-表格元素
- 6-表单与控件元素[重点]
- CSS3基础
- 1-css与html文档
- 2-css选择器
- 3-细说盒模型
- Flex布局[精简版]
- 1-Flex概论
- 2-Flex布局是什么
- 3-Flex基本概念
- 4-Flex容器属性
- 5-Flex项目属性
- Flex布局[细说版]
- 1-flex 布局概述
- 2-flex 容器与项目
- 3-flex 容器主轴方向
- 4-flex 容器主轴项目换行
- 5-flex 容器主轴与项目换行简写
- 6-flex 容器主轴项目对齐
- 7-flex 容器交叉轴项目对齐
- 8-flex 多行容器交叉轴项目对齐
- 9-flex 项目主轴排列顺序
- 10-flex 项目交叉轴单独对齐
- 11-flex 项目放大因子
- 12-flex 项目收缩因子
- 13-flex 项目计算尺寸
- 14-flex 项目缩放的简写
- Flex布局[案例版]
- 1-调整项目顺序
- Grid布局[精简版]
- 1. 常用术语
- 2. 容器属性
- 3. 项目属性
- 4. 布局实例
- 1. 经典三列布局
- 2. 媒体查询
- Grid布局[细说版]
- 1-必知术语
- 2-容器创建与行列划分
- 3-单元格常用单位
- 4-项目填充到单元格
- 5-项目填充到网格区域
- 6-对齐容器中的所有项目
- 7-对齐单元格中所有项目
- 8-对齐单元格中某个项目
- 9-容器中行与列之间的间距