无论你是 CSS 新手还是有多年经验,你都可能遇到过伪类。最广为人知的伪类可能是 ,它允许我们在元素处于悬停状态时(例如当鼠标指针悬停在元素上时)设置元素的样式。
:hover
这篇文章详细介绍了伪类。我们将探讨什么是伪类,它们如何运作,如何对它们进行分类,以及它们与伪元素有何不同。
理解伪类
伪类是添加到 CSS 选择器中的关键字,用于定义 HTML 元素的特定状态。您可以使用 colon syntax 将伪类添加到 CSS 选择器中,如下所示:
a:hover { ... }
CSS 类是应用于 HTML 元素的属性,用于强制执行相同的样式规则,例如顶部菜单项或侧边栏小部件标题。从本质上讲,CSS 类对具有共同特征的 HTML 元素进行分组或分类。
伪类类似于 CSS 类,因为它们还将样式规则应用于具有共同特征的元素。但是,虽然标准类是用户定义的,并且在源代码中可见,但伪类是由用户代理(Web 浏览器)根据 HTML 元素的当前状态应用的。
伪类的作用
常规 CSS 类的目的是对元素进行分类或分组。开发人员根据预期的样式对元素进行分组,创建“menu-items”、“buttons”或“thumbnail”等类,以确保相似元素的设计一致。这些分组基于开发人员定义的特征。
例如,开发人员可能会使用 a 作为缩略图,并使用 “thumbnail” 类对其进行分类。
<div class="thumbnail">[...]</div>
但是,HTML 元素具有基于其状态、位置、性质以及与页面和用户的交互的固有特征。这些特征通常不会在 HTML 代码中标记,但可以通过 CSS 中的伪类来定位。示例包括:
- 作为其父元素中的最后一个子元素的元素
- 已访问的链接
- 已全屏显示的元素
这些是伪类通常解决的特征类型。为了更好地理解 class 和 pseudo-classes 之间的区别,让我们考虑使用 class 来识别各种父容器中的最后一个元素。
.last
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li class="last">item 4</li>
</ul>
<select>
<option>option 1</option>
<option>option 2</option>
<option>option 3</option>
<option class="last">option 4</option>
</select>
您可以使用以下 CSS 设置这些最后一个子元素的样式:
li.last {<br> text-transform: uppercase;<br> }<br> <br> option.last {<br> font-style: italic;<br> }
但是,当最后一个元素发生变化时会发生什么呢?您需要手动将类从上一个最后一个元素更新为新元素。
.last
对于某些常见特征,可以避免这种更新类的麻烦。例如,使用预定义的伪类非常有益。这样,就不需要标记 HTML 代码中的最后一个元素,你仍然可以使用以下 CSS 设置它的样式::last-child
li:last-child {
text-transform: uppercase;
}
option:last-child {
font-style: italic;
}
伪类的主要类型
CSS 提供了各种伪类,这些伪类允许开发人员根据可能难以访问的特定特征来定位元素。
1. 动态伪类
动态伪类根据 HTML 元素由于用户交互而转换到的状态,动态地应用于 HTML 元素。一些示例包括:hover
、:focus
、:link:
和 visited
,所有这些 通常与 anchor 标记一起使用。
a:visited {
color: #8D20AE;
}
.button:hover,
.button:focus {
font-weight: bold;
}
2. 基于状态的伪类
当元素处于特定的静态状态时,基于状态的伪类将应用于元素。常见示例包括:
:checked
对于复选框 (<input type="checkbox">
):fullscreen
以当前以全屏模式显示的任何元素为目标:disabled
对于可以禁用的元素,例如 、 和 。<input> <select> <button>
伪类特别受欢迎,因为它指示是否选中了复选框。:checked
.checkbox:checked + label {
font-style: italic;
}
input:disabled {
background-color: #EEEEEE;
}
3. 结构伪类
结构伪类根据元素在文档结构中的位置来定位元素。一些最常用的示例包括 、 和 。这些可用于根据特定子元素在容器中的位置设置其样式。另一个示例是 ,它以 DOM 中最高级别的父元素为目标。:first-child :last-child :nth-child(n)、:root
4. 杂项伪类
还有一些伪类不能完全归入其他类别,例如:
:not(x)
,用于选择与指定选择器 x 不匹配的元素:lang(language-code)
用于根据内容语言定位元素:dir(directionality)
,它选择内容具有特定方向性(例如,从左到右或从右到左)的元素。
p:lang(ko) {
background-color: #FFFF00;
}
:root {
background-color: #FAEBD7;
}
nth-child 与 nth-of-type 伪类
伪类最具挑战性的方面之一是理解 和 伪类 之间的区别。
:nth-child :nth-of-type
这两个都是以父元素(容器)中的特定元素为目标的结构伪类,但它们以不同的方式实现。
假设 n 为 2。选择器以作为其父元素的第二个子元素的元素为目标,而不管元素的类型如何。另一方面,以父元素中特定类型元素(例如段落)的第二次出现为目标。
:nth-child(n) :nth-of-type(n)
让我们看一个示例来说明这种差异:
/* Styles the second child element inside its parent, which can be of any type */
p:nth-child(2) {
color: #1E90FF; /* Light blue */
}
/* Styles the second paragraph inside its parent element */
p:nth-of-type(2) {
font-weight: bold;
}
现在,让我们看看这个 CSS 在两种不同的场景中是如何影响 HTML 的。
案例 1
在情况 1 中,a 中的第二个元素是无序列表,因此该规则不适用于段落。尽管无序列表是第二个子项,但它不是一个段落。
<div>:nth-child(2)
但是,如果父元素包含第二个段落,则规则将适用,因为此规则专门针对元素并忽略父元素中的其他类型的元素(如无序列表)。:nth-of-type(2)
<p>
在我们的示例中,该规则将设置第二个段落的样式,在本例中为 Child 3。
:nth-of-type(2)
<!-- Case 1 -->
<div>
<p>Paragraph 1, Child 1</p>
<ul>Unordered List 1, Child 2</ul>
<p>Paragraph 2, Child 3</p>
</div>
案例 2
在情况 2 中,我们将无序列表移动到第三个位置,将第二个段落放在它之前。现在,和 rules 都将适用,因为第二个段落既是其父元素的第二个子元素,也是第二个元素。
:nth-child(2) :nth-of-type(2) <div> <p>
<!-- Case 2 -->
<div>
<p>Paragraph 1, Child 1</p>
<p>Paragraph 2, Child 2</p>
<ul>Unordered List 1, Child 3</ul>
</div>
为了进一步探索两者之间的区别,如果您使用 SASS,Family.scss 可以帮助您创建复杂的基于 n 个子元素的元素。:nth-child :nth-of-type
伪类 vs 伪元素
伪类和伪元素的区别
(1)类,用户定义的类名,这个类是具体的,看得见的,如div.div0,选择具有类div0的div元素。
(2)伪类,用于向某些选择器添加特殊的效果。用伪类定义的样式并不是作用在标记上,而是作用在标记的状态上,如a标签的:hover,表单元素的:disabled。
(3)元素,如div、p、h1等,是实实在在存在的元素。
(4)伪元素,是html中不存在的元素,仅在css中用来渲染的,伪元素创建了一个虚拟容器,这个容器不包含任何DOM元素,但是可以包含内容。如::before、::after。
此外,我们在如何使用 CSS 定位伪类和伪元素方面存在差异。
1. 它们在 CSS 选择器序列中的位置
伪元素必须出现在选择器序列之后,而伪类可以放置在 CSS 选择器序列中的任何位置。
例如,您可以通过两种不同的方式将元素中的最后一个列表项作为目标:<ul>
<ul>
<li class="red"></li>
<li></li>
<li class="red"></li>
<li class="red"></li>
</ul>
ul > :last-child.red {
color: #B0171F;
}
或
ul > .red:last-child {
color: #B0171F;
}
第一个选择器以具有类 的元素中的最后一个子元素为目标,而第二个选择器以具有类的元素中的最后一个子元素为目标。如您所见,伪类的位置可能会有所不同。
让我们尝试对伪元素进行类似的事情。
ul > .red::after {
display: block;
content: 'red';
color: #B0171F;
}
上面的 CSS 是有效的,但是,以下代码将不起作用,因为我们无法更改 selector 序列中伪元素的位置。
ul > ::after.red {
display: block;
content: 'red';
color: #B0171F;
}
2. 选择器序列中的出现次数
每个选择器只能使用一个伪元素,而只要组合有意义,就可以组合伪类。例如,要以同样为只读的第一子元素为目标,您可以组合伪类,如下所示::first-child :read-only
:first-child:read-only {
color: #EEEEEE;
}
jQuery 选择器扩展
并非所有包含 a 的选择器语法都是合适的 CSS 伪类。如果您使用过 jQuery,则可能熟悉 、 和 .:
$(':checkbox')
$(':input')
$(':selected')
请务必注意,这些不是 jQuery 的目标 CSS 伪类。相反,它们被称为 jQuery 选择器扩展。
jQuery 选择器扩展允许您使用更简单的关键字来定位 HTML 元素。其中许多扩展是标准 CSS 选择器组合的简写,由单个关键字表示。
/* Change the font of all input-related HTML elements,
like button, select, and input */
$( ":input" ).css("font-family","courier new");