【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

相关推荐
web Rookie29 分钟前
JS类型检测大全:从零基础到高级应用
开发语言·前端·javascript
Au_ust37 分钟前
css:基础
前端·css
帅帅哥的兜兜37 分钟前
css基础:底部固定,导航栏浮动在顶部
前端·css·css3
yi碗汤园40 分钟前
【一文了解】C#基础-集合
开发语言·前端·unity·c#
就是个名称41 分钟前
购物车-多元素组合动画css
前端·css
编程一生1 小时前
回调数据丢了?
运维·服务器·前端
丶21361 小时前
【鉴权】深入了解 Cookie:Web 开发中的客户端存储小数据
前端·安全·web
Missmiaomiao2 小时前
npm install慢
前端·npm·node.js
程序员爱技术4 小时前
Vue 2 + JavaScript + vue-count-to 集成案例
前端·javascript·vue.js
并不会5 小时前
常见 CSS 选择器用法
前端·css·学习·html·前端开发·css选择器