Elastic Toggle
Home
Snippets
Elastic Toggle
HTML
CSS
JS
<div class="control-card"> <div class="label-group"> <span class="title">Haptic Core Physics</span> <span class="sub" id="status-txt">Status // Disabled</span> </div> <div class="switch-box" id="toggle-trigger"> <canvas id="switch-canvas"></canvas> </div> </div>
:root { --bg: #06070a; --surface: #0d0e15; --border: rgba(255, 255, 255, 0.04); --accent: #a855f7; } body { margin: 0; background-color: var(--bg); color: #f8fafc; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; height: 100vh; display: flex; justify-content: center; align-items: center; user-select: none; -webkit-user-select: none; padding: 20px; box-sizing: border-box; } .control-card { width: 100%; max-width: 320px; background: var(--surface); border: 1px solid var(--border); border-radius: 24px; padding: 24px; box-sizing: border-box; display: flex; justify-content: space-between; align-items: center; box-shadow: 0 30px 60px rgba(0, 0, 0, 0.5); } .label-group { display: flex; flex-direction: column; gap: 4px; } .title { font-size: 15px; font-weight: 600; letter-spacing: -0.2px; } .sub { font-size: 12px; color: #4b526d; font-weight: 500; } .switch-box { position: relative; width: 70px; height: 38px; cursor: pointer; border-radius: 100px; } canvas { display: block; width: 100%; height: 100%; }
const trigger = document.getElementById('toggle-trigger'); const canvas = document.getElementById('switch-canvas'); const ctx = canvas.getContext('2d'); const statusTxt = document.getElementById('status-txt'); let isOn = false; let knobX = 19; let targetX = 19; let knobWidth = 30; let targetWidth = 30; let vx = 0; let wvx = 0; function initBounds() { canvas.width = trigger.clientWidth; canvas.height = trigger.clientHeight; } function updatePhysics() { ctx.clearRect(0, 0, canvas.width, canvas.height); const h = canvas.height; const w = canvas.width; ctx.fillStyle = isOn ? 'rgba(168, 85, 247, 0.15)' : '#141622'; ctx.strokeStyle = isOn ? 'rgba(168, 85, 247, 0.4)' : 'rgba(255,255,255,0.02)'; ctx.lineWidth = 1; ctx.beginPath(); ctx.roundRect(0, 0, w, h, 100); ctx.fill(); ctx.stroke(); let ax = (targetX - knobX) * 0.22; vx += ax; vx *= 0.72; knobX += vx; targetWidth = 30 + Math.abs(vx) * 0.8; let aw = (targetWidth - knobWidth) * 0.25; wvx += aw; wvx *= 0.7; knobWidth += wvx; ctx.fillStyle = isOn ? '#a855f7' : '#393e59'; ctx.beginPath(); ctx.roundRect(knobX - knobWidth / 2, h / 2 - 15, knobWidth, 30, 100); ctx.fill(); requestAnimationFrame(updatePhysics); } function toggle() { isOn = !isOn; targetX = isOn ? (canvas.width - 19) : 19; statusTxt.textContent = isOn ? "Status // Active" : "Status // Disabled"; statusTxt.style.color = isOn ? "#a855f7" : "#4b526d"; } trigger.addEventListener('click', toggle); window.addEventListener('resize', initBounds); initBounds(); updatePhysics();
Ad #1
Ad #2
Scroll to Top