AI CSS Animations

Power Button

A dark device button that boots up on click: a glowing ring draws itself around the rim, the power icon lights in your accent and the glow keeps breathing while it is on. Click again to switch off.

Also known as: power button css, on off button animation, power toggle button.

HTML

<label class="btn-power">
  <input class="btn-power-input" type="checkbox" aria-label="Power">
  <span class="btn-power-face" aria-hidden="true">
    <svg class="btn-power-ring" viewBox="0 0 48 48"><circle cx="24" cy="24" r="22"/><circle cx="24" cy="24" r="22"/></svg>
    <svg class="btn-power-icon" viewBox="0 0 24 24"><path d="M12 3.5v7.5"/><path d="M7.2 6.6a7.4 7.4 0 1 0 9.6 0"/></svg>
  </span>
</label>

CSS

.btn-power {
  --c: var(--btn-color, #3b82f6);
  position: relative;
  display: inline-grid;
  place-items: center;
  font: 600 var(--btn-size, 18px)/1.1 system-ui, sans-serif;
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.btn-power-input {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
  border-radius: 50%;
}
.btn-power-face {
  position: relative;
  display: grid;
  place-items: center;
  width: 3.8em;
  height: 3.8em;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 35%, color-mix(in srgb, var(--c) 14%, #2a3140), color-mix(in srgb, var(--c) 10%, #0d1117));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    0 0 0 1px rgba(148, 163, 184, 0.14),
    0 0.35em 0.8em -0.2em rgba(2, 6, 23, 0.55),
    0 0 0 0 transparent;
  transition: transform 0.25s cubic-bezier(0.3, 1.6, 0.5, 1), box-shadow 0.5s ease;
}
.btn-power-ring {
  position: absolute;
  inset: 0.18em;
  width: calc(100% - 0.36em);
  height: calc(100% - 0.36em);
  fill: none;
  stroke: var(--c);
  stroke-width: 2.5;
  stroke-linecap: round;
  transform: rotate(-90deg);
}
.btn-power-ring circle:first-child { stroke: rgba(148, 163, 184, 0.16); }
.btn-power-ring circle:last-child {
  stroke-dasharray: 139;
  stroke-dashoffset: 139;
  transition: stroke-dashoffset 0.3s ease;
}
.btn-power-icon {
  width: 1.5em;
  height: 1.5em;
  fill: none;
  stroke: #64748b;
  stroke-width: 2.4;
  stroke-linecap: round;
  transition: stroke 0.3s ease;
}
.btn-power:active .btn-power-face { transform: scale(0.93); }
.btn-power-input:focus-visible ~ .btn-power-face {
  outline: 2px solid var(--c);
  outline-offset: 0.2em;
}
.btn-power-input:checked ~ .btn-power-face {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    0 0 0 1px color-mix(in srgb, var(--c) 40%, transparent),
    0 0.35em 0.8em -0.2em rgba(2, 6, 23, 0.55),
    0 0 1.2em 0.1em color-mix(in srgb, var(--c) 45%, transparent);
  animation: btn-power-breathe 2.4s ease-in-out 0.8s infinite;
}
.btn-power-input:checked ~ .btn-power-face .btn-power-ring circle:last-child {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 0.7s cubic-bezier(0.65, 0, 0.35, 1);
}
.btn-power-input:checked ~ .btn-power-face .btn-power-icon {
  stroke: color-mix(in srgb, var(--c) 70%, #fff);
  animation: btn-power-flicker 0.6s steps(1) 0.1s;
}
@keyframes btn-power-breathe {
  0%, 100% {
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.14),
      0 0 0 1px color-mix(in srgb, var(--c) 40%, transparent),
      0 0.35em 0.8em -0.2em rgba(2, 6, 23, 0.55),
      0 0 1.2em 0.1em color-mix(in srgb, var(--c) 45%, transparent);
  }
  50% {
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.14),
      0 0 0 1px color-mix(in srgb, var(--c) 40%, transparent),
      0 0.35em 0.8em -0.2em rgba(2, 6, 23, 0.55),
      0 0 0.6em 0 color-mix(in srgb, var(--c) 25%, transparent);
  }
}
@keyframes btn-power-flicker {
  0%, 30%, 60% { opacity: 1; }
  15%, 45% { opacity: 0.35; }
}

@media (prefers-reduced-motion: reduce) {
  .btn-power, .btn-power *, .btn-power::before, .btn-power::after, .btn-power *::before, .btn-power *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

Customizing this snippet

  • Color: set --btn-color on the element or a parent. Currently previewing #3b82f6.
  • Base size: set --btn-size. Every other dimension is in em, so the whole thing scales together. Currently previewing 18px.
  • Speed: change the duration on the transition or animation shorthand. Staggered delays are relative, so they keep their rhythm.
  • Reduced motion: the rule at the end of the CSS turns the motion off for people who asked their OS for less of it. Keep it.

Similar buttons