【CSS】伪元素与伪类

CSS 伪元素和伪类

1.为什么要引入伪元素和伪类?

在 CSS 的官方文档中,是这样描述的:

CSS introduces the concepts of pseudo-elements and pseudo-classes to permit formatting based on

information that lies outside the document tree.

意思是:CSS 引入伪类和伪元素概念是为了格式化文档树以外的信息。即,伪类和伪元素是用来修饰不在文档树种的部分。CSS 中没有比如:"段落的第一行"、"文章首字母"之类的选择器,而这些部分在一些业务场景中又是需要控制的,这时候就需要用到伪元素和伪类了。

2.伪类和伪元素的概念以及作用

2.1 伪类

伪类是为处于某一状态的已有元素添加相应的样式,而这个状态是根据用户的行为而动态改变的。

伪类一般用于以下场景:

  1. 设置鼠标悬停在元素上的样式
  2. 为已访问和未访问链接设置不同的样式
  3. 设置元素获得焦点时的样式
  4. 为一串元素中的某些特定元素设置样式
  5. ...
2.2 伪元素

伪元素是用于创建一些不存在于文档树中的元素,并为其添加指定的样式。即,虽然用户可以看到这些元素,但是这些元素实际上并不存在于文档树中!这一点也是伪元素与伪类之间的本质区别!

伪元素一般用于以下场景:

  1. 设置文本元素首字母、首行的样式
  2. 在元素内容之前或之后插入内容
  3. 设置滚动元素的滚动条样式
  4. ...

3.伪类

CSS 中的常用伪类可以分为以下几类:

  • 状态伪类
  • 结构性伪类
  • 表单相关
  • 语言相关
  • 其他

如下图:

3.1 状态伪类

状态伪类,即元素的样式会根据其状态的不同而呈现不同的样式,当元素处于某一状态时,应用该状态对应的样式,而进入另一状态后,该样式也不再生效。

常见的状态伪类有:

  • :link 应用于未被访问过的链接
  • :hover 应用于鼠标悬停到的元素
  • :active 应用于被激活的元素
  • :visited 应用于被访问过的链接 ,是一种与:link状态互斥的状态!
  • :focus 应用于拥有键盘输入焦点的元素

需要注意的是,**这几个伪类同时出现在一个元素的操作上,顺序是固定的,否则很大程度上会产生紊乱,造成效果失效!**具体来说,:hover 必须在 CSS 定义中的 :link:visited 之后,才能生效。:active 必须在 CSS 定义中的 :hover 之后才能生效。

3.2 结构性伪类

结构性伪类是 CSS3 中新加入的元素选择器,它通过对 DOM 树进行元素过滤,用文档结构的相互关系来匹配元素,能够减少 classid 属性的定义,使得文档结构更加简洁!

常见的结构性伪类:

  1. :first-child 选择某个元素的第一个子元素
  2. :last-child 选择某个元素的最后一个子元素
  3. :nth-child(n) 匹配属于其父元素的第 n 个子元素,不论元素的类型;
  4. :nth-last-child() 从这个元素的最后一个子元素开始算,选匹配属于其父元素的第 n 个子元素,不论元素的类型;
  5. :nth-of-type() 规定属于其父元素的第 n 个指定类型元素
  6. :nth-last-of-type() 从元素的最后一个开始计算,规定属于其父元素的指定类型元素
  7. :first-of-type 选择一个上级元素下的第一个同类子元素
  8. :last-of-type 选择一个上级元素的最后一个同类子元素
  9. :only-child 选择它的父元素的唯一一个子元素
  10. :only-of-type 选择一个元素是它的上级元素的唯一一个相同类型的子元素
  11. :checked 匹配被选中的input元素 ,这个input元素包括radiocheckbox
  12. :empty 选择的元素里面没有任何内容
  13. :disabled 匹配禁用的表单元素。
  14. :enabled 匹配没有设置disabled属性的表单元素。
  15. :valid 匹配条件验证正确的表单元素。
  16. :in-range 选择具有指定范围内的值<input> 元素。
  17. :optional 选择不带 required 属性<input> 元素。
  18. :focus 选择获得焦点<input> 元素。
