CSS 伪类、伪元素的应用实例:电池充电、高能进度条

一、目的

    本文通过 CSS 伪类、伪元素,结合动画 animation 和 Vue 动态样式属性(通过 CSS 变量)的写法,来实现电池充电、高能进度条的效果,如下图所示。

二、基础知识

1、CSS 伪类、伪元素

简单概括成以下 4 点:

1、CSS 伪类是对当前元素下,处于某些特定状态时而添加特殊效果的样式(基于文档之外的抽象,所以叫伪类),不同状态可以应用不同的样式。不产生新元素,写法用单冒号(:)开头,比如 :hover、:active、:visited、:first-child 等。

2、CSS 伪元素是对当前元素下,某些特殊部位应用样式,通过创建虚拟元素实现,一般与 content 属性一起使用(基于元素的抽象,所以叫伪元素)。表示文档中不存在实际的元素,写法用双冒号(::)开头,比如 ::before、::after 等。

3、注意的是,单冒号(:)在一些旧版 CSS 中也被用来表示伪元素,这是为了兼容旧的浏览器,但是在最新的 CSS 规范中,建议应该使用双冒号(::)来表示伪元素,与伪类区分开来。

4、灵活应用 CSS 伪类、伪元素可以创建出更丰富的前端页面效果。

更多详细可以参考以下文档链接:

  • 伪元素 - CSS:层叠样式表 | MDN
  • CSS 伪元素 | 菜鸟教程

2、CSS 变量 var()

定义:用于插入自定义属性,如果一个属性在多处被使用,该方法就很有用。

语法:var(custom-property-name, value),参数说明如下表格。

描述
custom-property-name必需。自定义属性的名称,必需以 -- 开头。
value可选。备用值,在属性不存在的时候使用。

详细使用示例:

/* 在 :root 上使用自定义属性,其中 :root 表示文档根元素,该定义将在整个文档内生效 */
:root {
  --main-bg-color: red;
  --second-bg-color: var(--main-bg-color); /* 可以继承自其他已定义的变量,称为派生变量 */
  --main-margin: 20px;
}
#div1 {
  background-color: var(--main-bg-color); /* 等同于 background-color: red; */

  --main-txt-color: blue; /* 也可以在局部定义变量 */
  color: var(--main-txt-color); /* 等同于 color: blue; */
}
#div2 {
  background-color: var(--second-bg-color); /* 等同于 background-color: red; */

  /* 如果一个变量未被定义,可以使用回退值来替代 */
  padding: var(--main-padding, 10px); /* 等同于 padding: 10px; */

  /* 使用自定义属性作为回退值 */
  margin: var(--second-margin, var(--main-margin, 30px)); /* 等同于 margin: 20px; 因为 --main-margin 有被设置,所以它的回退值不生效*/
}

CSS 变量可以被 JavaScript 动态修改,根据上面示例来操作,如下代码:

// 语法:DOM.style.setProperty(custom-property-name, value)
document.getElementById('div1').style.setProperty('--main-txt-color', 'green')

三、具体操作实现

    为了节省代码,达到简单实用的目的,本次实例代码采用 Vue2 框架,ElementUI 组件库,搭配 CSS 预处理器 Scss 完成的。

    Scss 写样式能用更简单且高级的写法降低开发成本,比如嵌套规则,父选择器 & 等,如果需要 HTML + CSS + JS 的形式,读者可以自行转化。

实例 1 —— Battery.vue 组件:

  1. 首先通过 CSS 伪元素描画出电池雏形和电池容量,同时加入闪电图标;
  2. 接着实现充电时波浪效果所需的容器,通过 CSS 伪类中的 hover 来实现鼠标悬停时效果;
  3. 然后通过 CSS 伪元素描画出充电时的波浪,让 CSS 伪类 hover 与 CSS 伪元素相结合,并加上动画实现样式效果;
  4. 最后通过 Vue 动态属性 :style 绑定值传入 CSS 中的变量 var() 使用,实现动态变化。更多具体内容查看下面完整代码。
<template>
  <div style="padding: 50px;">
    <div class="battery" :style="{'--height': `${100 - elecVal || 0}%`}">
      <img :src="iconUrl" alt="闪电icon">
      <div class="cover" :style="{'--top': `${0 - elecVal || 0}%`}"></div>
    </div>

    <div style="margin-top: 20px;">
      当前电量:
      <el-input-number
        v-model="elecVal"
        :min="0"
        :max="100"
        :step="5"
        :precision="2"
        controls-position="right"
        style="width: 120px;"
      ></el-input-number>
      %
    </div>
    
  </div>
</template>

