【动画消消乐】HTML+CSS 自定义加载动画:清新折叠方块效果 063(附源码及原理详解)
前言
Hello!小伙伴!
非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~
自我介绍ଘ(੭ˊᵕˋ)੭
昵称:海轰
标签:程序猿|C++选手|学生
简介:因C语言结识编程,随后转入计算机专业,有幸拿过国奖、省奖等,已保研。目前正在学习C++/Linux(真的真的太难了~)
学习经验:扎实基础 + 多做笔记 + 多敲代码 + 多思考 + 学好英语!
【动画消消乐】 平时学习生活比较枯燥,无意之间对一些网页、应用程序的过渡/加载动画产生了浓厚的兴趣,想知道具体是如何实现的? 便在空闲的时候学习下如何使用css实现一些简单的动画效果,文章仅供作为自己的学习笔记,记录学习生活,争取理解动画的原理,多多“消灭”动画!
效果展示

Demo代码
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body>
<section><span></span></section>
</body>
</html>
CSS
html, body {
margin: 0;
height: 100%;
}
body {
display: flex;
justify-content: center;
align-items: center;
background: #ed556a;
/* background-color: #82466e; */
animation: backColor 4s infinite;
}
section {
width: 650px;
height: 300px;
padding: 10px;
position: relative;
display: flex;
align-items: center;
justify-content: center;
border: 2px solid white;
}
span {
width: 48px;
height: 48px;
background-color: goldenrod;
display: inline-block;
position: relative;
transform: rotate(45deg);
}
span::before {
content: '';
width: 24px;
height: 24px;
position: absolute;
left: 0;
top: -24px;
animation: loading_1 4s ease infinite;
}
span::after {
content: '';
position: absolute;
left: 0;
top: 0;
width: 24px;
height: 24px;
background: rgba(255, 255, 255, 0.85);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
animation: loading_2 2s ease infinite;
}
@keyframes loading_1 {
0% {
box-shadow: 0 24px rgba(255, 255, 255, 0), 24px 24px rgba(255, 255, 255, 0), 24px 48px rgba(255, 255, 255, 0), 0px 48px rgba(255, 255, 255, 0)
}
12% {
box-shadow: 0 24px rgba(255, 255, 255, 1), 24px 24px rgba(255, 255, 255, 0), 24px 48px rgba(255, 255, 255, 0), 0px 48px rgba(255, 255, 255, 0)
}
25% {
box-shadow: 0 24px rgba(255, 255, 255, 1), 24px 24px rgba(255, 255, 255, 1), 24px 48px rgba(255, 255, 255, 0), 0px 48px rgba(255, 255, 255, 0)
}
37% {
box-shadow: 0 24px rgba(255, 255, 255, 1), 24px 24px rgba(255, 255, 255, 1), 24px 48px rgba(255, 255, 255, 1), 0px 48px rgba(255, 255, 255, 0)
}
50% {
box-shadow: 0 24px rgba(255, 255, 255, 1), 24px 24px rgba(255, 255, 255, 1), 24px 48px rgba(255, 255, 255, 1), 0px 48px rgba(255, 255, 255, 1)
}
62% {
box-shadow: 0 24px rgba(255, 255, 255, 0), 24px 24px rgba(255, 255, 255, 1), 24px 48px rgba(255, 255, 255, 1), 0px 48px rgba(255, 255, 255, 1)
}
75% {
box-shadow: 0 24px rgba(255, 255, 255, 0), 24px 24px rgba(255, 255, 255, 0), 24px 48px rgba(255, 255, 255, 1), 0px 48px rgba(255, 255, 255, 1)
}
87% {
box-shadow: 0 24px rgba(255, 255, 255, 0), 24px 24px rgba(255, 255, 255, 0), 24px 48px rgba(255, 255, 255, 0), 0px 48px rgba(255, 255, 255, 1)
}
100% {
box-shadow: 0 24px rgba(255, 255, 255, 0), 24px 24px rgba(255, 255, 255, 0), 24px 48px rgba(255, 255, 255, 0), 0px 48px rgba(255, 255, 255, 0)
}
}
@keyframes loading_2 {
0% {
transform: translate(0, 0) rotateX(0) rotateY(0)
}
25% {
transform: translate(100%, 0) rotateX(0) rotateY(180deg)
}
50% {
transform: translate(100%, 100%) rotateX(-180deg) rotateY(180deg)
}
75% {
transform: translate(0, 100%) rotateX(-180deg) rotateY(360deg)
}
100% {
transform: translate(0, 0) rotateX(0) rotateY(360deg)
}
}
原理详解
步骤1
使用span标签,设置为
- 宽度、高度均为48px
- 背景色:棕色
- 相对定位
span {
width: 48px;
height: 48px;
background-color: goldenrod;
position: relative;
}
效果图如下:

