{ CF }

20 Pure CSS Toggles & Switches

Skeuomorphic Knob

A brushed-metal rotary knob that physically rotates 90 degrees on toggle. Different motion type from the sliding switches — rotation as the state signal. Tick marks anchor the dial.

Pure CSS MIT licensed

Skeuomorphic Knob the 16th 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-knob">
  <input class="tg-knob-input" type="checkbox" checked>
  <span class="tg-knob-stage" aria-hidden="true">
    <span class="tg-knob-tick tg-knob-t-off">OFF</span>
    <span class="tg-knob-tick tg-knob-t-on">ON</span>
    <span class="tg-knob-dial">
      <span class="tg-knob-indicator"></span>
    </span>
  </span>
  <span class="tg-knob-label">Power</span>
</label>
.tg-knob {
  display: inline-flex;
  align-items: center;
  gap: 16px;
  cursor: pointer;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: #d8d4dc;
  user-select: none;
}
.tg-knob-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-knob-stage {
  position: relative;
  width: 60px;
  height: 60px;
}
.tg-knob-tick {
  position: absolute;
  font-family: ui-monospace, "Fira Code", monospace;
  font-size: 8px;
  letter-spacing: 0.1em;
  color: #6a6a7a;
}
.tg-knob-t-off { top: 4px;  left: 0; }
.tg-knob-t-on  { top: 4px;  right: 0; }
.tg-knob-dial {
  position: absolute;
  top: 12px; left: 6px;
  width: 48px; height: 48px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 30% 30%, #f0e8d8 0%, #6a5a30 90%);
  box-shadow:
    inset 0 1px 1px rgba(255,255,255,0.4),
    inset 0 -2px 4px rgba(0,0,0,0.3),
    0 2px 6px rgba(0,0,0,0.4);
  transform: rotate(-45deg);
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.tg-knob-indicator {
  position: absolute;
  top: 4px; left: 50%;
  width: 3px; height: 14px;
  background: #2a1d0e;
  border-radius: 2px;
  transform: translateX(-50%);
}
.tg-knob-input:checked ~ .tg-knob-stage .tg-knob-dial {
  transform: rotate(45deg);
}
.tg-knob-input:checked ~ .tg-knob-stage .tg-knob-t-on { color: #d8b66e; }
.tg-knob-input:not(:checked) ~ .tg-knob-stage .tg-knob-t-off { color: #d8b66e; }
.tg-knob-input:focus-visible ~ .tg-knob-stage .tg-knob-dial {
  outline: 2px solid #d8b66e;
  outline-offset: 4px;
}
@media (prefers-reduced-motion: reduce) {
  .tg-knob-dial { transition: none; }
}

Search CodeFronts

Loading…