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.
<button class="btn-pixel-8bit">Start game</button>
.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;
}
}--btn-color on the element or a parent.
Currently previewing #3b82f6.--btn-size. Every other dimension is in
em, so the whole thing scales together. Currently previewing 18px.transition or animation
shorthand. Staggered delays are relative, so they keep their rhythm.