步骤2
使用span::before伪元素,设置为
- 绝对定位( left: 0 top: -24px)
- 宽度、高度均为24px
- 背景色:白色
span::before {
content: '';
width: 24px;
height: 24px;
position: absolute;
background-color: #fff;
left: 0;
top: -24px;
}
效果图如下:

步骤3
使用box-shadow为span::before设置四个阴影
span::before {
box-shadow: 0 24px red, /* 阴影1 */
24px 24px orange, /* 阴影2 */
24px 48px yellow, /* 阴影3 */
0px 48px green; /* 阴影4 */
}
四个阴影位置关系如下:

注:这里为了视觉显示区分四个阴影,每个阴影采用了不同的颜色,在实际中其实每个阴影都设置为白色。
步骤4
为span::before的四个阴影添加动画loading_1
每个阴影只有两种状态:显示 与 不显示
显示与否则是通过设置颜色的透明级别为0或1
比如
- 阴影显示:0 24px rgba(255, 255, 255, 1)
- 阴影不显示:0 24px rgba(255, 255, 255, 0)
关键有 九帧
第一帧
- 阴影1、2、3、4均不显示
box-shadow: 0 24px rgba(255, 255, 255, 0),
24px 24px rgba(255, 255, 255, 0),
24px 48px rgba(255, 255, 255, 0),
0px 48px rgba(255, 255, 255, 0);
效果图如下:

第二帧
- 阴影1显示
- 阴影2、3、4不显示
box-shadow: 0 24px rgba(255, 255, 255, 1),
24px 24px rgba(255, 255, 255, 0),
24px 48px rgba(255, 255, 255, 0),
0px 48px rgba(255, 255, 255, 0);
效果图如下:

第三帧
- 阴影1、2显示
- 阴影3、4不显示
box-shadow: 0 24px rgba(255, 255, 255, 1),
24px 24px rgba(255, 255, 255, 1),
24px 48px rgba(255, 255, 255, 0),
0px 48px rgba(255, 255, 255, 0);
效果图如下:

第四帧
- 阴影1、2、3显示
- 阴影4不显示
box-shadow: 0 24px rgba(255, 255, 255, 1),
24px 24px rgba(255, 255, 255, 1),
24px 48px rgba(255, 255, 255, 1),
0px 48px rgba(255, 255, 255, 0);
效果图如下:

第五帧
- 阴影1、2、3、4都显示
box-shadow: 0 24px rgba(255, 255, 255, 1),
24px 24px rgba(255, 255, 255, 1),
24px 48px rgba(255, 255, 255, 1),
0px 48px rgba(255, 255, 255, 1);
效果图如下:

第六帧
- 阴影2、3、4显示
- 阴影1不显示
box-shadow: 0 24px rgba(255, 255, 255, 0),
24px 24px rgba(255, 255, 255, 1),
24px 48px rgba(255, 255, 255, 1),
0px 48px rgba(255, 255, 255, 1);
效果图如下:

第七帧
- 阴影3、4显示
- 阴影1、2不显示
box-shadow: 0 24px rgba(255, 255, 255, 0),
24px 24px rgba(255, 255, 255, 0),
24px 48px rgba(255, 255, 255, 1),
0px 48px rgba(255, 255, 255, 1);
效果图如下:

第八帧
- 阴影4显示
- 阴影1、2、3不显示
box-shadow: 0 24px rgba(255, 255, 255, 0),
24px 24px rgba(255, 255, 255, 0),
24px 48px rgba(255, 255, 255, 0),
0px 48px rgba(255, 255, 255, 1);
效果图如下:

第九帧
- 阴影1、2、3、4均不显示
box-shadow: 0 24px rgba(255, 255, 255, 0),
24px 24px rgba(255, 255, 255, 0),
24px 48px rgba(255, 255, 255, 0),
0px 48px rgba(255, 255, 255, 0);
效果图如下:

