💖用 CSS 打造会“亲吻”的动画小球

今天,我深入学习了 CSS 高级动画 的实现技巧,并动手写了一个超可爱的动画小球项目!两个白色小球 👯‍♀️ 在屏幕上互动:左边的小球眨眼 😊,右边的小球则会"亲吻" 💋,整个画面温馨又充满童趣。这不仅是一次代码练习,更是一场 CSS 动画的艺术创作!


🧱 项目结构:简洁而优雅

html文件配合 css文件,我们实现了完整的动画界面。这体现了 "结构与样式分离" 的前端最佳实践。

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CSS Animation</title>
  <link rel="stylesheet" href="./style.css">
</head>

<body>
  <div class="container">
    <!-- 女主 -->
    <div class="ball" id="l-ball">
      <div class="face face-l">
        <div class="eye eye-l"></div>
        <div class="eye eye-r"></div>
        <div class="mouth"></div>
      </div>
    </div>
    <!-- 男主 -->
    <div class="ball" id="r-ball">
      <div class="face face-r">
        <div class="eye eye-l eye-r-p"></div>
        <div class="eye eye-r eye-r-p"></div>
        <div class="mouth mouth-r"></div>
        <div class="kiss-m">
          <div class="kiss"></div>
          <div class="kiss"></div>
        </div>
      </div>
    </div>
  </div>
</body>

</html>
css 复制代码
* {
  margin: 0;
  padding: 0;
}

body {
  background-color: rgb(192, 237, 255);
}

.container {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 238px;
  /* background-color: white; */
}

.ball {
  background-color: white;
  border: 8px solid;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  display: inline-block;
  position: relative;
}

.face {
  width: 70px;
  height: 30px;
  position: absolute;
  right: 0;
  top: 30px;
}

/* 伪元素选择器 
  css 声明,像html一样来用,不需要在html里面声明
一定要有content属性 忍者 */
/* 元素内容开始之前 */
.face::after,
.face::before {
  content: "";
  position: absolute;
  width: 18px;
  height: 8px;
  background-color:pink;
  top: 20px;
  border-radius: 50%;
}

.face::before {
  right: -8px;
}

/* 元素内容结束之后 */
.face::after {
  left: -5px;
}

.eye {
  width: 15px;
  height: 14px;
  border-radius: 50%;
  border-bottom: 5px solid;/* 仅保留底部边框形成弧线造型 */
  position: absolute;
}

.eye-l {
  left: 10px;
}

.eye-r {
  right: 5px;
}

.eye-r-p {
  border-top: 5px solid;
  border-bottom: 0px solid;
}

.mouth {
  width: 30px;
  height: 14px;
  border-radius: 50%;
  border-bottom: 5px solid;
  position: absolute;
  bottom: -5px;
  left: 0;
  right: 0;
  transform: translate(3px);
  margin: auto;
  /*平分左右的margin*/
}

/* 动画 */
#l-ball {
  animation: close 4s ease infinite;
  position: relative;
  z-index: 100;
}

@keyframes close {
  0% {
    transform: translate(0);
  }

  20% {
    transform: translate(20px);
  }

  35% {
    transform: translate(20px);
  }

  55% {
    transform: translate(0px);
  }

  100% {
    transform: translate(0px);
  }
}

.face-l {
  animation: face 4s ease infinite;
}

@keyframes face {
  0% {
    transform: translate(0) rotate(0);
  }

  10% {
    transform: translate(0) rotate(0);
  }

  20% {
    transform: translate(5px) rotate(-2deg);
  }

  28% {
    transform: translate(0) rotate(0);
  }

  35% {
    transform: translate(5px) rotate(-2deg);
  }

  50% {
    transform: translate(0) rotate(0);
  }

  100% {
    transform: translate(0) rotate(0);
  }
}

#r-ball {
  animation: kiss 4s ease infinite;
}

@keyframes kiss {
  40% {
    transform: translate(0);
  }

  50% {
    transform: translate(30px) rotate(20deg);
  }

  60% {
    transform: translate(-33px);
  }

  67% {
    transform: translate(-33px);
  }

  77% {
    transform: translate(0px);
  }
}

.mouth-r {
  animation: mouth-m 4s ease infinite;
}

.kiss-m {
  position: absolute;
  left: 20px;
  top: 22px;
  opacity: 0;
  animation: kiss-m 4s ease infinite;
}

.kiss {
  width: 13px;
  height: 10px;
  background-color: white;
  border-left: 5px solid;
  border-radius: 50%;
}

