22 CSS Button Group Designs 20 / 22
Synthwave Dial
Quantity stepper as a synthwave-grid dial — chrome +/− buttons with a scanline window that morphs to magenta when the count hits max, cyan when it hits min.
The code
<div class="cbgp-syn" role="group" aria-label="Quantity"> <button type="button" data-cbgp-syn-step="-1" aria-label="Decrease quantity">−</button> <input type="number" min="1" max="10" value="1" aria-label="Quantity" data-cbgp-syn /> <button type="button" data-cbgp-syn-step="1" aria-label="Increase quantity">+</button> </div>
<div class="cbgp-syn" role="group" aria-label="Quantity">
<button type="button" data-cbgp-syn-step="-1" aria-label="Decrease quantity">−</button>
<input type="number" min="1" max="10" value="1" aria-label="Quantity" data-cbgp-syn />
<button type="button" data-cbgp-syn-step="1" aria-label="Increase quantity">+</button>
</div>.cbgp-syn {
display: inline-flex; align-items: stretch;
background: linear-gradient(180deg, #0a0a14 0%, #050810 100%);
border: 1px solid #ff5af1;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 0 14px rgba(255,90,241,0.25);
}
.cbgp-syn button {
width: 42px; height: 42px;
border: 0; cursor: pointer;
background:
linear-gradient(180deg, rgba(255,255,255,0.08), transparent),
rgba(8,10,18,0.92);
color: #ff5af1;
font: 800 18px/1 ui-monospace, monospace;
text-shadow: 0 0 6px rgba(255,90,241,0.6);
transition: background 0.18s, color 0.18s;
}
.cbgp-syn button:hover {
background: rgba(255,90,241,0.12);
color: #ffaaf0;
}
.cbgp-syn button:focus-visible { outline: 2px solid #00ffe0; outline-offset: -2px; }
.cbgp-syn button:disabled { opacity: 0.3; cursor: not-allowed; }
.cbgp-syn button:disabled:hover { background: rgba(8,10,18,0.92); color: #ff5af1; }
.cbgp-syn input {
width: 64px;
border: 0; outline: none;
background:
repeating-linear-gradient(0deg,
transparent 0 4px,
rgba(0,255,224,0.06) 4px 5px),
#0a0a14;
color: #00ffe0;
font: 800 16px/1 ui-monospace, monospace;
text-align: center;
text-shadow: 0 0 6px rgba(0,255,224,0.5);
border-left: 1px solid rgba(255,90,241,0.3);
border-right: 1px solid rgba(255,90,241,0.3);
-moz-appearance: textfield;
}
.cbgp-syn input::-webkit-outer-spin-button,
.cbgp-syn input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.cbgp-syn.is-min input { color: #00ffe0; box-shadow: inset 0 0 16px rgba(0,255,224,0.3); }
.cbgp-syn.is-max input { color: #ff5af1; box-shadow: inset 0 0 16px rgba(255,90,241,0.4); } .cbgp-syn {
display: inline-flex; align-items: stretch;
background: linear-gradient(180deg, #0a0a14 0%, #050810 100%);
border: 1px solid #ff5af1;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 0 14px rgba(255,90,241,0.25);
}
.cbgp-syn button {
width: 42px; height: 42px;
border: 0; cursor: pointer;
background:
linear-gradient(180deg, rgba(255,255,255,0.08), transparent),
rgba(8,10,18,0.92);
color: #ff5af1;
font: 800 18px/1 ui-monospace, monospace;
text-shadow: 0 0 6px rgba(255,90,241,0.6);
transition: background 0.18s, color 0.18s;
}
.cbgp-syn button:hover {
background: rgba(255,90,241,0.12);
color: #ffaaf0;
}
.cbgp-syn button:focus-visible { outline: 2px solid #00ffe0; outline-offset: -2px; }
.cbgp-syn button:disabled { opacity: 0.3; cursor: not-allowed; }
.cbgp-syn button:disabled:hover { background: rgba(8,10,18,0.92); color: #ff5af1; }
.cbgp-syn input {
width: 64px;
border: 0; outline: none;
background:
repeating-linear-gradient(0deg,
transparent 0 4px,
rgba(0,255,224,0.06) 4px 5px),
#0a0a14;
color: #00ffe0;
font: 800 16px/1 ui-monospace, monospace;
text-align: center;
text-shadow: 0 0 6px rgba(0,255,224,0.5);
border-left: 1px solid rgba(255,90,241,0.3);
border-right: 1px solid rgba(255,90,241,0.3);
-moz-appearance: textfield;
}
.cbgp-syn input::-webkit-outer-spin-button,
.cbgp-syn input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.cbgp-syn.is-min input { color: #00ffe0; box-shadow: inset 0 0 16px rgba(0,255,224,0.3); }
.cbgp-syn.is-max input { color: #ff5af1; box-shadow: inset 0 0 16px rgba(255,90,241,0.4); }/* Synthwave-stepper — clamp + classify min/max state for color shift. */
document.querySelectorAll('.cbgp-syn').forEach(function (group) {
var input = group.querySelector('[data-cbgp-syn]');
var minus = group.querySelector('[data-cbgp-syn-step="-1"]');
var plus = group.querySelector('[data-cbgp-syn-step="1"]');
if (!input) return;
function update() {
var min = Number(input.min) || -Infinity;
var max = Number(input.max) || Infinity;
var val = Number(input.value) || 0;
if (minus) minus.disabled = val <= min;
if (plus) plus.disabled = val >= max;
group.classList.toggle('is-min', val <= min);
group.classList.toggle('is-max', val >= max);
}
group.querySelectorAll('[data-cbgp-syn-step]').forEach(function (btn) {
btn.addEventListener('click', function () {
var dir = parseInt(btn.dataset.cbgpSynStep, 10) || 0;
var min = Number(input.min) || -Infinity;
var max = Number(input.max) || Infinity;
var val = (Number(input.value) || 0) + dir;
input.value = String(Math.max(min, Math.min(max, val)));
update();
});
});
input.addEventListener('input', update);
update();
}); /* Synthwave-stepper — clamp + classify min/max state for color shift. */
document.querySelectorAll('.cbgp-syn').forEach(function (group) {
var input = group.querySelector('[data-cbgp-syn]');
var minus = group.querySelector('[data-cbgp-syn-step="-1"]');
var plus = group.querySelector('[data-cbgp-syn-step="1"]');
if (!input) return;
function update() {
var min = Number(input.min) || -Infinity;
var max = Number(input.max) || Infinity;
var val = Number(input.value) || 0;
if (minus) minus.disabled = val <= min;
if (plus) plus.disabled = val >= max;
group.classList.toggle('is-min', val <= min);
group.classList.toggle('is-max', val >= max);
}
group.querySelectorAll('[data-cbgp-syn-step]').forEach(function (btn) {
btn.addEventListener('click', function () {
var dir = parseInt(btn.dataset.cbgpSynStep, 10) || 0;
var min = Number(input.min) || -Infinity;
var max = Number(input.max) || Infinity;
var val = (Number(input.value) || 0) + dir;
input.value = String(Math.max(min, Math.min(max, val)));
update();
});
});
input.addEventListener('input', update);
update();
});