设置动画animation使得从第一帧平稳过渡至第九帧
animation: loading_1 4s ease infinite;
@keyframes loading_1 {
0% {
box-shadow: 0 24px rgba(255, 255, 255, 0), 24px 24px rgba(255, 255, 255, 0), 24px 48px rgba(255, 255, 255, 0), 0px 48px rgba(255, 255, 255, 0)
}
12% {
box-shadow: 0 24px rgba(255, 255, 255, 1), 24px 24px rgba(255, 255, 255, 0), 24px 48px rgba(255, 255, 255, 0), 0px 48px rgba(255, 255, 255, 0)
}
25% {
box-shadow: 0 24px rgba(255, 255, 255, 1), 24px 24px rgba(255, 255, 255, 1), 24px 48px rgba(255, 255, 255, 0), 0px 48px rgba(255, 255, 255, 0)
}
37% {
box-shadow: 0 24px rgba(255, 255, 255, 1), 24px 24px rgba(255, 255, 255, 1), 24px 48px rgba(255, 255, 255, 1), 0px 48px rgba(255, 255, 255, 0)
}
50% {
box-shadow: 0 24px rgba(255, 255, 255, 1), 24px 24px rgba(255, 255, 255, 1), 24px 48px rgba(255, 255, 255, 1), 0px 48px rgba(255, 255, 255, 1)
}
62% {
box-shadow: 0 24px rgba(255, 255, 255, 0), 24px 24px rgba(255, 255, 255, 1), 24px 48px rgba(255, 255, 255, 1), 0px 48px rgba(255, 255, 255, 1)
}
75% {
box-shadow: 0 24px rgba(255, 255, 255, 0), 24px 24px rgba(255, 255, 255, 0), 24px 48px rgba(255, 255, 255, 1), 0px 48px rgba(255, 255, 255, 1)
}
87% {
box-shadow: 0 24px rgba(255, 255, 255, 0), 24px 24px rgba(255, 255, 255, 0), 24px 48px rgba(255, 255, 255, 0), 0px 48px rgba(255, 255, 255, 1)
}
100% {
box-shadow: 0 24px rgba(255, 255, 255, 0), 24px 24px rgba(255, 255, 255, 0), 24px 48px rgba(255, 255, 255, 0), 0px 48px rgba(255, 255, 255, 0)
}
}
效果图如下:

步骤5
取消span::before的背景色
将此时形成的动画定义为动画1

步骤6
先忽略span::before形成的动画,暂时注释掉
使用span::after伪元素,设置为
- 绝对定位(top:0 left:0)
- 宽带、高度均为24px
- 背景色:白色,透明级别:0.85
- 阴影:0 0 10px rgba(0, 0, 0, 0.15);
span::after {
content: '';
position: absolute;
left: 0;
top: 0;
width: 24px;
height: 24px;
background: rgba(255, 255, 255, 0.85);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
}
效果图如下:

步骤7
为span::after添加动画
有5个关键帧
第一帧(初始状态)
- 二维空间:右移:0 下移:0
- 三维空间:绕x轴旋转0度 绕y轴旋转0度
transform: translate(0, 0) rotateX(0) rotateY(0)
第二帧(相对于初始状态)
- 二维空间:右移:100% 下移:0 (100%是指相对于自身的大小,若自身宽100px 那就移动100px)
- 三维空间:绕x轴旋转0度 绕y轴旋转180度
transform: translate(100%, 0) rotateX(0) rotateY(180deg)
第一帧 过渡至 第二帧 效果图如下

第三帧 (相对于初始状态)
- 二维空间:右移:100% 下移:100%
- 三维空间:绕x轴旋转-180度 绕y轴旋转180度
transform: translate(100%, 100%) rotateX(-180deg) rotateY(180deg)
第二帧 过渡至 第三帧 效果图如下

第四帧(相对于初始状态)
- 二维空间:右移:0 下移:100%
- 三维空间:绕x轴旋转-180度 绕y轴旋转360度
transform: translate(0, 100%) rotateX(-180deg) rotateY(360deg)
第三帧 过渡至 第四帧 效果图如下

第五帧(相对于初始状态)
- 二维空间:右移:0 下移:0
- 三维空间:绕x轴旋转0度 绕y轴旋转360度
transform: translate(0, 0) rotateX(0) rotateY(360deg);
第四帧 过渡至 第五帧 效果图如下

设置动画从第一帧过渡至第五帧
animation: loading_2 2s ease infinite;
@keyframes loading_2 {
0% {
transform: translate(0, 0) rotateX(0) rotateY(0)
}
25% {
transform: translate(100%, 0) rotateX(0) rotateY(180deg)
}
50% {
transform: translate(100%, 100%) rotateX(-180deg) rotateY(180deg)
}
75% {
transform: translate(0, 100%) rotateX(-180deg) rotateY(360deg)
}
100% {
transform: translate(0, 0) rotateX(0) rotateY(360deg)
}
}
将此动画定义为动画2
效果图如下

步骤8
动画1为:

动画2为:

将动画1与动画2叠加
效果图如下

步骤9
将span旋转45度
span {
transform: rotate(45deg);
}
效果图如下:

步骤10
取消span背景色
得到最终效果

结语
文章仅作为学习笔记,记录从0到1的一个过程
希望对您有所帮助,如有错误欢迎小伙伴指正~
我是海轰ଘ(੭ˊᵕˋ)੭,如果您觉得写得可以的话,请点个赞吧
谢谢支持️

