Back to CSS Toggles & Switches Permission Stack Pure CSS
Share
HTML
<div class="tg-perm">
  <label class="tg-perm-item">
    <input class="tg-perm-input" type="checkbox" checked>
    <svg class="tg-perm-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
      <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/>
      <circle cx="12" cy="10" r="3"/>
    </svg>
    <span class="tg-perm-info">
      <span class="tg-perm-name">Location</span>
      <span class="tg-perm-desc">While using the app</span>
    </span>
    <span class="tg-perm-pill" aria-hidden="true">
      <span class="tg-perm-thumb"></span>
    </span>
  </label>
  <label class="tg-perm-item">
    <input class="tg-perm-input" type="checkbox">
    <svg class="tg-perm-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
      <path d="M23 7l-7 5 7 5V7z"/>
      <rect x="1" y="5" width="15" height="14" rx="2"/>
    </svg>
    <span class="tg-perm-info">
      <span class="tg-perm-name">Camera</span>
      <span class="tg-perm-desc">Photos and video</span>
    </span>
    <span class="tg-perm-pill" aria-hidden="true">
      <span class="tg-perm-thumb"></span>
    </span>
  </label>
  <label class="tg-perm-item">
    <input class="tg-perm-input" type="checkbox" checked>
    <svg class="tg-perm-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
      <rect x="9" y="2" width="6" height="12" rx="3"/>
      <path d="M19 10a7 7 0 0 1-14 0"/>
      <path d="M12 18v3"/>
    </svg>
    <span class="tg-perm-info">
      <span class="tg-perm-name">Microphone</span>
      <span class="tg-perm-desc">Voice input</span>
    </span>
    <span class="tg-perm-pill" aria-hidden="true">
      <span class="tg-perm-thumb"></span>
    </span>
  </label>
  <label class="tg-perm-item">
    <input class="tg-perm-input" type="checkbox">
    <svg class="tg-perm-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
      <path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/>
      <circle cx="9" cy="7" r="4"/>
      <path d="M22 21v-2a4 4 0 0 0-3-3.87"/>
      <path d="M16 3.13a4 4 0 0 1 0 7.75"/>
    </svg>
    <span class="tg-perm-info">
      <span class="tg-perm-name">Contacts</span>
      <span class="tg-perm-desc">Read access only</span>
    </span>
    <span class="tg-perm-pill" aria-hidden="true">
      <span class="tg-perm-thumb"></span>
    </span>
  </label>
</div>
CSS
.tg-perm {
  --tg-perm-bg: #08080f;
  --tg-perm-rim: #14141e;
  --tg-perm-wire: #1e1e2e;
  --tg-perm-fog: #3a3a52;
  --tg-perm-ash: #7a7a98;
  --tg-perm-snow: #f0f0fa;
  --tg-perm-volt: #e0ff00;
  --tg-perm-void: #04040a;
  display: flex;
  flex-direction: column;
  gap: 0;
  width: 280px;
  font-family: "Inter", "Segoe UI", system-ui, sans-serif;
}
.tg-perm-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border: 1px solid var(--tg-perm-wire);
  margin-top: -1px;
  background: var(--tg-perm-bg);
  cursor: pointer;
  transition: background 0.2s ease;
}
.tg-perm-item:first-child { border-radius: 12px 12px 0 0; }
.tg-perm-item:last-child  { border-radius: 0 0 12px 12px; }
.tg-perm-item:hover { background: var(--tg-perm-rim); }
.tg-perm-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-perm-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  color: var(--tg-perm-ash);
  opacity: 0.4;
  transition: opacity 0.3s ease, color 0.3s ease;
}
.tg-perm-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.tg-perm-name {
  font-size: 13px;
  letter-spacing: 0.02em;
  color: var(--tg-perm-snow);
  opacity: 0.5;
  transition: opacity 0.3s ease;
}
.tg-perm-desc {
  font-size: 11px;
  color: var(--tg-perm-ash);
}
/* Mini pill toggle on the right of each row. */
.tg-perm-pill {
  position: relative;
  width: 38px;
  height: 20px;
  flex-shrink: 0;
  border-radius: 10px;
  background: var(--tg-perm-wire);
  border: 1px solid var(--tg-perm-fog);
  transition: background 0.3s ease, border-color 0.3s ease;
}
.tg-perm-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--tg-perm-fog);
  transition: transform 0.3s cubic-bezier(0.34,1.56,0.64,1), background 0.3s ease;
}
.tg-perm-input:checked ~ .tg-perm-icon { opacity: 1; color: var(--tg-perm-volt); }
.tg-perm-input:checked ~ .tg-perm-info .tg-perm-name { opacity: 1; }
.tg-perm-input:checked ~ .tg-perm-pill {
  background: var(--tg-perm-volt);
  border-color: var(--tg-perm-volt);
}
.tg-perm-input:checked ~ .tg-perm-pill .tg-perm-thumb {
  transform: translateX(18px);
  background: var(--tg-perm-void);
}
.tg-perm-input:focus-visible ~ .tg-perm-pill {
  outline: 2px solid var(--tg-perm-volt);
  outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
  .tg-perm-item,
  .tg-perm-icon,
  .tg-perm-name,
  .tg-perm-pill,
  .tg-perm-thumb { transition: none; }
}