3.3 表单相关

有些伪类的使用常常与表单向关联:

3.3.1 :checked

:checked --- 匹配被选中的 input 元素,这个 input 元素包括 radio 和 checkbox。

例:当复选框被选中时,与其相邻的<label> 元素的背景会变化

HTML

html 复制代码
<input type="checkbox"/>
<label>agree</label>

CSS

css 复制代码
/* 匹配选中状态input元素的相邻label元素 */
input:checked + label {
    background: yellow;
}
3.3.2 :default

:default --- 匹配默认选中的元素

3.3.3 :disabled

:disabled --- 匹配禁用的表单元素

例如这里,我们将禁用的 input 元素置为红色

HTML

html 复制代码
<input type="text" disabled/>

CSS

css 复制代码
input:disabled {
    background-color: red;
}
3.3.4 :empty

:empty --- 匹配没有子元素 的元素。但凡元素中含有文本节点、HTML 元素或者一个空格,:empty都不能匹配这个元素。

例:

HTML

html 复制代码
<div>这个容器里的背景是橙色的</div>
<div>  </div>
<div></div>
<div><!-- 注释不会被视作内容 --></div>

CSS

css 复制代码
div {
    background: red;
    height: 30px;
    width: 200px;
}
 
div:empty {
    background: blue;
}

效果如下:

可以看到,第一个元素中有文本节点,所以其背景不会变成蓝色;第二个元素中有一个空格,有空格则该元素不为空,所以其背景不会变成蓝色;第三个元素中没有任何内容,所以其背景会变成蓝色;第四个元素中只有一个注释,此时该元素是空的,所以其背景会变成蓝色;

3.3.5 :enabled

:disabled相反,:enabled 匹配没有设置 disabled 属性的表单元素。

3.3.6 :in-range

:in-range 匹配在指定区域内元素。

例如:

HTML

html 复制代码
<input type="number" min="5" max="10">

CSS

css 复制代码
input[type=number] {
    border: 5px solid orange;
}
 
input[type=number]:in-range {
    border: 5px solid green;
}

效果如下:

可以看到,当输入的数字在我们设定的范围 5 ~ 10 之间时,边框变为绿色。

3.3.7 :out-of-range

:out-of-rangein-range 相反,其用于匹配不在指定区域内的元素。

3.3.8 :indeterminate

indeterminate 的英文意思是" 不确定的"。当某组中的单选框或复选框还没有选取状态时,:indeterminate 可以匹配到该组中所有的单选框或复选框。

例:

HTML

html 复制代码
<ul>
    <li>
        <input type="radio" name="list" id="option1">
        <label for="option1">Option 1</label>
    </li>
    <li>
        <input type="radio" name="list" id="option2">
        <label for="option2">Option 2</label>
    </li>
    <li>
        <input type="radio" name="list" id="option3">
        <label for="option3">Option 3</label>
    </li>
</ul>

CSS

css 复制代码
:indeterminate + label {
    background: red;
}

效果如下:

可以看到,当组中没有一个单选被选中时,所有的单选都处于不确定的状态,因此它们的label背景都为红色;而当有一项被选中后,所有单选的状态都确定了!所以它们的背景都不会被设置为红色。

3.3.9 :valid

:valid 匹配条件验证正确的表单元素。

3.3.10 :invalid

:invalid:valid 相反,匹配条件验证错误的表单元素。

3.3.11 :optional

:optional 匹配是具有 optional 属性的表单元素。当表单元素没有设置为 required 时,即为 optional 属性。

3.3.12 :required

:required:optional 相反,匹配设置了 required 属性的表单元素。

