乐于分享
好东西不私藏

极简开关(可复制源代码)

极简开关(可复制源代码)

效果演示

文末可一键复制完整代码

源代码

<!DOCTYPE html><htmllang="zh-CN"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>极简开关</title><style>            :root { --sz: 10vmin; --c1: #ffffff; --c2: #848484; --c3: #474747; --c4: #323232; } @property --c2 { syntax: '<color>'; inherits: false; initial-value: #848484; } *, *:before { box-sizing: border-box; transition: all 0.5s ease 0s; } body { margin: 0; padding: 0; width: 100vw; height: 100vh; overflow: hidden; display: flex; align-items: center; justify-content: center; background: var(--c4); } .toggle { position: relative; width: calc(var(--sz) * 4); height: calc(var(--sz) * 2); display: flex; align-items: center; justify-content: center; } input { opacity: 0; visibility: hidden; } label[for=btn] { position: absolute; width: calc(var(--sz) * 4); height: calc(var(--sz) * 2); display: flex; align-items: center; justify-content: center; pointer-events: none; } label[for=btn]:before { content: ""; position: absolute; width: calc(var(--sz) * 3); height: calc(var(--sz) * 0.25); background: var(--c3); border-radius: var(--sz); } .thumb { position: absolute; width: calc(calc(var(--sz) * 2) - calc(var(--sz) / 8)); height: calc(calc(var(--sz) * 2) - calc(var(--sz) / 8)); top: calc(calc( var(--sz) / 10) + calc(var(--sz) / -20)); left: calc(calc( var(--sz) / 10) + calc(var(--sz) / -30)); border-radius: var(--sz); background: var(--c2); cursor: pointer; border: calc(var(--sz) / 4) solid var(--c4); display: flex; align-items: center; justify-content: center; overflow: hidden; pointer-events: all; animation: start-thumb 1.5s ease 0s 1; } .thumb:before { content: ""; position: absolute; width: 65%; height: 65%; background: var(--c4); border-radius: var(--sz); animation: start-thumb-before 1.5s ease 0s 1; } #btn:checked + label .thumb { left: calc(calc(100% - calc(calc(var(--sz) * 2) - calc(var(--sz) / 3))) - calc(calc( var(--sz) / 10) + calc(var(--sz) / 5.75))); --c2: var(--c1); } #btn:checked + label .thumb:before { width: 0%; height: 0%; } @keyframes start-thumb { 0%, 50% { left: calc(calc(100% - calc(calc(var(--sz) * 2) - calc(var(--sz) / 3))) - calc(calc( var(--sz) / 10) + calc(var(--sz) / 5.75))); --c2: var(--c1); } 100% { left: calc(calc( var(--sz) / 10) + calc(var(--sz) / -30)); } } @keyframes start-thumb-before { 0%, 50% { width: 0%; height: 0%; } 100% { width: 65%; height: 65%; } }</style></head><body><divclass="toggle"><inputtype="checkbox"id="btn"><labelfor="btn"><spanclass="thumb"></span></label></div></body></html>

实现思路拆分

极简开关是怎么做出来的?

这一篇做一个极简开关:打开页面即可体验核心动效。整页靠 HTML 与 CSS 完成,不用 JavaScript。

整体思路:三块内容分工

可以把成品页面想成三块积木拼在一起:

  1. 结构:可点击 label + 隐藏复选框 + 视觉滑块/字母/图标。
  2. 布局:Grid 或 Flex 排布轨道与状态符号,尺寸多用 em/clamp 缩放。
  3. 动效:相邻兄弟或 :checked 选择器联动 transformopacity,无需 JavaScript。

结构和样式分开写,改灯色或主题色只动 CSS 变量,不动 HTML。

配色与场景氛围

这一版用颜色与背景营造场景,而不只是装饰:

  • sz--sz):10vmin。
  • c1--c1):#ffffff
  • c2--c2):#848484
  • c3--c3):#474747
  • c4--c4):#323232
  • 页面背景:var(--c4)。

让画面「活」起来

Flex 水平垂直居中排布内容。

动效方面,这一版启用了这些效果:

  • start-thumb 动画循环
  • start-thumb-before 动画循环
  • :checked 区分两种主状态,无需脚本改 class
  • transition 让状态切换更顺滑

结构拆解:从上到下的图层

可访问的开关骨架
  1. 隐藏 checkbox + 外层 label,点击整块区域切换
主要结构与图层
  1. .toggle 结构节点
  2. 隐藏 checkbox,驱动 :checked / :has() 状态

源码获取