@keyframes kiss-m {
  0% {
    opacity: 0;
  }

  55% {
    opacity: 0;
  }

  66% {
    opacity: 1;
  }

  66.1% {
    opacity: 0;
  }
}

@keyframes mouth-m {
  0% {
    opacity: 1;
  }

  54.9% {
    opacity: 1;
  }

  55% {
    opacity: 0;
  }

  66% {
    opacity: 0;
  }

  66.1% {
    opacity: 1;
  }
}

.face-r {
  left: 0;
  top: 37px;
}

🎭 面向对象的 CSS:.face 基类与多态

readme.md 中提到:"面向对象的 css .face 基类 .face-l 多态"。这正是本项目的核心设计思想!

  • .face 是一个通用基类,定义了脸部的基本位置和尺寸。
  • .face-l.face-r 则是它的"子类",分别应用不同的动画(face 动画 vs 默认静止),实现了 多态行为 ------ 同一个"脸"的结构,在不同球上表现不同动作。
css 复制代码
.face { /* 基类:定义共性 */ }
.face-l { animation: face 4s ease infinite; } /* 左脸:眨眼动画 */
.face-r { /* 右脸:配合亲吻动作 */ }

这种写法让代码高内聚、低耦合,便于维护和扩展 👍。


✨ 关键动画解析

1️⃣ 左球:眨眼动画 👀

通过移动 .face-l 并轻微旋转,模拟"眨眼"效果:

css 复制代码
@keyframes face {
  20%, 35% {
    transform: translate(5px) rotate(-2deg);
  }
}

配合眼睛(.eye)的弧形边框设计,眨眼显得自然又灵动。

2️⃣ 右球:亲吻动画 💋

这是最精彩的部分!右球(#r-ball)执行 kiss 动画:

css 复制代码
@keyframes kiss {
  50% { transform: translate(30px) rotate(20deg); }
  60% { transform: translate(-33px); } /* 快速靠近左球 */
}

同时,嘴巴(.mouth-r)在关键时刻隐藏,一个粉色"亲吻印记"(.kiss-m)短暂出现:

css 复制代码
@keyframes kiss-m {
  66% { opacity: 1; } /* 一闪而过的 kiss 💋 */
}

💖 这个设计巧妙利用了 opacity 和精确的时间控制,让"亲吻"瞬间既浪漫又不突兀!


🎯 技术亮点总结

技术点 说明
水平垂直居中 使用 .container { position: absolute; top/left: 50%; transform: translate(-50%, -50%) },经典且兼容性好 ✅
伪元素绘图 ::before / ::after 画脸颊,无需额外 HTML 元素,轻量高效 🧼
边框绘图技巧 眼睛和嘴巴仅用 border-bottom + border-radius 实现弧线,极简主义美学 🎨
动画时间协调 所有动画统一 4s ease infinite,确保左右球动作同步,节奏和谐 ⏱️

🌈 学习感悟

通过这个小项目,我深刻体会到:

CSS 不只是样式,更是表现力和创造力的工具。

从面向对象的结构设计,到动画关键帧的精细调控,每一步都让我对 CSS 的能力有了新的认识。原来,用几行代码,就能让静态页面"活"起来,传递情感与故事 ❤️。


🔮 下一步计划

  • 添加更多表情(比如害羞 blush、开心 smile)
  • 响应用户交互(点击触发动画)
  • 尝试用 CSS Houdini 实现更复杂的自定义动画

继续加油!CSS 动画的世界,远比想象中更精彩 🚀🌈

相关推荐
Mintopia3 小时前
⚙️ 用 Next.js 玩转压测:**200 Requests/s 的华丽舞步**
前端·javascript·全栈
Mintopia3 小时前
🌐 AIGC与知识图谱:Web端智能问答系统的技术核心
前端·javascript·aigc
2501_938773993 小时前
从字节码生成看 Lua VM 前端与后端协同:编译器与执行器衔接逻辑
开发语言·前端·lua
荻酷社区4 小时前
HTML加密工具EXE软件介绍
前端·html·html加密·html代码加密工具
chxii4 小时前
前后端分离
前端
青衫码上行5 小时前
【Java Web学习 | 第三篇】CSS(2) - 元素显示模式
java·前端·学习
IT_陈寒5 小时前
Redis性能翻倍的5个冷门技巧,90%的开发者都不知道第3个!
前端·人工智能·后端
柑橘乌云_5 小时前
学习记录-package.json的scripts添加参数的方式有那些
前端·学习·node.js·json
清沫5 小时前
规训 AI Agent 实践
前端·ai编程·cursor