AI CSS Animations

8-Bit Pixel Button

A chunky pixel art button with notched corners and a shaded edge. On hover a blinking arrow cursor appears beside it and the button hops up one pixel, all on stepped timing like an old console menu.

Also known as: pixel art button, retro game button, 8bit button css.

HTML

<button class="btn-pixel-8bit">Start game</button>

CSS

.btn-pixel-8bit {
  --c: var(--btn-color, #3b82f6);
  --px: 0.25em;
  --ink: color-mix(in srgb, var(--c) 35%, #000);
  position: relative;
  padding: 0.75em 1.25em;
  border: 0;
  border-radius: 0;
  background-color: var(--c);
  color: #fff;
  font: 700 var(--btn-size, 18px)/1 ui-monospace, Menlo, Consolas, monospace;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  cursor: pointer;
  box-shadow:
    inset calc(var(--px) * -1) calc(var(--px) * -1) 0 color-mix(in srgb, var(--c) 70%, #000),
    inset var(--px) var(--px) 0 color-mix(in srgb, var(--c) 60%, #fff),
    0 calc(var(--px) * -1) 0 0 var(--ink),
    0 var(--px) 0 0 var(--ink),
    calc(var(--px) * -1) 0 0 0 var(--ink),
    var(--px) 0 0 0 var(--ink);
  transition: transform 0.16s steps(2), background-color 0.16s steps(2);
}
.btn-pixel-8bit::before {
  content: "";
  position: absolute;
  top: 50%;
  left: -1.7em;
  width: 0.8em;
  height: 1.4em;
  margin-top: -0.7em;
  background: var(--c);
  clip-path: polygon(0 0, 25% 0, 25% 14.29%, 50% 14.29%, 50% 28.57%, 75% 28.57%, 75% 42.86%, 100% 42.86%, 100% 57.14%, 75% 57.14%, 75% 71.43%, 50% 71.43%, 50% 85.71%, 25% 85.71%, 25% 100%, 0 100%);
  opacity: 0;
}
.btn-pixel-8bit:is(:hover, :focus-visible) {
  transform: translateY(calc(var(--px) * -1));
  background-color: color-mix(in srgb, var(--c) 85%, #fff);
}
.btn-pixel-8bit:is(:hover, :focus-visible)::before {
  animation: btn-pixel-8bit-blink 1s steps(1, end) infinite;
}
.btn-pixel-8bit:active {
  transform: translateY(var(--px));
  box-shadow:
    inset var(--px) var(--px) 0 color-mix(in srgb, var(--c) 70%, #000),
    inset 0 0 0 transparent,
    0 calc(var(--px) * -1) 0 0 var(--ink),
    0 var(--px) 0 0 var(--ink),
    calc(var(--px) * -1) 0 0 0 var(--ink),
    var(--px) 0 0 0 var(--ink);
}
@keyframes btn-pixel-8bit-blink {
  0%        { opacity: 1; }
  60%, 100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .btn-pixel-8bit, .btn-pixel-8bit *, .btn-pixel-8bit::before, .btn-pixel-8bit::after, .btn-pixel-8bit *::before, .btn-pixel-8bit *::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