CSS 的伪类 ( Pseudo-Class ) 和伪元素 ( Pseudo-Elements )
参考文档 & 参考博客
明显的区别
伪类以一个冒号 ( : )作为前缀,而伪元素以两个冒号 ( :: )作为前缀。
注意:CSS2中已存的伪元素仍然可以使用一个冒号 ( : ),但是CSS3中新增的伪元素必须使用两个冒号 ( :: )
举个例子:
1 | /* ↓ 伪类 ::hover*/ |
定义
伪类是添加到选择器的关键字,指定要选择的元素的特殊状态。
伪元素是一个附加至选择器末的关键词,允许你对被选择元素的特定部分修改样式。
↑ 从 MDN 给的定义可以看出来 ,伪类是对选中的元素的特殊状态的样式进行样式定义,而伪类则是对选中的元素的特定部分进行样式定义。
W3C 的定义:
The pseudo-class concept is introduced to permit selection based on information that lies outside of the document tree or that cannot be expressed using the other simple selectors.
Pseudo-elements create abstractions about the document tree beyond those specified by the document language. For instance, document languages do not offer mechanisms to access the first letter or first line of an element’s content. Pseudo-elements allow authors to refer to this otherwise inaccessible information. Pseudo-elements may also provide authors a way to refer to content that does not exist in the source document (e.g., the ::before and ::after pseudo-elements give access to generated content).
↑ 从加粗的动词可以看到伪类和伪元素进行的功能其实有挺大差异的。
简单来说就是
伪类可以给选中的元素的位于文档树之外的内容或者不能用简单选择器表达的内容进行添加样式。
比如说 :hover 获取被鼠标覆盖的元素 :nth-child(1) 获取父元素的第一个子元素,是不处于文档树/不能用简单选择器获取的。
伪元素就是创建了一些抽象元素 (是不存在于文档中的),对这个抽象的元素进行给定样式。
比如说 ::after ,用过都知道要有 content 这一条属性。
伪类
看了 MDN 文档才发现伪类的种类有特别多。 → 传送门
来说几个常用的。
:active / :link / :hover / :visited
这四个经常和 <a> 标签一起用
选择器 | 选择的目标 |
---|---|
:link | 选中所有未访问的链接 |
:visited | 选中用户已访问过的链接 |
:hover | 选中被鼠标覆盖(虚指)的元素,虚指就是指并没有激活,这个伪类可以在任何元素上使用 |
:active | 选中被用户激活的元素,当用鼠标交互时,代表的就是按下鼠标开始到松开鼠标的那段时间 |
注:为了确保生效,四个伪类的定义顺序应该是 :link -> :visited -> :hover -> :active 。另外并不建议在触摸屏使用 :hover 。
:checked
这个伪类会选中处于 selected 状态的 radio、checkbox 以及 select 元素中的 option。
举个例子:
1 | input[type='checkbox']:checked { |
被选中的单/多选框元素在选中后字体会变成红色。
:disabled
这个伪类会选中处于 disabled 状态元素。
举个例子:
1 | input:disabled { |
被设置了 disabled 的 input 框里的背景颜色会是红色的。
突然想到如果设置 color:red; 会不会有反应呢?
- 如果设置有 placeholder ,placeholder 的内容不会成为红色。
- 如果设置有 value , value的内容会成为红色。
那么要怎么修改 placeholder 的样式呢!这就要涉及到伪元素了…
:first-child / :last-child
这两个伪类非常相似,区别就在一个元素以及最后元素。
我遇到过两中对定义的描述:
- 表示一组兄弟元素中的第/最后一个元素。
- 表示父元素的第/最后一个元素。
个人更倾向第一种说法,更方便理解,因为在实际应用的时候,不会管父元素是什么的(下面的例子可以很清楚看出来
1 | <div> |
1 | p:first-child { |
CSS代码中可以看到,在 :first-child 前面的是 p 而不是 div,而 "demo 1" 的字体颜色才是红色," demo 2"的字体颜色是默认的黑色。
所以我更倾向于"表示一组兄弟元素中的第/最后一个元素"这个说法,在这个两个伪类的使用过程中,是不需要考虑父元素的。
注意:是一组兄弟元素中的第/最后一个元素,如果只有一个元素,该伪类是不生效的。
:focus
获得焦点的元素。当用户点击或触摸元素或通过键盘的 "tab" 键选择它时会被触发。
大多数情况下都用在 input 上。(完全没有遇到过/见过用在别的元素上的情况。
:nth-child() / :nth-last-child()
这两个伪类是带参数的
nth-child( ) 会从兄弟元素组中选择第 an+b 个元素。(同样的,如果只有一个元素,是不会生效的。
但是这个伪类的优势在于由于 n 的存在,可以选择单一或多个的元素。
举一些例子:
- 0n+3。选择第三个元素。
- 1n+0。选择每一个元素。
- 2n+0。选择第 2、4、6、8… 个元素(即偶数位元素,不存在第 0 个元素,因此从第 2 个元素开始匹配)。可以用 even 关键字替换。
- 2n+1。选择第 1、3、5、7、9… 个元素(即奇数位元素,从第 1 个元素开始匹配)。可以用 odd 关键词替换。
- 上面三种都是特殊情况,匹配每位/奇数位/偶数位。但是 an+b 没有限制 a/b 只能是 0、1、2,所以当参数是 3n+4 时,匹配位置为 4、7、10、13…的元素。
注意:
- a、b 都必须是整数。
- 元素组里第一个元素下标为 1 而不是 0。
- an 要写在 b 的前面,就是说 b+an 这种写法是错误的。
:nth-last-child( ) 基本与 :nth-child( ) 一致,只是它从结尾处反序计数,而不是从开头处。
伪元素
需要注意的是,CSS2 中就存在的伪元素的前缀可以是 : ,而 CSS3 中定义的伪元素的前缀必须是 ::
::after / ::before
最最最常用的伪元素。
另外可以前缀可以是 : 。当然啦不推荐,CSS3 中使用两个冒号的原因就是为了区分伪类和伪元素,建议按 CSS3 的标准使用 :: 作为前缀,仅当为了支持 IE8 时,使用单冒号 : 作为前缀。
这两个伪元素会为匹配的元素创建一个伪元素作为该元素的第一个/最后一个子元素。
使用 content 属性添加修饰性内容。
创建的伪元素默认为行内元素。
举一个 MDN 的例子:
1 | <span class="ribbon">Notice where the orange box is.</span> |
1 | .ribbon { |
::first-letter / ::first-line
作用很相似的两个伪元素。
::first-letter 会选中某块级元素第一行的第一个字母,并且文字所处的行之前没有其他内容(如图片和内联的表格) 。
::first-line 会选中某块级元素的第一行。
但是对于第一个字母并不总是容易识别。
同时第一行也要考虑到行宽、字体大小等因素。
另外对于这两个伪元素能够使用的 CSS 样式也有一定的限制。
最后这两个伪元素也是于 CSS2 中出现的伪元素,建议仅当考虑兼容性时使用单个冒号作为前缀。
::selection
这个伪元素通常会配合整体网页的配色来使用。
默认情况下,鼠标选中浏览器的文字,文字会变成蓝底白字。
但是配置了该伪元素之后,选中的文字会进行相应的变动,下面举一个谷歌翻译网站的例子。
可以看到依据谷歌对于 ::selection 的配置,选中的文字字体颜色保持黑色,而背景颜色变成了淡蓝色。
对比一下本站,可以看到本站中,选中的文字会变成黑底白字。
另外需要注意的是 ::selection 中只允许使用一小部分 CSS 样式:
- color
- background-color
- cursor
- caret-color
- outline
- text-decoration
- text-emphasis-color
- text-shadow
::placeholder
placeholder 是在 input 中常用的属性。
但是这个伪元素存在兼容性的问题相较之前提到的其他的伪元素伪类来说较大,参考 Can I Use 就可以看出来来
同时为了考虑其他支持的浏览器,该伪元素的使用也需要进行一些变动,如下:
- ::-webkit-input-placeholder
- :-moz-placeholder ( 匹配 Firefox 18-
- ::-moz-placeholder ( 匹配 Firefox 19+
- :-ms-input-placeholder
总结
伪元素和伪类的存在,一定程度上弥补了 CSS 的一些缺陷。
但是需要注意的是伪类和伪元素的语法是存在一些差异的,同时部分的伪元素和伪类对能够使用的 CSS 样式存在限制。
虽然说上面提到的这些功能都可以使用 JavaScript 实现。但是耐不住伪类和伪元素使用起来方便(指代码量少)。
上面之总结了小部分常用的,稳定的 ( 除了 placeholder ) 的伪类和伪元素。
那么就这样啦。
在之前的时候就知道伪类和伪元素有一项差异。
伪类可以同时定义多个,而伪元素只能定义一个。
当时的想法是:同一个元素可以同时拥有 ::before 和 ::after 啊?
今天才意识到可以定义多个的意思可以理解为可以嵌套,举个例子:
1 | /* 多个伪类 */ |
而伪元素是不存在这个情况的。