到底什么是伪元素 ?
前言
前几天为了尝试 chatGPT 的打字机效果手写了一个 定时器 + css 的实现
在实现光标的闪烁的过程中,我将伪元素作为光标的主体,这时候伪元素就出现啦。
我想伪元素大家都不陌生吧,在学习 css 或是开发页面的过程中或多或少都会用到过。
但对于平时只知道用的我,从来也没想过在 DOM 中去获取它。
那既然这次实现中遇到了伪元素就来看看它到底为什么东西。
打字机效果实现
先看看我的打字机是怎么实现的 😂
import React, { useEffect } from "react";
import "./index.scss";
export default function Detail() {
useEffect(() => {
const element = document.getElementById("typewriter") as HTMLElement;
// console.log(element.textContent);
const text =
"当你不知道该往哪走的时候,就先跑起来,耳边有风,风就是方向。";
let i = 0;
const typing = setInterval(() => {
if (i > text.length) {
console.log("输入完成");
clearInterval(typing);
// 输入完成取消光标输入样式
element.setAttribute("data-attr", "");
} else {
element.setAttribute("data-attr", "|");
element.textContent = text.slice(0, i);
i++;
}
}, 200);
});
return <div id="typewriter" data-attr="|"></div>;
}
/* scss 光标闪烁样式 */
#typewriter {
display: inline-block;
width: 200px;
height: 200px;
&::after{
display: inline-block;
content: attr(data-attr);
color:black;
animation: 0.5s blink infinite step-end ;
}
}
@keyframes blink{
from{
opacity: 0;
}
50% {
opacity: 1;
}
to {
opacity: 0;
}
}
这里用到了一个 attr() 函数它是 CSS 的一个内置函数,用于获取元素的属性值。
content 属性通过 attr(data-attr) 获取元素的 data-attr 属性值,并将其作为伪元素的内容。
通过 data-attr 属性可以控制伪元素得展示和隐藏 。
当然在写这个效果得时候并没有那么顺利,想要控制光标的消失我也想过用 js 去获取伪元素的 DOM 结构,但是奈何假的就是假的,及时它再怎么像真的终究还是假的,DOM 中根本不存在这个节点,所以只能换个角度,通过样式的属性去控制伪元素的消失。
那么究竟什么是伪元素呢,我们该怎么去获取伪元素并修改他呢?
带着这个大大疑问开始今天的 6 月更文吧!!!
什么是伪元素?
在CSS中,伪元素(pseudo-elements)是用于选择元素的特定部分或生成额外内容的一种方式。
之所以称之为 '伪元素' 是因为它们是虚拟的,他可以被浏览器渲染但并不实际存在于 HTML 文档结构中的,而是通过CSS样式来创建和控制。
伪元素通过 content 属性向页面加入额外的内容,例如插入图标、添加装饰性的元素等。它们也可以用于选择元素的特定部分,例如选择元素的第一个字母或第一行文本等。
button::before {
content: "+";
font-size: 20px;
margin-right: 5px;
}
这里向 button 元素前插入一个“+”图标,并设置了图标的大小和右侧间距。
这样可以让按钮看起来更加美观和易于理解。
伪元素的使用
CSS3 规范中的要求使用双冒号 (::) 表示伪元素,以此来区分伪元素和伪类。除了IE8及以下版本,所有浏览器都支持两个冒号的伪元素表示法。
常见的伪元素:
在这其中最常用的就是 ::after 和 ::before。
伪元素 | 选中或创建出来的元素 | 兼容性 |
---|---|---|
::first-letter | 选中(仅适用于块级)元素中的第一个元素 | ✅ |
::first-line | 选中首行 | ✅ |
::before | 在元素前创建一个虚拟元素 | ✅ |
::after | 在元素后创建一个虚拟元素 | ✅ |
::placeholder | 选中表单元素的占位文本 | ✅ |
::file-selector-button | 选中类型为 file 的 input 里面的 button | ✅ |
::selection | 选择被用户选中的文本部分 | ⚠️ |
::backdrop | 选中视觉聚焦元素后面的背景元素 | ⚠️ |
::marker | 选中 list 的 marker | ⚠️ |
- ✅ 代表主流浏览器都支持(至少 95% 以上)
- ❌ 代表大部分主浏览器都不支持(仅 20% 以下浏览器实现该特性)
- ⚠️ 代表部分浏览器支持(可能需要加前缀,例如 :webkit-或 :-moz-等)
(参考自 juejin.cn/post/713608…)
使用伪元素可以增强页面的样式和布局,并提供更多的设计自由度,是CSS中非常有用的特性,用于创建各种效果和装饰。
什么是伪类?
伪类(pseudo-class)是 CSS 中选择器的一种,用于选择元素在特定状态或具有特定属性时的样式规则。它们可以根据元素的状态、位置、用户行为等进行选择,从而实现对元素的精细控制和样式化。
伪类使用单冒号(:)表示,例如 :hover、:active 和 :first-child 等。它们可以与选择器结合使用,用于选择特定的元素或元素的特定状态。
常见的伪类可以分为以下几类:
-
动态伪类:
- :hover:鼠标悬停时应用样式
- :active:元素被激活(鼠标按下)时应用样式
- :focus:元素获取焦点时应用样式
- :visited:已访问链接的样式
-
结构性伪类:
- :first-child:选择父元素下的第一个子元素
- :last-child:选择父元素下的最后一个子元素
- :nth-child(n):选择父元素下的第n个子元素
- :nth-last-child(n):选择父元素下的倒数第n个子元素
- :nth-of-type(n):选择父元素下的第n个指定类型的子元素
- :nth-last-of-type(n):选择父元素下的倒数第n个指定类型的子元素
- :only-child:选择父元素下唯一的子元素
- :only-of-type:选择父元素下唯一的指定类型的子元素
- :empty:选择没有子元素或文本内容的空元素
-
状态伪类:
- :enabled:选择可用的表单元素
- :disabled:选择被禁用的表单元素
- :checked:选择已选中的表单元素
-
其他伪类:
-
:not(selector):选择不匹配指定选择器的元素
-
:target:选择URL片段标识符(Hash)与当前URL匹配的元素
-
伪类可以根据元素的状态、结构或其他条件选择目标元素,并为其应用相应的样式,
通过使用不同的伪类组合和结合 CSS 选择器,可以实现对元素的精细控制和样式化。
如何获取伪元素
由于伪元素只存在于 CSS 渲染树中,仅用于样式化和装饰元素的特定部分,在渲染阶段被添加到渲染树中,并在最终的绘制阶段进行绘制。
所以 伪元素并不会在 DOM 树中增加额外的节点,也无法通过 js 去访问或操作伪元素。
那么我们是否可以通过 CSS 样式表去获取伪元素呢?
想要获取伪元素,可以通过 window.getComputedStyle() 获取到指定元素的计算样式对象,
当使用 getComputedStyle 方法时,它返回的是一个 CSSStyleDeclaration 对象,其中包含了指定元素的所有计算样式,包括伪元素的样式。
const element = document.getElementById("typewriter") as HTMLElement;
// 获取伪元素
const after = window.getComputedStyle(element, ":after");
after.display = "none";
console.log(after.display);
// style 强制覆盖伪元素样式
element.innerHTML = "#typewriter::after{display:none}";
通过访问计算样式对象的属性来获取伪元素的具体样式值,
注意:伪元素的样式是只读的,只能用于获取伪元素的样式值,而不能用于修改它们。
获取元素属性值
在获取 CSS 样式声明对象后利用 getPropertyValue() 或 直接使用键值访问 来获取对应属性的值。
const element = document.getElementById("typewriter") as HTMLElement;
const after = window.getComputedStyle(element, ":after");
console.log(after.getPropertyValue("color")); // rgb(0,0,0)
console.log(after.display); // inline-block
使用 getPropertyValue() 获取属性值会更加灵活,它可以获取任意 CSS 属性的值。
而直接使用键值访问则更适用于访问元素的 style 属性中的属性值,通常用于直接操作内联样式。
注意:伪元素默认的 display属性为 inline,但在设置 CSS 样式时可以手动修改其 display 属性为 block、inline-block 或 其他。
更改伪元素的样式
- 类名替换
在 CSS 中定义不同的 CSS 类名,并在 js 中通过添加或删除类名来改变伪元素的样式。
首先,在 CSS 样式表中定义类名对应的样式规则,
.element::before {
/* 默认样式规则 */
}
.element.new-class::before {
/* 新样式规则 */
}
.element.old-class::before {
/* 旧样式规则 */
}
通过 JavaScript 来添加或移除这些类名,使得在不同类名下的伪元素样式发生变化
const element = document.querySelector('.element');
element.classList.add('new-class');
element.classList.remove('old-class');
- 使用 CSSStyleSheet 对象插入样式规则
通过对 CSSStyleSheet 对象插入 insertRule 方法来为伪元素插入新的样式规则。这个方法允许你动态地添加新的 CSS 规则到样式表中,包括针对伪元素的样式。
使用 insertRule 修改伪元素的样式:
const styleSheet = document.styleSheets[0]; // 获取文档的第一个样式表
// 定义插入的样式规则
const newRule = '.element::before { color: red; }';
// 使用 insertRule 方法将规则插入到样式表的末尾 并返回该规则在样式表中的索引位置
styleSheet.insertRule(newRule, styleSheet.cssRules.length);
// 注意:如果要修改伪元素的样式,确保已经定义了对应的伪元素样式规则
使用 insertRule 方法可以在运行时动态地修改伪元素的样式,提供了更大的灵活性。
然而,需要注意样式表的索引和规则的位置,以确保插入的样式规则被正确应用。
- 使用样式属性对象
通过修改元素的 style 属性来更改伪元素的样式。获取元素对象后,直接修改其 style 属性即可。
const element = document.querySelector('.element');
element.style.setProperty('--pseudo-element-color', 'red');
利用元素的行内属性来设置 CSS 变量定义伪元素的样式
.element::before {
color: var(--pseudo-element-color);
}
同样的利用这种方式可以实现伪元素中 content 的修改,就像开篇打字机效果设置的 data-attr 变量
通过行内属性改变伪元素的样式。
修改伪元素的样式,建议使用更换类名或利用 DOM 的动态属。
总结
伪元素的 content 属性很强大,除了插入文本和图像之外,还可以插入一些特殊的字符和符号。但是伪元素的内容只存在于 CSS 渲染树中,所以为了 SEO 优化,不要将重要的文本和信息放在伪元素中,可能会影响网站的可访问性和可读性,从而降低 SEO 的效果。在修改伪元素时,也建议使用更换类名或利用 DOM 的动态属性进行修改。
好啦,以上是目前我所了解的伪元素的内容啦,如果有新的发现我也会继续补充的,希望这些对你们也有所帮助,拜拜啦 !!!
参考
转载自:https://juejin.cn/post/7242676549735465018