纯CSS实现有趣emoji切换开关

这是一个纯CSS创建的动画切换开关,它不仅能够在视觉上吸引用户,还能通过交互提供即时反馈。本文将解析源码的核心实现逻辑,这个项目的核心是使用CSS变量、3D变换和过渡效果来实现一个动态的、响应式的用户界面元素。

关键技术点

  1. CSS变量:用于动态调整样式。
  2. 3D变换:用于创建翻转动画效果。
  3. 过渡效果:用于平滑地改变元素的样式。
  4. emoji:并不是真正的emoji而是通过CSS绘制。

实现步骤

1. HTML

首先需要创建一个基本的HTML结构,包括一个表单元素(checkbox)和一个用于显示Emoji的元素。这里的switch__emoji-face即是开关上面的两个emoji表情。

html 复制代码
<div class="switch">
  <input type="checkbox" class="switch__input" id="toggle">
  <label for="toggle" class="switch__label">Toggle</label>
  <div class="switch__wrapper">
    <div class="switch__emoji">
      <div class="switch__emoji-face"></div>
      <div class="switch__emoji-face"></div>
    </div>
  </div>
</div>
2. CSS

接下来,我们使用CSS来设计这个切换开关的样式。这段CSS代码主要用来实现以下几个目标:

  1. 统一的颜色主题

    • 通过定义 --hue 变量,可以在整个网站中统一色调,使得颜色方案更加一致。
    • --bg--fg 分别定义了背景色和前景色,使得文本和背景之间有良好的对比度,提高可读性。
  2. 动态响应的字体大小

    • 使用 calc() 函数和视口宽度单位 vw,可以根据屏幕大小动态调整字体大小,实现响应式设计。
  3. 平滑的过渡动画

    • --trans-dur 定义了过渡动画的持续时间,使得元素的显示和隐藏更加平滑自然。
    • --trans-timing1--trans-timing2 使用贝塞尔曲线定义了动画的缓动效果,使得动画变化更加符合物理规律和视觉习惯。
  4. 易于维护和扩展

    • 通过使用CSS变量,可以在一个地方修改值,而在整个文档中生效,提高了代码的可维护性。
    • 同时这些变量也可以在其他样式规则中被引用,方便进行样式的扩展和复用。
css 复制代码
:root {
  --hue: 223;
  --bg: hsl(var(--hue),10%,90%);
  --fg: hsl(var(--hue),10%,10%);
  --trans-dur: 0.5s;
  --trans-timing1: cubic-bezier(0.65,0,0.35,1);
  --trans-timing2: cubic-bezier(0.65,0,0.35,1.5);
  font-size: calc(56px + (120 - 56) * (100vw - 280px) / (3840 - 280));
}

Emoji 的绘制主要依赖于 .switch__emoji 相关的 CSS 代码块。这段代码通过使用 CSS 的 transform 属性和一些伪元素来创建一个可动的 Emoji 效果。以下是核心代码部分的解释:

css 复制代码
.switch__emoji {
  $hue: 48;
  $sat: 90%;
  $radius: 0.5em;

  box-shadow: 0.25em 0.25em 0.125em hsl(0,0%,0%,0.3);
  overflow: hidden;
  pointer-events: none;
  top: 0.25em;
  left: 0.25em;
  width: 1em;
  height: 1em;

  /* ...其他样式... */

  &:before,
  &:after,
  &-eye,
  &-mouth,
  &-face {
    display: block;
    position: absolute;
  }

  /* ...其他样式... */
}
  • 伪元素 &:before&:after : 用于绘制 Emoji 的脸的上半部分和下半部分,通过 border-radius 属性设置为圆形,并通过 box-shadow 为 Emoji 添加眼睛和嘴巴。

  • &-eye : 用于绘制 Emoji 的眼睛。通过 border 属性创建一个有边框的圆,并利用 transform 属性调整位置和倾斜角度。

  • &-mouth : 用于绘制 Emoji 的嘴巴。通过 background-image 属性使用渐变和径向渐变来创建嘴巴的形状。

  • &-face : 用于绘制 Emoji 的脸部,通过 transform-style: preserve-3d 属性来保留 3D 空间中的子元素位置。

  • 3D 转换 : 使用 transform 属性的 rotateYtranslateZ 函数来创建翻转效果。

  • 过渡效果 : 使用 transition 属性来平滑地变换 Emoji 的表情。

下面是绘制 Emoji 表情的核心部分,接下来就是3D动画变换:

css 复制代码
.switch__emoji-eye {
  border: 0.0625em solid hsl(var(--hue),10%,10%);
  border-radius: 50%;
  top: 50%;
  left: 50%;
  width: 0.25em;
  height: 0.25em;
  transform: translate(-50%,-50%) rotateY(-22.5deg) translateZ($radius) rotateZ(45deg);
}

.switch__emoji-mouth {
  background-image: ...;
  top: 50%;
  left: 50%;
  width: 0.5em;
  height: 0.5em;
  transform: translate(-50%,-50%) rotateX(-15deg) translateZ($radius);
}
3. 3D变换和过渡

为了实现Emoji的翻转效果,我们使用CSS的3D变换和过渡属性。点击切换动画的主要部分涉及到 .switch__input 这个 checkbox 输入元素以及与之相关的 .switch__emoji 元素。当 checkbox 被选中时,会触发 .switch__emoji 的状态变化,从而执行动画。