3.3.13 :read-only

:read-only 匹配设置了只读属性 的元素,表单元素可以通过设置 readonly 属性来定义元素只读。

3.3.14 :read-write

:read-write 可以匹配处于编辑状态 的元素。input,textarea 和设置了 contenteditable 的HTML元素获取焦点时即处于编辑状态。

例:

HTML

html 复制代码
<input type="text" value="获取焦点时背景变黄"/>
 
<div class="editable" contenteditable>
    <h1>点击这里可以编辑</h1>
    <p>获取焦点时背景变黄</p>
</div>

CSS

css 复制代码
:read-write:focus {
    background: yellow;
}

效果如下:

可以看到,在 input 框获取焦点时,样式作用到了其身上。同时,我们为div设置 contenteditable 属性后,使其获取焦点时,同样可以将样式作用到其身上。

3.3.15 :scope(处于试验阶段)

:scope 匹配处于 style 作用域下的元素。当 style 没有设置 scope 属性时,style 内的样式会对整个 html 起作用。


以上就是常用的三类伪类,至于其他两类,在实际开发中的使用并不多,这里就不作介绍了,需要使用时,可以查阅官方文档。

4.伪元素

常用的伪元素如下:

  1. ::after --- 在元素之后插入内容。
  2. ::before --- 在元素之前插入内容。
  3. ::first-letter --- 选择元素的首字母,只能作用于块级元素!
  4. ::first-line --- 选择元素的首行,只能作用于块级元素!
  5. ::selection --- 选择用户选择的元素部分。
  6. ::placeholder --- 匹配占位符的文本,只有元素设置了 placeholder 属性时,该伪元素才能生效。但需要注意的是,该伪元素不是 CSS 的标准,它的实现可能在将来会有所改变,所以要决定使用时必须谨慎。

下面就拿最为常用的两个伪元素 ::after::before 来举个例子:

vue 复制代码
<style lang="less" scoped>
.btn_block {
  position: relative;
  .block {
    position: absolute;
    bottom: 55px;
    left: -40px;
    width: 200px;
    height: 200px;
    background: skyblue;
  }
  .block::after {
    content: '这里是after伪元素';
    position: absolute;
    top: 100%;
    left: 18%;
    // background: orange;
    border-width: 10px;
    border-style: solid;
    border-color: orange transparent transparent transparent;
  }
}
/* 这里用了iview组件库的Modal组件,其类名为 ivu-modal */
:deep(.ivu-modal::before) {
  content: '1111111111111';
  background: skyblue;
}
:deep(.ivu-modal::after) {
  content: url(../../assets/icons/uploadBtn.png);
}
</style>
<template>
<div class="btn_block">
    <button @mouseenter="isShowBlock = true" @mouseleave="isShowBlock = false">
        hover to show block
    </button>
    <div class="block" v-show="true">this is a block!</div>
</div>
<div class="btn_modal">
    <button>click to show modal</button>
    <Modal v-model="isShowModal"> 11111 </Modal>
</div>
</template>
<script>
export default {
    data() {
        return {
            isShowBlock: false,
            isShowModal: false,
        }
    }
}
</script>

效果如下:

可以看到,我们在这里通过::after::before能够为元素的前方、后方添加原本不存在于文档流中的元素。另外,需要注意的是,虽然通过这样的方式在元素前后方添加元素很方便,且的确能够向伪元素身上添加事件,但是仍然是比较麻烦的,如果要添加的元素与交互相关,那么尽量还是通过实际元素来实现!而伪元素则用来做一些修饰性的工作。

参考文档

An Ultimate Guide To CSS Pseudo-Classes And Pseudo-Elements

相关推荐
y先森14 分钟前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy14 分钟前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu108301891117 分钟前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿1 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡2 小时前
commitlint校验git提交信息
前端
虾球xz3 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇3 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒3 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员3 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐3 小时前
前端图像处理(一)
前端