ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
# 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> ```