效果演示

文末可一键复制完整代码
源代码
<!DOCTYPE html><htmllang="zh-CN"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>LED控制条</title><style> * { border: 0; box-sizing: border-box; margin: 0; padding: 0; } :root { --hue: 223; --sat: 10%; --bg: hsl(var(--hue),var(--sat),30%); --fg: hsl(var(--hue),var(--sat),90%); font-size: 12px; } body, input { font: 1em/1.5 sans-serif; } body { background-color: var(--bg); color: var(--fg); display: flex; height: 100vh; } input { outline: transparent; -webkit-appearance: none; appearance: none; -webkit-tap-highlight-color: transparent; } main { display: flex; overflow-x: hidden; padding: 1.5em 0; width: 100vw; height: 100vh; } .grid { display: grid; gap: 1.5em; grid-template-columns: repeat(2, 1fr); margin: auto; } .led-control { margin: auto; position: relative; width: 10.5em; height: 22em; } .led-control__icon { color: #eee; bottom: 2.5em; left: 2.5em; width: 5.5em; height: 5.5em; } .led-control__icon, .led-control__icon:before { position: absolute; } .led-control__icon:before { border-radius: 50%; content: ""; display: block; filter: drop-shadow(1px 1px var(--bg)) drop-shadow(-1px 0 var(--bg)) drop-shadow(0 -1px var(--bg)); top: 0.0625em; left: 0.0625em; width: 0.375em; height: 0.375em; } .led-control__icon--audio:before { box-shadow: 2.5em 0.5em, 2em 1em, 2.5em 1em, 1.5em 1.5em, 2em 1.5em, 2.5em 1.5em, 4.5em 1.5em, 0.5em 2em, 1em 2em, 1.5em 2em, 2em 2em, 2.5em 2em, 4em 2em, 0.5em 2.5em, 1em 2.5em, 1.5em 2.5em, 2em 2.5em, 2.5em 2.5em, 4.5em 2.5em, 0.5em 3em, 1em 3em, 1.5em 3em, 2em 3em, 2.5em 3em, 4em 3em, 1.5em 3.5em, 2em 3.5em, 2.5em 3.5em, 4.5em 3.5em, 2em 4em, 2.5em 4em, 2.5em 4.5em; } .led-control__icon--sun:before { box-shadow: 2.5em 0em, 0.5em 0.5em, 2.5em 0.5em, 4.5em 0.5em, 1em 1em, 2em 1em, 2.5em 1em, 3em 1em, 4em 1em, 1.5em 1.5em, 3.5em 1.5em, 1em 2em, 4em 2em, 0em 2.5em, 0.5em 2.5em, 1em 2.5em, 4em 2.5em, 4.5em 2.5em, 5em 2.5em, 1em 3em, 4em 3em, 1.5em 3.5em, 3.5em 3.5em, 1em 4em, 2em 4em, 2.5em 4em, 3em 4em, 4em 4em, 0.5em 4.5em, 2.5em 4.5em, 4.5em 4.5em, 2.5em 5em; } .led-control__input, .led-control__label, .led-control__layer, .led-control__layer-wrap { position: absolute; } .led-control__input { background-color: transparent; box-shadow: 0 0 0 0.25em transparent; top: 50%; left: 50%; transform: translate(-50%, -50%) rotate(-90deg); width: 22em; height: 10.5em; } .led-control__input:focus-visible { box-shadow: 0 0 0 0.25em var(--fg); } .led-control__input::-webkit-slider-thumb { background-color: transparent; border: 0; border-radius: 0; box-shadow: none; cursor: pointer; width: 2.5em; height: 10.5em; -webkit-appearance: none; } .led-control__input::-moz-range-thumb { background-color: transparent; border: 0; border-radius: 0; box-shadow: none; cursor: pointer; width: 2.5em; height: 10.5em; } .led-control__label { overflow: hidden; width: 1px; height: 1px; } .led-control__layer { background: url("data:image/svg+xml,<svgviewBox='0 0 8 8'xmlns='http://www.w3.org/2000/svg'><circlefill='%23111'cx='4'cy='4'r='3' /></svg>") 0 0/0.5em 0.5em; } .led-control__layer, .led-control__layer-wrap { inset: 0; } .led-control__layer-wrap { clip-path: polygon(1em 0em, 9.5em 0em, 9.5em 0.5em, 10em 0.5em, 10em 1em, 10.5em 1em, 10.5em 21em, 10em 21em, 10em 21em, 10em 21.5em, 9.5em 21.5em, 9.5em 22em, 1em 22em, 1em 21.5em, 0.5em 21.5em, 0.5em 21em, 0em 21em, 0em 1em, 0.5em 1em, 0.5em 0.5em, 1em 0.5em); } .led-control__layer--inverted { background-image: url("data:image/svg+xml,<svgviewBox='0 0 8 8'xmlns='http://www.w3.org/2000/svg'><circlefill='%23eee'cx='4'cy='4'r='3' /></svg>"); } .led-control__layer--inverted .led-control__icon { color: #111; }</style></head><body><divid="root"></div><scripttype="module">import e,{StrictMode as v,useState as E}from"https://esm.sh/react";import{createRoot as p}from"https://esm.sh/react-dom/client";p(document.getElementById("root")).render(e.createElement(v,null,e.createElement("main",null,e.createElement("div",{className:"grid"},e.createElement(r,{icon:"sun",label:"Brightness",id:"brightness",name:"brightness",value:30}),e.createElement(r,{icon:"audio",label:"Volume",id:"volume",name:"volume",value:20})))));functionr({icon:t,label:c,id:m,name:a,value:i=0}){let[n,s]=E(i),o=44,l=(1-n/o)*100,d={clipPath:`polygon(0 0,100% 0,100% ${l}%,0 ${l}%)`},_={clipPath:`polygon(0 ${l}%,100% ${l}%,100% 100%,0 100%)`};return e.createElement("div",{className:"led-control"},e.createElement("div",{className:"led-control__layer-wrap"},e.createElement("div",{className:"led-control__layer",style:d},e.createElement("div",{className:`led-control__icon led-control__icon--${t}`})),e.createElement("div",{className:"led-control__layer led-control__layer--inverted",style:_},e.createElement("div",{className:`led-control__icon led-control__icon--${t}`}))),e.createElement("label",{className:"led-control__label",htmlFor:a},c),e.createElement("input",{className:"led-control__input",type:"range",id:m,name:a,value:n,step:1,min:0,max:o,onChange:u=>s(+u.target.value)}))}</script></body></html>实现思路拆分
LED控制条是怎么做出来的?
这一篇做一个LED控制条:打开页面即可体验核心动效。整页靠 HTML、CSS 与 JavaScript 完成。
整体思路:三块内容分工
可以把成品页面想成三块积木拼在一起:
结构: .stage内 DOM 组件或控件。样式:背景、居中、过渡与关键帧动画。 脚本:事件监听与 classList/ 定时器驱动交互逻辑。
结构和样式分开写,改灯色或主题色只动 CSS 变量,不动 HTML。
配色与场景氛围
这一版用颜色与背景营造场景,而不只是装饰:
hue( --hue):223。sat( --sat):10%。bg( --bg):hsl(var(--hue),var(--sat),30%)。fg( --fg):hsl(var(--hue),var(--sat),90%)。
让画面「活」起来
页面采用全视口布局,突出单一效果本身。
动效方面,这一版启用了这些效果:
以静态展示为主;可按需增加 @keyframes或脚本驱动动画。
源码获取

夜雨聆风