CSS
.btn-latch {
position: relative;
padding: 14px 32px 14px 50px;
border: 2px solid #1a1a1a;
border-radius: 6px;
background:
radial-gradient(circle 80px at var(--mx, 50%) var(--my, 50%),
rgba(255,255,255,0.18), transparent 70%),
linear-gradient(180deg, #0e7a5c 0%, #0d6048 60%, #084030 100%);
color: #e0f0ec;
font-family: ui-monospace, monospace;
font-size: 13px; font-weight: 800;
letter-spacing: 0.22em;
cursor: pointer;
box-shadow: 0 4px 14px rgba(8,64,48,0.4), inset 0 1px 0 rgba(255,255,255,0.15);
--mx: 50%; --my: 50%;
}
.btn-latch-bolt {
position: absolute;
left: 12px; top: 50%;
width: 18px; height: 18px;
margin-top: -9px;
background: radial-gradient(circle at 35% 30%, #f5f5f5, #8a8a85 60%, #3a3a32 100%);
border-radius: 50%;
box-shadow: inset 0 0 0 1px #1a1a1a, 0 1px 2px rgba(0,0,0,0.4);
}
.btn-latch-bolt::before, .btn-latch-bolt::after {
content: '';
position: absolute; top: 50%; left: 50%;
width: 12px; height: 2px;
background: #1a1a1a;
transform: translate(-50%, -50%);
}
.btn-latch-bolt::after { transform: translate(-50%, -50%) rotate(90deg); } JS
document.querySelectorAll('.btn-latch').forEach(function(btn) {
btn.addEventListener('mousemove', function(e) {
var rect = btn.getBoundingClientRect();
btn.style.setProperty('--mx', (e.clientX - rect.left) + 'px');
btn.style.setProperty('--my', (e.clientY - rect.top) + 'px');
});
btn.addEventListener('mouseleave', function() {
btn.style.setProperty('--mx', '50%');
btn.style.setProperty('--my', '50%');
});
});