我已经使用CSS多年了,但直到最近我才深入研究了一下CSS选择器。

我为什么要这样做呢?我们都知道选择器,但麻烦的是随着时间的推移,很容易习惯于在每个项目中使用相同的可信任选择器来实现你需要做的事情。

所以我就对CSS选择器进行了深入的回顾,并且遇到了一些有趣的,对我来说是新的或者以前不知道的一些用法。

我还发现了一些很酷的新选择器,将来可用但尚未被广泛支持。

组合选择器

让我们从熟悉的领域开始。组合选择器用于选择后代元素、子元素以及兄弟元素,并且已经存在了很长一段时间。

  • 后代选择器 A B

  • 子元素选择器 A>B

  • 相邻兄弟选择器 A+B

  • 通用兄弟选择器 A~B

相邻兄弟选择器 A+B 你应该很熟悉,选择紧跟在 A 之后的元素 B,但是通用兄弟选择器 A~B 呢? 这将选择所有跟在 A 之后的兄弟元素 B

参看下面的一个例子:

(codepen链接:https://codepen.io/dgwyer/embed/RyvYXd)

New York被选中是因为它紧跟在第一行之后,最后两个城市被突出显示,因为通用兄弟选择器匹配了第四行之后的所有城市。

属性选择器

我非常喜欢属性选择器。当你需要匹配包含具有特定属性值的元素时,它们非常灵活。

(codepen链接:https://codepen.io/dgwyer/embed/MGLZEK)

这个例子演示了如何选择所有 type="checkbox" 的元素并将其关联标签设置样式,使其变为粗体和蓝色。

然后,选择其中 name="chk2" 元素并将其关联标签改为红色。

属性选择器不仅适用于表单元素,它们还可以匹配任何元素的属性,并且在非官方支持的属性上也可应用。此外,还可以检查属性是否存在,参看下面的一个例子:

button[icon]

匹配 <button> 标签中有 icon 属性存在的元素 ,不论 icon 属性是否有值。

更多相关的例子:

(codepen链接:https://codepen.io/dgwyer/embed/pVGGye)

第一个链接没有 target 属性,因此不匹配。 接下来的两个链接是匹配的,因为它们都具有 target 属性,并一个有特定值,一个没有值。 最后一个链接设置为粉红色,因为它具 fluffy 属性。

一个实用的例子,突出显示没有 alt 属性的图像。 此属性是可访问性所必需的,因此对于SEO而言,确保所有图像元素都包含此属性非常重要。

我们可以使用以下代码来实现:

img:not([alt]) {
border: 2px red dashed;
}

(codepen链接:https://codepen.io/dgwyer/embed/OZdqLp)

如果要匹配属性值部分,则可以使用以下方法。

  • A[attr^=val] 属性值以val开头。

  • A[attr|=val] 属性值等于val或者以“val-”开头;

  • A[attr$=val] 属性值以val结束。

  • A[attr*=val] 属性值中包含了val;

  • A[attr~=val] 属性值是一个词列表,并且以空格隔开,其中词列表中包含了一个val词。

以下包含了相对应的每个例子:

(codepen链接:https://codepen.io/dgwyer/embed/MGLdvE)

前两个实例非常相似,其中 A[attr|=val] 匹配“val-”开头的这个特性,对于匹配语言属性很有用,例如: <plang=“en-us”>

[attr$=val] 可以轻松匹配文件扩展名,并且配合 ::after 把匹配到文件属性值显示在页面上。

A[attr*=val] 无论使用何种协议或子域,都可以匹配到含有 mysite 域名的元素。

最后 A[attr~=val] 它非常适合匹配由空格分隔的属性值,因为它只匹配整个单词而不是单词片段。

以上所有属性选择器实例都区分大小写。 但是我们有一个技巧, 如果我们在结束方括号之前插入一个i,我们可以不区分大小写进行匹配。

(codepen链接:https://codepen.io/dgwyer/embed/LmaYzp)

除Internet Explorer和Microsoft Edge外,大多数主流浏览器都支持这种不区分大小写的匹配方法。

用户界面选择器

如果你处理过表单样式,那么你之前一定遇到过这些伪类选择器:

  • :enabled 启用状态(可激活或获取焦点)的元素。

  • :disabled 禁用状态的元素。

  • :checked 选中状态的元素。

例如,我们使用 :checked 来实现一个简单的待办事项列表。

(codepen链接:https://codepen.io/dgwyer/embed/BxbjoO)

这些是比较常用到的,还有其他一些有趣的伪类选择器。

:default 可以匹配一个或多个元素,这些元素是一组相关元素中默认的元素。

(codepen链接:https://codepen.io/dgwyer/embed/ELMoNK)

下面的伪类选择器可以匹配输入值是否有效,以及在提交表单之前检查必填项是否填写。

  • :valid 内容验证正确的元素。

  • :invalid 内容验证未通过的元素。

  • :required 有required属性的元素(必填项)。

  • :optional 没有required属性的元素(可选项)。

(codepen链接:https://codepen.io/dgwyer/embed/qYvpMP)

工作电子邮件地址是必填项,并且要求填写正确有效;个人工作电子邮件地址不是必需的,但如若填写,需正确有效。还有要注意一点是伪类选择器是可以组合使用,例如: :required:invalid

接下来的两个伪类选择器匹配拥有取值范围(支持 minmax 属性)的元素。

  • :in-range 当前值处于属性 min 和 max 限定的范围之内。

  • :out-of-range 当前值处于属性 min 和 max 限定的范围之外。

(codepen链接:https://codepen.io/dgwyer/embed/Jvzpgz)

最后我们再介绍三个伪类选择器: :read-only:read-write:placeholder-shown

(codepen链接:https://codepen.io/dgwyer/embed/ZoPREB)

:read-only 匹配不可被用户编辑或拥有 readonly 属性的元素。 :read-write 匹配可以被用户编辑或拥有 contenteditable 属性的元素。

最后, :placeholder-shown 匹配占位文字处于显示状态的元素,当输入内容后,占位文字不再显示时,该元素将不会被匹配;应谨慎使用此选择器,因为它尚未得到广泛支持。

结构选择器

结构选择器非常强大,它是基于元素在DOM中的位置进行匹配。

这类型选择器特殊的地方在于它允许通过传入参数的方式来操作。

例如: :nth-child() 传入一个参数,通过该参数将匹配特定的元素。

因此,如果我们有一组列表,通过下面的选择器将匹配到位置排序是第三的列表:

ul:nth-child(3)

这个参数不只是数字,它还可以是一个表达式,使得匹配能力更强大。

下面是关于使用参数的多个例子:

  • ul:nth-child(2) 位置排序是第二个的元素。

  • ul:nth-child(4n) 位置排序是 (4, 8, 12, …)的元素。

  • ul:nth-child(2n+1) 位置排序是 (1, 3, 5, …)的元素。

  • ul:nth-child(3n — 1) 位置排序是 (2, 5, 8, …)的元素。

  • ul:nth-child(odd) 位置排序是奇数的元素 (1, 3, 5, …)。

  • ul:nth-child(even) 位置排序是偶数的元素 (2, 4, 6, …)。

其中 n 是从零开始,然后 n 为1,再 n 为2,依此类推匹配所有符合表达式的元素。

结构选择器中使用参数来做匹配的选择器如下:

  • :nth-child() 正序匹配某个元素的一个或多个子元素。

  • :nth-last-child() 倒序匹配某个元素的一个或多个子元素。

  • :nth-of-type() 正序匹配某个元素的一个或多个特定类型子元素。

  • :nth-last-of-type() 倒序匹配某个元素的一个或多个特定类型子元素。

(codepen链接:https://codepen.io/dgwyer/embed/MGxzEq)

你可以对选择器做各种不同组合,例如上面的例子里一个代码片段:

ul:last-of-type li:nth-last-of-type(2)::after {
 content: “ (2nd from end)”;
 /* Other styles… */
}

它匹配是一个排序倒数第二个 li 标签的伪元素,从属于最后一项 ul 中。当你面对一个复杂的选择器,可以尝试从右往左阅读它,这样有助与能更好的理解它。

接下来的一组结构选择器,它们仅匹配特定的子元素,您无法通过传递参数给它们以修改其行为。

  • :first-child 匹配某个元素的第一个子元素。

  • :last-child 匹配某个元素的最后一个子元素。

  • :only-child 匹配某个元素的唯一一个子元素。

  • :first-of-type 匹配某个元素的第一个特定类型子元素。

  • :last-of-type 匹配某个元素的最后一个特定类型子元素。

(codepen链接:https://codepen.io/dgwyer/embed/JvzwJE)

咋一看,内容样式是无序纷杂的;你在使用这些类型的选择器时要小心,因为你可能得到你没想到的结果。

例如,你可能想知道为什么 <section> 里只有“And so on…”这段文本是蓝色的,实际上 <section> 里文本都本应该是蓝色的,只是其他元素被不同的选择器覆盖了颜色,才造成只有一段文本是蓝色。

内容选择器

这些是目前可以直接使用的内容选择器:

  • ::first-line 匹配元素的第一行。

  • ::first-letter 匹配元素的第一个字母。

  • ::selection 匹配文档中被用户高亮部分(比如使用鼠标或其他选择设备选中)。

(codepen链接:https://codepen.io/dgwyer/embed/xjBBqN)

::first-line::first-letter 仅在应用于块级元素时才起作用。另外要小心应只在特定元素上使用 ::first-letter,否则每个段落都会有一个首字母下沉,这可能不是你想要的!

还有一些内容选择器还未得到广泛支持,但是当它们得到支持时,它们将开启各种可能性。

以下是需要我们关注的一些内容选择器:

  • ::inactive-selection 匹配当前窗口处于非激活状态下已被选取的文档中被用户高亮部分。

  • ::spelling-error 匹配浏览器标识拼写错误的文本段。

  • ::grammar-error 匹配浏览器标识语法错误的文本段。

  • ::marker 匹配列表项目标记符号(即 <li> 元素由 type 属性生成出的标记符号)。

  • ::placeholder 匹配表单元素中的占位符文本。

杂项选择器

我们再拿出点时间了解一下那些不属于任何类别的选择器,这其中有部分是实验性的,所以你必须等待一段时间才能在生产中使用。

:target 选择器匹配的是一个ID元素,其ID与当前URL片段相对应。例如我们有一个 id="part1" 的元素,当前页面URL是:

https://mysite.com#part1

这时我们就可以匹配到 id="part1" 这个元素并做如下等设置:

:target { border: 1px red solid; }

如果当你遇到一个复杂的选择器组合时,或许 :matches() 选择器可以帮到你。例如你有以下的选择器组合:

nav p.content,
header p.content,
main p.content,
sidebar p.content,
footer p.content {
 margin: 15px;
 padding: 10px;
}

我们可以通过 :matches() 选择器进行简化处理:

:matches(nav, header, main, sidebar, footer) p:content {
 margin: 15px;
 padding: 10px;
}

太好了! 这将有助于使样式表更具可读性。

接下来的 :any-link 选择器,它可以同时匹配 :link:visited 两种链接状态。

下面两段代码,我们会得到相同的效果:

:any-link {
 color: red;
}
:link, :visited {
 color: red;
}

我们最后再介绍一组选择器:

  • :dir() 匹配 dir 属性定义了文本方向的元素。

  • :lang() 匹配 lang 属性定义了语言的元素。

这两个选择器都与站点的语种有关联。

:dir() 接受参数 ltr (从左到右) 或 rtl (从右到左),具体取决于您要匹配的文本方向,目前仅Firefox支持。

:dir(rtl) 匹配是定义了从右到左文本方向的元素。

lang 属性可以给每个元素做单独的语言设置。

<div lang=”en”>The language of this element is set to English.</div>
<div lang=”el”>Η γλώσσα αυτού του στοιχείου έχει οριστεί στα ελληνικά.</div>
<div lang=”is”>Tungumál þessa þáttar er sett á íslensku.</div>

我们将含义相同的三种语言文字分别放到各自的 <div> 中,并用 lang 属性分别单独给其定义对应的语言代码。

  • en — English language(英语)

  • el — Greek language(希腊语)

  • is — Icelandic language(冰岛语)

现在就可以通过 :lang 选择器来匹配定义了不同语言的 <div> 元素:

:lang(en) { color: red; }
:lang(el) { color: green; }
:lang(is) { color: blue; }

下面是演示实例:

(codepen链接:https://codepen.io/dgwyer/embed/xjBoNG)

好消息是所有主流浏览器都支持 :lang() 选择器。

资源

如果你要查询一个选择器,或者需要深入研究CSS规范,那么你可以参看以下的资源:

  • MDN Web Docs (https://developer.mozilla.org/zh-CN/)

  • CSS Specifications (https://www.w3.org/Style/CSS/specs.en.html)

  • Can I Use (https://caniuse.com)

结语

我希望这篇文章对你有用,我也会继续探索CSS选择器技巧的各种可能性。

使用纯CSS可以做很多很酷的事情,这在几年前是不可能实现的。

非常炫目的效果和动画现在都可以纯CSS实现,不用任何的JavaScript,这真的让人感到兴奋。

原创系列推荐



4. 
5. 
6. 
7. 

回复“加群”与大佬们一起交流学习~

点这,与大家一起分享本文吧~

【CSS】381- 提升你的CSS选择器技巧的更多相关文章

  1. 前端极易被误导的css选择器权重计算及css内联样式的妙用技巧

    记得大学时候,专业课的网页设计书籍里面讲过css选择器权重的计算:id是100,class是10,html标签是5等等,然后全部加起来的和进行比较... 我只想说:真是误人子弟,害人不浅! 最近,在前 ...

  2. 20个 CSS 快速提升技巧

    作者:web秀 http://www.javanx.cn/20190321/css-skill/ 本文涵盖了20个css技巧,可以解决许多工作中常见的问题. 1.使用CSS重置(reset) css重 ...

  3. css知多少(6)——选择器的优先级

    1. 引言 上一节<css知多少(5)——选择器>最后提到,选择器类型过多将导致一些问题,是什么问题呢?咱们直接举例子说明. 上图中,css中的两个选择器都是针对<span>的 ...

  4. css引入方式优先级以及不同选择器的优先级区别

    我们都知道css有3种基本设置方式即 1.行内也叫嵌入式 例如: <div style='background:red'></div> 2.内联式,在html文件中用style ...

  5. css中的7中属性选择器

    在CSS的选择符中有七个属性选择符.它们分别是: 1.E[att] 选择具有att属性的E元素. 2.E[att="val"] 选择具有att属性且属性值等于val的E元素. 3. ...

  6. css中最基本几个选择器

    css中有四种不同的选择器 ①类选择器,又叫class选择器.类选择器{属性名:属性值:...}/*类选择器*/.s1{ font-weight:bold;font-size:16px;}②id选择器 ...

  7. CSS(一) 引入方式 选择器 权重

    Css(一) Cascading Style Sheet 层叠样式表 css注释方式/*  */ 一.Css引入方式 1. 行间样式 style=" key:value; " &l ...

  8. css background之设置图片为背景技巧

    css background之设置图片为背景技巧-css 背景 Background是什么意思,翻译过来有背景意思.同样在css里面作为css属性一成员同样是有背景意思,并且是设置背景图片.背景颜色. ...

  9. CSS【03】:CSS 基础选择器与三种引入方式

    基础选择器 选择器:css 选择 html 标签的一个工具,是将 css 与 html 建立起联系,那么 css 就可以控制 html 样式 选择器其实就是给 html 标签起名字 标签选择器 作用: ...

随机推荐

  1. Spark性能优化指南——基础篇(转)

    [转]Spark性能优化指南——基础篇 http://mp.weixin.qq.com/s?__biz=MjM5NDMwNjMzNA==&mid=2651805828&idx=1&am ...

  2. hdu 1754 I Hate It (线段树、单点更新)(PS:ios::sync_with_stdio(false)可以加快cin、cout的读取写出速度)

    I Hate ItTime Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  3. 100天搞定机器学习|Day56 随机森林工作原理及调参实战(信用卡欺诈预测)

    本文是对100天搞定机器学习|Day33-34 随机森林的补充 前文对随机森林的概念.工作原理.使用方法做了简单介绍,并提供了分类和回归的实例. 本期我们重点讲一下: 1.集成学习.Bagging和随 ...

  4. 某些机root也不能访问dma-buf

    从4.3后,回顾<从surfaceflinger历史变更谈截屏>,只能通过生产消费者队列向surfaceflinger服务申请显示缓冲,这个缓冲就是dma-buf映射的共享内存. bind ...

  5. opencv 5 图像转换(1 边缘检测)

    边缘检测 一般步骤 canny算子 步骤 canny函数 彩色canny #include<opencv2/opencv.hpp> #include<opencv2/highgui/ ...

  6. Qt Framework 问题之 framework/Versions/A:bundle format unrecognized, invalid, or unsuitable

    在解决标题提到的问题之后,先来介绍下Qt Framework一些基本知识. 基于QT的Mac端工程,在打包时需要对所有需要嵌入到APP的framework及dylib文件进行手动签名处理. 一.签名处 ...

  7. vue cli3.0 封装组件全局引入js文件并发布到npm

    首先用 vue create创建一个项目 当前的项目目录是这样的: 首先需要创建一个 packages 目录,用来存放组件 然后将 src 目录改为 examples 用作示例 二.修改配置 启动项目 ...

  8. k8s 获取 Pod ip 添加到环境变量

    0x00 事件 有一个需要将 Pod 自身的 ip 地址添加到环境变量的需求,可以在 yaml 文件的 env 中这样设置: env: - name: POD_OWN_IP_ADDRESS value ...

  9. sql server建库建表(数据库和数据表的常用操作)

    数据库和数据表 (开发常用 操作) 一,数据库的创建 一个SQLServer 是由两个文件组成的:数据文件(mdf) 和日志文件(ldf),所以我们创建数据库就是要为其指定数据库名.数据文件和日志文件 ...

  10. 【Android - 进阶】之Animator属性动画

    1.概述 在3.0系统之前,Android给我们提供了逐帧动画Frame Animation和补间动画Tween Animation两种动画: 逐帧动画的原理很简单,就是将一个完整的动画拆分成一张张单 ...