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-numberv-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-numberv-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>

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高德地图+HTML+点击事件+自定心信息窗体

代码如下 <!doctype html> <html><head><meta charset"utf-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"initial-scale1.0, user-scalableno, width…

谷粒商城实战(020 RabbitMQ-消息确认)

Java项目《谷粒商城》架构师级Java项目实战&#xff0c;对标阿里P6-P7&#xff0c;全网最强 总时长 104:45:00 共408P 此文章包含第258p-第p261的内容 消息确认 生产者 publishers 消费者 consumers 设置配置类 调用api 控制台 抵达brocker 代理 新版本ReturnCallbac…

bash逻辑取反技巧(bool_not函数)

bash函数不支持像其他高级语言一样的高级的返回变量&#xff0c;bash只能返回数值。 bash有bool变量&#xff0c;但是bool操作符号只能存在于[ ... ]、[[ ... ]]等特定语法结构中 举个例子 bash中&#xff0c;想要对bool变量y取反并赋值给变量x &#xff0c;这样写x!$y是不合…

OpenCV 填洼处理

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 这里使用一种从外边缘往内部收缩的算法来实现对图像进行填洼处理,当然,在这个过程中,我们需要通过根据指定的最小坡度来对低洼区域进行高程修正处理。(OpenCV版本) 二、实现代码 ImageSmoothing.h #pragma onc…

DevEco Studio mac版启动不了【鸿蒙开发Bug已解决】

文章目录 项目场景:问题描述原因分析:解决方案:此Bug解决方案总结Bug解决方案寄语项目场景: 最近也是遇到了这个问题,看到网上也有人在询问这个问题,本文总结了自己和其他人的解决经验,解决了【DevEco Studio mac版启动不了】的问题。 问题描述 报错如下。 -------…

如何判断第三方软件测试公司是否具有资质

在软件开发的过程中&#xff0c;软件测试是确保软件质量、稳定性和用户体验的关键环节。许多企业选择将软件测试工作交给专业的第三方软件测试公司来完成&#xff0c;以确保测试的准确性和公正性。但是&#xff0c;如何判断一个第三方软件测试公司是否具有资质呢&#xff1f;以…

Python urllib 爬虫入门(2)

本文为Python urllib类库爬虫更入门的一些操作和爬虫实例及源码。 目录 模拟浏览器请求 简单模拟 设置随机user-agent 请求超时 HTTP请求类型 Get请求 Post请求 抓取网页动态请求 封装ajax请求 调用 循环调用 抓取小说 封装请求函数 把html写入本地分析 调用 正…

2024年Docker常用操作快速查询手册

目录 一、Linux系统上 Docker安装流程&#xff08;以ubuntu为例&#xff09; 一、卸载所有冲突的软件包 二、设置Docker的apt存储库&#xff08;这里使用的是阿里云软件源&#xff09; 三、直接安装最新版本的Docker 三、安装指定版本的Docker 四、验证Docker是否安装成功…

Linux 手动部署JDK21 环境

1、下载包&#xff08;我下载的是tar) https://www.oracle.com/cn/java/technologies/downloads/#java21 完成后进行上传 2、检查已有JDK&#xff0c;并删除&#xff08;我原有是jdk8&#xff09; rpm -qa | grep -i java | xargs -n1 rpm -e --nodeps3、清理掉 profile中的j…

构建安全通信桥梁:PKI与数字证书

目录 前言 1. 密钥管理 2. 数字证书 3. PKI 4. 证书透明性 5. 实际案例 结论 前言 在数字化时代&#xff0c;信息和数据的传输变得日益频繁和普遍。无论是个人用户还是企业组织&#xff0c;都面临着保护通信和数据安全的重要挑战。而在这个保护的过程中&#xff0c;PKI&…

Mybatis-Plus扩展接口InnerInterceptor

InnerInterceptor 接口就是 MyBatis-Plus 提供的一个拦截器接口&#xff0c;用于实现一些常用的 SQL 处理逻辑&#xff0c;处理 MyBatis-Plus 的特定功能,例如PaginationInnerInterceptor、OptimisticLockerInnerInterceptor 等,都实现了 InnerInterceptor 接口&#xff0c;并添…

LINUX基础培训三十一之实操题模拟测试试卷

一、前言 针对前面章节介绍的基础知识内容,为方便实操锻炼和了解学习的掌握程度,模拟设置了这条基础操作题,在实战过程中曾给部分童鞋实操测试过。本章只给出具体题目内容,实际做题还需要搭建部署对应实操模拟环境以及设置自动评分功能,此处略过没写了,因为环境和评分都跟…

Vue项目打包APK----Vue发布App

时隔多年我又来跟新了&#xff0c;今天给大普家及下前端Vue傻瓜式发布App&#xff0c;话不多说直接上干货。 首先准备开发工具HBuilder X&#xff0c;去官网直接下载即可&#xff0c;算了直接给你们上地址吧HBuilderX-高效极客技巧。 打开软件&#xff0c;文件-->新建--&g…

【XR806开发板试用】基于XR806实现智能小车

一、实验功能&#xff1a; 1、 基于XR806实现WIFI连接路由器 2、 XR806设备创建TCP socket服务器&#xff0c;局域网内通过PC端TCP客服端连接XR806 TCP服务器进行指令控制小车运行&#xff08;指令&#xff21;&#xff1a;前进、&#xff22;&#xff1a;后退、&#xff23;&…

实验15 MVC

二、实验项目内容&#xff08;实验题目&#xff09; 编写代码&#xff0c;掌握MVC的用法。 三、源代码以及执行结果截图&#xff1a; inputMenu.jsp&#xff1a; <% page contentType"text/html" %> <% page pageEncoding "utf-8" %> &…

Element-UI 快速入门

Element-UI 快速入门 引言 在现代Web开发中&#xff0c;前端界面的构建对用户体验至关重要。Element-UI是一个基于Vue.js的组件库&#xff0c;它提供了丰富的界面组件&#xff0c;帮助开发者快速构建出美观且功能全面的网页应用。本文将作为你的快速入门指南&#xff0c;带你…

nvm pnpm powershell

nvm 下载 在 nvm 安装路径下修改 settings.txt root: e:\xxx\nvm path: e:\xxx\nodejs npm_mirror https://npmmirror.com/mirrors/npm/ node_mirror https://npmmirror.com/mirrors/node/nvm list available nvm install 18.20.2 nvm use 18.20.2npm config list npm config …

pta题库答案c语言

PTA&#xff08;Programming Teaching and Assignment&#xff0c;程序设计与教学&#xff09;平台提供了大量的C语言练习题和题目&#xff0c;这些题目覆盖了C语言的各个知识点&#xff0c;包括基础语法、函数、数组、指针、结构体、文件操作等。对于想要提高C语言编程能力的学…

Nginx配置Https缺少SSL模块

1、Linux下Nginx配置https nginx下载和安装此处就忽略&#xff0c;可自行百度 1.1、配置https 打开nginx配置文件 vim /opt/app/nginx/conf/nginx.conf相关https配置 server {listen 443 ssl; #开放端口server_name echarts.net;#域名#redirect to https#ssl on; #旧版#ssl证…

C语言-嵌入式-STM32:FreeRTOS说明和详解

Free即免费的&#xff0c;RTOS的全称是Real time operating system&#xff0c;中文就是实时操作系统。 注意&#xff1a;RTOS不是指某一个确定的系统&#xff0c;而是指一类操作系统。比如&#xff1a;uc/OS&#xff0c;FreeRTOS&#xff0c;RTX&#xff0c;RT-Thread 等这些都…