这里对于从右到左(如阿拉伯语或希伯来语)的语言,还实现了相反方向的滑动。👍

以下是实现点击切换动画的核心代码:

css 复制代码
.switch__input:checked + .switch__emoji {
  transform: translateX(100%);
}

[dir="rtl"] .switch__input:checked + .switch__emoji {
  transform: translateX(-100%);
}

.switch__input:checked + .switch__emoji .switch__emoji-face {
  transform: rotateY(179.99deg);
}

[dir="rtl"] .switch__input:checked + .switch__emoji .switch__emoji-face {
  transform: rotateY(-179.99deg);
}

.switch__input:checked + .switch__emoji .switch__emoji-face + .switch__emoji-face {
  transform: rotateY(0);
}

[dir="rtl"] .switch__input:checked + .switch__emoji .switch__emoji-face + .switch__emoji-face {
  transform: rotateY(-360deg);
}

代码解析

  1. .switch__input:checked + .switch__emoji

    • .switch__input 被选中(即被勾选)时,与其相邻的 .switch__emoji 元素会执行 transform: translateX(100%); 动画,即沿着 X 轴移动自身宽度的 100%,从而实现滑块开关的效果。
  2. [dir="rtl"] .switch__input:checked + .switch__emoji

    • 对于从右到左(如阿拉伯语或希伯来语)的语言,使用 translateX(-100%); 来实现相反方向的滑动。
  3. .switch__input:checked + .switch__emoji .switch__emoji-face

    • .switch__input 被选中时,.switch__emoji-face 元素会执行 rotateY(179.99deg); 动画,即围绕 Y 轴旋转 179.99 度,接近 180 度的旋转使得 Emoji 翻转。
  4. [dir="rtl"] .switch__input:checked + .switch__emoji .switch__emoji-face

    • 对于从右到左的语言,使用 rotateY(-179.99deg); 来实现相反方向的翻转。
  5. .switch__input:checked + .switch__emoji .switch__emoji-face + .switch__emoji-face

    • .switch__input 被选中时,第二个 .switch__emoji-face 元素会执行 rotateY(0); 动画,即恢复到原始状态。
  6. [dir="rtl"] .switch__input:checked + .switch__emoji .switch__emoji-face + .switch__emoji-face

    • 对于从右到左的语言,使用 rotateY(-360deg); 来实现相反方向的旋转。

动画效果的实现

核心动画效果是通过 CSS 的 transition 属性来实现的,确保变换是平滑的。

css 复制代码
.switch__emoji-face {
  transform-style: preserve-3d;
  transition: transform var(--trans-dur) var(--trans-timing2);
}
  • transform-style: preserve-3d; 确保子元素在 3D 空间中的位置得以保留。
  • transition: transform var(--trans-dur) var(--trans-timing2); 定义了变换的持续时间和缓动函数,使得动画效果更加平滑自然。

通过这些代码,点击切换按钮时,Emoji 会沿着一个轴翻转,同时滑块也会移动,从而实现了一个有趣的切换动画效果。

响应式设计

为了确保这个按钮在不同设备上以及暗色场景下都能良好显示,源码使用了CSS媒体查询和相对单位。

css 复制代码
@media (prefers-color-scheme: dark) {
  :root {
    --bg: hsl(var(--hue),10%,10%);
    --fg: hsl(var(--hue),10%,90%);
  }
  .switch__input {
    background-color: hsl(var(--hue),10%,20%);
    box-shadow: 0.0625em 0.0625em 0.0625em hsl(var(--hue),10%,25%) inset, -0.0625em -0.0625em 0.0625em hsl(var(--hue),10%,20%) inset, 0 0 0 0.125em hsl(var(--hue),10%,30%) inset, 0.25em 0.25em 0.125em hsla(0,0%,0%,0.3) inset, 0.0625em 0.0625em 0.0625em hsla(0,0%,0%,0.3);
  }
}

在线预览

总结

通过使用CSS变量、3D变换和过渡效果,创建了一个既美观又功能丰富的Emoji Toggle按钮。这个交互效果极大了增强了用户体验。希望这篇文章能激发你探索更多CSS的可能性,感兴趣的可以尝试看看~


看完本文如果觉得有用,记得点个赞支持,收藏起来说不定哪天就用上啦~

专注前端开发,分享前端相关技术干货,公众号:南城大前端(ID: nanchengfe)

相关推荐
前端小小王6 分钟前
React Hooks
前端·javascript·react.js
迷途小码农零零发16 分钟前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
娃哈哈哈哈呀38 分钟前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
旭东怪1 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
ekskef_sef3 小时前
32岁前端干了8年,是继续做前端开发,还是转其它工作
前端
sunshine6413 小时前
【CSS】实现tag选中对钩样式
前端·css·css3
真滴book理喻3 小时前
Vue(四)
前端·javascript·vue.js
蜜獾云3 小时前
npm淘宝镜像
前端·npm·node.js
dz88i83 小时前
修改npm镜像源
前端·npm·node.js
Jiaberrr4 小时前
解锁 GitBook 的奥秘:从入门到精通之旅
前端·gitbook