<script>
export default {
  data() {
    return {
      elecVal: 75, // 电池电量
      iconUrl: 'https://showdoc.keytop.cn/Public/Uploads/2024-04-28/662dbe484313f.png' // 图标线上地址
    }
  }
}
</script>

<style lang="scss" scoped>
.battery { // 电池容器
  width: 100px;
  height: 150px;
  background: rgb(246, 246, 246);
  border: 1px solid rgb(211, 211, 211);
  border-radius: 5px; // 大小、背景、边框
  position: relative; // 后面绝对定位的前提
  img { // 让闪电图标在电池里水平垂直居中,并处于高层级
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    z-index: 100;
  }
  &::before { // 伪元素 - 模拟电池正极头
    content: "";
    width: 50px;
    height: 15px;
    position: absolute;
    left: 50%;
    top: -15px;
    transform: translate(-50%, 0); // 大小,水平居中,垂直定位
    background: rgb(246, 246, 246);
    border: 1px solid rgb(211, 211, 211);
    border-bottom: none;
    border-radius: 5px 5px 0 0; // 背景、边框
  }
  &::after { // 伪元素 - 模拟电量容量
    content: "";
    background-color: rgb(68, 220, 148); // 容量颜色
    position: absolute;
    left: 0;
    top: var(--height); // 容量大小,通过值传入动态变化
    right: 0;
    bottom: 0;
  }
  .cover{ // 充电时波浪效果容器
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0;
    top: 0; // 占满整个原电池容器
    overflow: hidden; // 超出部分隐藏
    z-index: 10;
  }
  &:hover{ // 伪类 - 当鼠标 hover 在电池上时,模拟正在充电的波浪效果
    .cover::before, .cover::after{ // 伪元素 - 两层波浪
      content: "";
      background: rgba(246, 246, 246, 0.8);
      border-radius: 40% 30%;
      position: absolute;
      width: 150px;
      height: 150px;
      left: -30%;
      top: var(--top); // 波浪所处位置,通过值传入动态变化
      transform: translate(-50%, 0); // 大小,水平居中,垂直定位
      animation: coverBefore 10s linear infinite; // 通过动画实现波浪
    }
    .cover::after{
      background: rgba(246, 246, 246, 0.6); // 通过背景色深浅来体现出两层效果
      animation: coverAfter 10s linear infinite;
    }
  }
}
// 定义的动画
@keyframes coverBefore {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
@keyframes coverAfter {
  0% {
    transform: rotate(30deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
</style>

实例 2 —— EnergyProgress.vue 组件:

  1. 首先通过 CSS 描画出进度条容器,设置背景色及背景区域为 content-box;
  2. 接着通过 CSS 伪元素来填充进度条,让其与进度条容器契合,设置相同的 height、padding、background-clip,通过 linear-gradient() 实现填充的渐变颜色;
  3. 然后再通过 CSS 伪元素描画出结尾节点,并对节点的中心点进行定位;
  4. 最后通过 Vue 动态属性 :style 绑定值传入 CSS 中的变量 var() 使用,实现动态变化。更多具体内容查看下面完整代码。
<template>
  <!-- 这里使用该背景色只是为了效果看得更明显而已 -->
  <div style="padding: 50px; background-color: #000; color: #fff;">
    <div class="energy-progress" :style="{'--width': `${progress || 0}%`}"></div>

    <div style="margin-top: 20px;">
      当前进度条:
      <el-input-number
        v-model="progress"
        :min="0"
        :max="100"
        :step="5"
        :precision="2"
        controls-position="right"
        style="width: 120px;"
      ></el-input-number>
      %
    </div>
  </div>
</template>

<script>
  export default {
    data(){
      return{
        progress: 66.6, // 进度条值
      }
    }
  }
</script>

<style lang="scss" scoped>
.energy-progress{ // 进度条容器
  width: 300px;
  height: 15px; // 大小
  background-color: rgb(22, 91, 128);
  padding: 3px 0;
  background-clip: content-box; // 缩小容器本身,为了结尾的节点让出空间
  position: relative; // 后面绝对定位的前提
  &::before{ // 伪元素 - 已填充进度条的部分
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    width: var(--width); // 填充容量,通过值传入动态变化
    height: 15px;
    padding: 3px 0;
    background-clip: content-box; // 为了与进度条容器契合,同理的
    background-image: linear-gradient(to right, rgb(22, 91, 128) 0%, rgb(97, 177, 242) 70%, #fff 100%); // 进度条填充颜色渐变效果
  }
  &::after{ // 伪元素 - 结尾节点
    content: "";
    position: absolute;
    top: 0;
    left: var(--width); // 根据填充容量定位,通过值传入动态变化
    width: 6px;
    height: 15px; // 大小
    background-color: #fff;
    border-radius: 5px;
    margin-left: -3px; // 这个设为宽度一半的负值,让原本是根据左边框对准位置的,这下让其中心对准位置了
    transform: rotate(30deg);
  }
  &:hover{ // 伪类 - 当鼠标 hover 在电池上时,模拟进度条高能效果
    cursor: pointer;
    &::before{ // 伪元素 - 宽度填充动画(1 秒完成,且先慢后快)
      animation: moveBefore 1s;
    }
    &::after{ // 伪元素 - 结尾节点填充动画(1 秒完成,且先慢后快)
      animation: moveAfter 1s;
    }
  }
}
// 定义的动画
@keyframes moveBefore {
  0% {
    width: 0;
  }
  100% {
    width: var(--width);
  }
}
@keyframes moveAfter {
  0% {
    left: 0;
  }
  100% {
    left: var(--width);
  }
}
</style>

    这是我本人在工作学习中做的一些总结,同时也分享出来给需要的小伙伴哈 ~ 供参考学习,有什么建议也欢迎评论留言,转载请注明出处哈,感谢支持!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/586408.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何提升制造设备文件汇集的可靠性和安全性?

制造设备文件汇集通常指的是将与制造设备相关的各种文档和资料进行整理和归档的过程。这些文件可能包括但不限于&#xff1a; 生产数据&#xff1a;包括生产计划、订单信息、生产进度等。 设计文件&#xff1a;如CAD图纸、设计蓝图、产品模型等。 工艺参数&#xff1a;用于指…

新唐的nuc980/nuc972的开发1-环境和源码同步

开发环境安装 1.1更新源 服务器端&#xff1a;可以参考&#xff1a;Linux替换清华源_更改清华源-CSDN博客 下面是桌面端的方法&#xff1a; 打开系统的软件中心&#xff0c;选择自己想要使用的源 更新缓存 1.2安装必须的库 apt-get install patch apt-get install libc6-dev …

ClickHouse高原理与实践

ClickHouse高原理与实践 1 ClickHouse的特性1.1. OLAP1.2. 列式存储1.3. 表引擎1.4. 向量化执行1.5. 分区1.6. 副本与分片1.7 其他特性 2. ClickHouse模块设计2.1 Parser分析器与Interpreter解释器2.2 Storage2.3 Column与Field2.4 DataType2.5 Block2.6 Cluster与Replication …

数据库基础--MySQL简介以及基础MySQL操作

数据库概述 数据库&#xff08;DATABASE&#xff0c;简称DB&#xff09; 定义:是按照数据结构来组织、存储和管理数据的仓库.保存有组织的数据的容器(通常是一个文件或一组文件) 数据库管理系统(Database Management System,简称DBMS) 专门用于管理数据库的计算机系统软件;…

机器学习:深入解析SVM的核心概念【一、间隔与支持向量】

直接阅读原始论文可能有点难和复杂&#xff0c;所以导师直接推荐我阅读周志华的《西瓜书》&#xff01;&#xff01;然后仔细阅读其中的第六章&#xff1a;支持向量机 间隔与支持向量 **问题一&#xff1a;什么叫法向量&#xff1f;为什么是叫法向量**什么是法向量&#xff1f;…

c#数据库: 10.调用存储过程查询信息,并显示在窗体上

查询女生信息&#xff0c;并将信息显示在窗体上: 原数据表//右键数据库名,新建查询 ------------- 新建查询窗口,添加新建存储过程Procedure_GetGirls1和查询代码如下 : CREATE PROCEDURE dbo.Procedure_GetGirls1 /*存储过程名称*/ AS SELECT * f…

如何通过前后端交互的方式制作Excel报表

前言 Excel拥有在办公领域最广泛的受众群体&#xff0c;以其强大的数据处理和可视化功能&#xff0c;成了无可替代的工具。它不仅可以呈现数据清晰明了&#xff0c;还能进行数据分析、图表制作和数据透视等操作&#xff0c;为用户提供了全面的数据展示和分析能力。 今天小编就…

2024年武汉东湖高新水测成绩出来了

本次水测通过人员有1016名&#xff0c;通过的人数还是蛮多的&#xff0c;水测其实没有大家想象的那么难&#xff0c;现在职称评审都是水测线下评审的模式进行的。 水平测试分机考&#xff0c;笔试和面试答辩&#xff0c;各区随机安排选其一&#xff0c;机考就相当于考驾照刷题&…

HTML:元素分类

HTML&#xff1a;元素分类 概述块级元素&#xff08;Block-level Elements&#xff09;内联元素&#xff08;Inline Elements&#xff09;替换元素&#xff08;Replaced Elements&#xff09;表单元素&#xff08;Form Elements&#xff09; 概述 HTML&#xff08;HyperText M…

如何使用Spring Boot导出数据到Excel表格

在开发应用程序时&#xff0c;经常会遇到将数据导出到Excel表格的需求。Spring Boot提供了简单而有效的方法来实现这个功能。本文将介绍如何使用Spring Boot和Apache POI库将数据导出到Excel表格&#xff0c;并提供一个示例代码来演示该过程。 1. 准备工作 首先&#xff0c;确…

从Paint 3D入门glTF

Paint 3D Microsoft Paint 3D是微软的一款图像编辑软件&#xff0c;它是传统的Microsoft Paint程序的升级版。 这个新版本的Paint专注于三维设计和创作&#xff0c;使用户可以使用简单的工具创建和编辑三维模型。 Microsoft Paint 3D具有直观的界面和易于使用的工具&#xff0…

C语言入门课程学习笔记-7

C语言入门课程学习笔记-7 第31课 - 初探程序中的函数实验-函数调用实验-函数求前n个正整数和 第32课 - 深入浅出函数调用第33课 - 函数定义细节剖析实验-返回int实验-返回void 第34课 - 函数参数深度剖析实验-形参实参实验-数组元素作为函数形参小结 第35课 - 编写函数对数组排…

WebAuthn 无密码身份认证

文章目录 WebAuthn简介工作原理组成部分架构实现注册认证应用场景案例演示 WebAuthn简介 WebAuthn&#xff0c;全称 Web Authentication&#xff0c;是由 FIDO 联盟&#xff08;Fast IDentity Online Alliance&#xff09;和 W3C&#xff08;World Wide Web Consortium&#x…

cisp证有用吗?

CISP证书肯定是有用的&#xff01;就像你说的&#xff0c;少一个证不如多一个证&#xff0c;总比“证到用时方恨少”的好&#xff01;既然你想往网络安全方向发展&#xff0c;考个CISP还是有必要的&#xff0c;CISP目前考试比较简单&#xff0c;拿证书还是比较容易的&#xff0…

【天龙怀旧服】攻略day8

关键字&#xff1a; 高血祭学习、角色伤害、幻魂升级 1】高血祭学习是否需要花费99金 珍兽手动技能分为分开阳类/破军类 高血祭属于开阳类 当已学会开阳类&#xff08;如肉墙&#xff09;学习高血祭&#xff0c;仅需1.70金&#xff0c;属于替换 而已学会破军类&#xff08;…

GitLab常用指令!(工作中常用的)

目录 克隆代码创建分支切换分支将代码提交到分支当中Merge合并 克隆代码 复制完地址&#xff0c;打开Git Bash&#xff0c;然后 git clone “复制的地址”创建分支 创建new_test分支 git branch new_test切换分支 切换到new_test分支 git checkout new_test将代码提交到分…

element的el-table 解决表格多页选择数据时,数据被清空

问题&#xff1a;切换页码时&#xff0c;勾选的数据会被清空 重点看我圈出来的&#xff0c;直接复制&#xff0c;注意&#xff0c;我这里 return row.productId;一般大家的是 return row.id,根据接口定的唯一变量 :row-key"getRowKeys"​​​​​​​:reserve-sele…

预编码算法学习笔记

文章目录 1. 基本原理2. 常见应用2.1 自编码器2.2 变分自编码器2.3 稀疏自编码器 3. 学习笔记 在机器学习领域&#xff0c;预编码算法是一种强大的工具&#xff0c;用于将高维数据映射到低维表示&#xff0c;从而提取数据中的重要特征。本文将介绍预编码算法的基本原理、常见应…

Spring - 9 ( 10000 字 Spring 入门级教程 )

一&#xff1a; MyBatis XML 配置文件 Mybatis 的开发有两种方式&#xff1a; 注解XML 我们已经学习了注解的方式, 接下来我们学习 XML 的方式 MyBatis XML 的方式需要以下两步: 配置数据库连接字符串和 MyBatis写持久层代码 1.1 配置连接字符串和 MyBatis 此步骤需要进…

04 Docker练习赛从0开始到 docker 镜像提交

1.1 本地安装 docker 工具 这里以ubutun下安装docker为例,其他操作系统安装命令略有不同,可自行百度。(建议使用阿里源安装速度快) sudo apt install docker.io如果你本地有gpu,请继续执行如下命令以支持gpu调用: 注意: 英伟达对 docker 支持的 linux 发行版:https:/…