{ CF }

20 Pure CSS Toggles & Switches

Haptic Keys

Chunky square key with a 3D press-depth shadow and a glowing accent ring on activate. Pressing literally sinks the button 3px while the hard bottom shadow collapses — pure tactile button metaphor for tactile UI trends.

Pure CSS MIT licensed

Haptic Keys the 1st of 20 designs in the 20 Pure CSS Toggles & Switches collection. The design is implemented in pure CSS — no JavaScript required. Copy the HTML and CSS panels below into your project. Because the demo is pure CSS, it works in any framework or templating engine you happen to use. The design honours prefers-reduced-motion and uses real semantic markup, so it ships accessibility-ready out of the box.

Live preview

Open in playground

The code

<label class="tg-hap">
  <input class="tg-hap-input" type="checkbox" checked>
  <span class="tg-hap-btn" aria-hidden="true">
    <span class="tg-hap-ring"></span>
    <svg class="tg-hap-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
      <path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/>
      <path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/>
    </svg>
  </span>
  <span class="tg-hap-label">Notify</span>
</label>
.tg-hap {
  --tg-hap-rim: #14141e;
  --tg-hap-wire: #1e1e2e;
  --tg-hap-edge: #020205;
  --tg-hap-accent: #39d353;
  display: inline-flex;
  align-items: center;
  gap: 18px;
  cursor: pointer;
  font-family: "Inter", "Segoe UI", system-ui, sans-serif;
  font-size: 14px;
  color: #1a1a2e;
  user-select: none;
}
.tg-hap-input {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0);
  white-space: nowrap; border: 0;
}
.tg-hap-btn {
  position: relative;
  display: inline-flex;
  width: 56px;
  height: 56px;
  border-radius: 16px;
  background: var(--tg-hap-rim);
  border: 1px solid var(--tg-hap-wire);
  align-items: center;
  justify-content: center;
  box-shadow:
    0 6px 0 var(--tg-hap-edge),
    0 8px 16px rgba(0,0,0,0.5);
  transition:
    box-shadow 0.1s ease,
    transform 0.1s ease,
    background 0.3s ease,
    border-color 0.3s ease;
}
.tg-hap-icon {
  width: 22px;
  height: 22px;
  color: #3a3a52;
  filter: grayscale(1) brightness(0.6);
  position: relative;
  z-index: 1;
  transition: color 0.3s ease, transform 0.3s ease, filter 0.3s ease;
}
.tg-hap-ring {
  position: absolute;
  inset: -4px;
  border-radius: 20px;
  border: 2px solid transparent;
  transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
/* Press effect — clicking the label sinks the button.
   Using the label's :active so the whole hit-area drives the press. */
.tg-hap:active .tg-hap-btn {
  box-shadow:
    0 2px 0 var(--tg-hap-edge),
    0 3px 8px rgba(0,0,0,0.5);
  transform: translateY(3px);
}
.tg-hap-input:checked ~ .tg-hap-btn {
  background: #0f1a0f;
  border-color: rgba(57,211,83,0.3);
  box-shadow:
    0 6px 0 var(--tg-hap-edge),
    0 8px 16px rgba(0,0,0,0.5),
    0 0 20px rgba(57,211,83,0.15);
}
.tg-hap-input:checked ~ .tg-hap-btn .tg-hap-icon {
  color: var(--tg-hap-accent);
  filter: none;
  transform: scale(1.15);
}
.tg-hap-input:checked ~ .tg-hap-btn .tg-hap-ring {
  border-color: var(--tg-hap-accent);
  box-shadow: 0 0 12px rgba(57,211,83,0.3);
}
.tg-hap-input:focus-visible ~ .tg-hap-btn {
  outline: 2px solid var(--tg-hap-accent);
  outline-offset: 6px;
}
@media (prefers-reduced-motion: reduce) {
  .tg-hap-btn,
  .tg-hap-icon,
  .tg-hap-ring { transition: none; }
}

Search CodeFronts

Loading…