【动画消消乐】HTML+CSS 自定义加载动画:清新折叠方块效果 063(附源码及原理详解)的更多相关文章
- 【动画消消乐】HTML+CSS 自定义加载动画 061
前言 Hello!小伙伴! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出- 自我介绍ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简介:因C语言结识编程,随后转入计算机专 ...
- 【动画消消乐】HTML+CSS 自定义加载动画 064(currentColor的妙用!)
前言 Hello!小伙伴! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出- 自我介绍ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简介:因C语言结识编程,随后转入计算机专 ...
- 【动画消消乐】HTML+CSS 自定义加载动画 065
前言 Hello!小伙伴! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出- 自我介绍 ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简介:因C语言结识编程,随后转入计 ...
- 【动画消消乐】HTML+CSS 自定义加载动画:怦然心跳 066
前言 Hello!小伙伴! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出- 自我介绍 ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简介:因C语言结识编程,随后转入计 ...
- 【动画消消乐】HTML+CSS 自定义加载动画 062
效果展示 Demo代码 HTML <!DOCTYPE html> <html lang="en"> <head> <meta charse ...
- leaflet-webpack 入门开发系列二加载不同在线地图切换显示(附源码下载)
前言 leaflet-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载地址 w ...
- 高性能页面加载技术(流水线加载)BigPipe的C#简单实现(附源码)
一,BigPipe简介 BigPipe是一个重新设计的基础动态网页服务体系.大体思路是,分解网页成叫做Pagelets的小块,然后通过Web服务器和浏览器建立管道并管理他们在不同阶段的运行.这是类似于 ...
- html自定义加载动画
整体代码 HTML 实现自定义加载动画,话不多说如下代码所示: <!DOCTYPE html> <html lang="en"> <head> ...
- CSS 实现加载动画之八-圆点旋转
这篇文件介绍的动画是QQ邮箱APP里的加载动画,效果类似,但是不完全一样.实现过程不复杂,这里不详细解释了,直接上源码.另外还有一种实现方式,利用元素的3D转换加平移. 1. 先看截图 2. 源代码 ...
随机推荐
- HAL库|神器cubemx的正确打开方式
前言 工欲善其事,必先利其器.HAL库的开发不一定必须使用cubemx,但是使用了cubemx,你绝对不会后悔.基于一些小伙伴对cubemx的使用还有一些疑问,本次小飞哥从新建工程到生成工程,编写应用 ...
- 从“信息化”到“智慧化”,GVS视声将如何赋能智慧医院?
4月23日-25日,2021年中华医院信息网络大会(CHINC)盛大举办,今年首次携手中国医院建筑与装备创新发展大会,同期同地亮相杭州国际博览中心,塑造了全新的"双引擎"品牌盛会. ...
- QT环境变量设置
首先找到自己对应的目录 我的如图 还有一个路径 将这两个路径添加到系统变量的Path中
- NX二次开发-矩阵乘矩阵的几何意义
函数:UF_MTX3_multiply() 或者UF_MTX3_multiply_t().推荐使用UF_MTX3_multiply() 函数说明:矩阵相乘,得到新的矩阵,如下图WCS与ABS重合,在暗 ...
- Spring Boot WebFlux-01——WebFlux 快速入门实践
第01课:WebFlux 快速入门实践 Spring Boot 2.0 spring.io 官网有句醒目的话是: BUILD ANYTHING WITH SPRING BOOT Spring Boot ...
- 入门实践丨如何在K3s上部署Web应用程序
在本文中,我们将使用Flask和JavaScript编写的.带有MongoDB数据库的TODO应用程序,并学习如何将其部署到Kubernetes上.这篇文章是针对初学者的,如果你之前没有深度接触过Ku ...
- 关于kubernetes的十七个实验(一)
实验综述 Kubernetes用来管理云平台上的容器化应用,这里从 https://www.katacoda.com/courses/kubernetes 学习Kubernetes的使用,对Kuber ...
- CloudCanal
CloudCanal 是一款数据迁移同步工具,帮助企业快速构建高质量数据流通通道,产品包含 SaaS 模式和私有输出专享模式.开发团队核心成员来自大厂,具备数据库内核.大规模分布式系统.云产品构建背景 ...
- 其实 Linux IO 模型没那么难
文章首发于公众号「陈树义」及个人博客 shuyi.tech,欢迎关注访问. 博主个人独立站点开通啦!欢迎点击访问:https://shuyi.tech IO 其实就是 Input 和 Output,在 ...
- QGIS如何打开ArcGIS创建的GDB数据库文件
引言 QGIS作为一种开源的地理信息处理软件由于其界面友好.渲染速度快.开源免费等特性而获得业内很多人士的青睐,然而在实际的生产和处理过程中,GIS数据往往存储在ArcGIS的文件地理数据库(Geod ...