25 CSS Button Groups17 / 25
CSS Pixel Matrix Button Group with LED Segment Glow (Retro Display Buttons)
A button group that looks like a retro LED dot-matrix panel — each button is a grid of tiny pixels that light up amber/green when active, complete with segment glow and a dark board bezel. The nostalgic-yet-modern 'CSS pixel matrix LED button group' for playful dashboards, retro UIs and hardware-style controls.
Published Updated
The code
<section class="btn-17" aria-label="Pixel matrix LED button group demo">
<div class="btn-17__board">
<p class="btn-17__label">Transport</p>
<div class="btn-17__keys" role="radiogroup" aria-label="Transport mode">
<input type="radio" name="btn-17" id="btn-17-1" class="btn-17__in" checked>
<label for="btn-17-1" class="btn-17__key btn-17__key--go" aria-label="Run"><span>RUN</span></label>
<input type="radio" name="btn-17" id="btn-17-2" class="btn-17__in">
<label for="btn-17-2" class="btn-17__key btn-17__key--wait" aria-label="Pause"><span>WAIT</span></label>
<input type="radio" name="btn-17" id="btn-17-3" class="btn-17__in">
<label for="btn-17-3" class="btn-17__key btn-17__key--stop" aria-label="Stop"><span>STOP</span></label>
</div>
</div>
</section><section class="btn-17" aria-label="Pixel matrix LED button group demo">
<div class="btn-17__board">
<p class="btn-17__label">Transport</p>
<div class="btn-17__keys" role="radiogroup" aria-label="Transport mode">
<input type="radio" name="btn-17" id="btn-17-1" class="btn-17__in" checked>
<label for="btn-17-1" class="btn-17__key btn-17__key--go" aria-label="Run"><span>RUN</span></label>
<input type="radio" name="btn-17" id="btn-17-2" class="btn-17__in">
<label for="btn-17-2" class="btn-17__key btn-17__key--wait" aria-label="Pause"><span>WAIT</span></label>
<input type="radio" name="btn-17" id="btn-17-3" class="btn-17__in">
<label for="btn-17-3" class="btn-17__key btn-17__key--stop" aria-label="Stop"><span>STOP</span></label>
</div>
</div>
</section>.btn-17,
.btn-17 *,
.btn-17 *::before,
.btn-17 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.btn-17 {
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: radial-gradient(120% 120% at 50% 0%,#161616,#050505);
padding: 44px 20px;
}
.btn-17__board {
width: min(520px,100%);
background: linear-gradient(180deg,#1c1c1c,#0e0e0e);
border: 1px solid #2c2c2c;
border-radius: 20px;
padding: 24px;
box-shadow: inset 0 2px 10px rgba(0,0,0,.8),0 30px 70px -40px #000;
}
.btn-17__label {
font-family: ui-monospace,Menlo,monospace;
font-size: 11px;
font-weight: 700;
letter-spacing: .24em;
color: #5a5a5a;
margin: 0 0 14px 2px;
}
.btn-17__keys {
display: grid;
grid-template-columns: repeat(3,1fr);
gap: 12px;
}
.btn-17__in {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
}
.btn-17__key {
--led: rgba(120,120,120,.22);
position: relative;
display: flex;
align-items: center;
justify-content: center;
min-height: 80px;
border-radius: 12px;
background: #0a0a0a;
border: 1.5px solid #262626;
cursor: pointer;
overflow: hidden;
box-shadow: inset 0 2px 6px rgba(0,0,0,.7);
}
.btn-17__key::before {
content: "";
position: absolute;
inset: 0;
background: radial-gradient(circle,var(--led) 30%,transparent 34%) 0 0/7px 7px;
transition: background .25s,filter .25s;
}
.btn-17__key span {
position: relative;
z-index: 1;
font-family: ui-monospace,Menlo,monospace;
font-size: 16px;
font-weight: 800;
letter-spacing: .12em;
color: var(--led);
text-shadow: none;
transition: color .25s,text-shadow .25s;
}
.btn-17__key--go.btn-17__key {
}
.btn-17__in:checked + .btn-17__key--go {
--led: #3dff6e;
border-color: #1c7a3a;
}
.btn-17__in:checked + .btn-17__key--wait {
--led: #ffb000;
border-color: #8a6000;
}
.btn-17__in:checked + .btn-17__key--stop {
--led: #ff4242;
border-color: #8a2020;
}
.btn-17__in:checked + .btn-17__key::before {
filter: drop-shadow(0 0 5px var(--led));
}
.btn-17__in:checked + .btn-17__key span {
color: #fff;
text-shadow: 0 0 8px var(--led),0 0 16px var(--led);
}
.btn-17__in:checked + .btn-17__key {
box-shadow: inset 0 2px 6px rgba(0,0,0,.7),0 0 22px -6px var(--led);
}
.btn-17__key::after {
content: "";
position: absolute;
inset: 0;
background: repeating-linear-gradient(0deg,rgba(255,255,255,.04) 0 1px,transparent 1px 3px);
pointer-events: none;
}
.btn-17__in:focus-visible + .btn-17__key {
outline: 3px solid #fff;
outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
.btn-17__key::before,
.btn-17__key span {
transition: none;
}
}.btn-17,
.btn-17 *,
.btn-17 *::before,
.btn-17 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.btn-17 {
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: radial-gradient(120% 120% at 50% 0%,#161616,#050505);
padding: 44px 20px;
}
.btn-17__board {
width: min(520px,100%);
background: linear-gradient(180deg,#1c1c1c,#0e0e0e);
border: 1px solid #2c2c2c;
border-radius: 20px;
padding: 24px;
box-shadow: inset 0 2px 10px rgba(0,0,0,.8),0 30px 70px -40px #000;
}
.btn-17__label {
font-family: ui-monospace,Menlo,monospace;
font-size: 11px;
font-weight: 700;
letter-spacing: .24em;
color: #5a5a5a;
margin: 0 0 14px 2px;
}
.btn-17__keys {
display: grid;
grid-template-columns: repeat(3,1fr);
gap: 12px;
}
.btn-17__in {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
}
.btn-17__key {
--led: rgba(120,120,120,.22);
position: relative;
display: flex;
align-items: center;
justify-content: center;
min-height: 80px;
border-radius: 12px;
background: #0a0a0a;
border: 1.5px solid #262626;
cursor: pointer;
overflow: hidden;
box-shadow: inset 0 2px 6px rgba(0,0,0,.7);
}
.btn-17__key::before {
content: "";
position: absolute;
inset: 0;
background: radial-gradient(circle,var(--led) 30%,transparent 34%) 0 0/7px 7px;
transition: background .25s,filter .25s;
}
.btn-17__key span {
position: relative;
z-index: 1;
font-family: ui-monospace,Menlo,monospace;
font-size: 16px;
font-weight: 800;
letter-spacing: .12em;
color: var(--led);
text-shadow: none;
transition: color .25s,text-shadow .25s;
}
.btn-17__key--go.btn-17__key {
}
.btn-17__in:checked + .btn-17__key--go {
--led: #3dff6e;
border-color: #1c7a3a;
}
.btn-17__in:checked + .btn-17__key--wait {
--led: #ffb000;
border-color: #8a6000;
}
.btn-17__in:checked + .btn-17__key--stop {
--led: #ff4242;
border-color: #8a2020;
}
.btn-17__in:checked + .btn-17__key::before {
filter: drop-shadow(0 0 5px var(--led));
}
.btn-17__in:checked + .btn-17__key span {
color: #fff;
text-shadow: 0 0 8px var(--led),0 0 16px var(--led);
}
.btn-17__in:checked + .btn-17__key {
box-shadow: inset 0 2px 6px rgba(0,0,0,.7),0 0 22px -6px var(--led);
}
.btn-17__key::after {
content: "";
position: absolute;
inset: 0;
background: repeating-linear-gradient(0deg,rgba(255,255,255,.04) 0 1px,transparent 1px 3px);
pointer-events: none;
}
.btn-17__in:focus-visible + .btn-17__key {
outline: 3px solid #fff;
outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
.btn-17__key::before,
.btn-17__key span {
transition: none;
}
}Here's a working CSS Button Group from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Pixel Matrix Button Group with LED Segment Glow (Retro Display Buttons)
Source: https://codefronts.com/components/css-button-groups/pixel-matrix/
A button group that looks like a retro LED dot-matrix panel — each button is a grid of tiny pixels that light up amber/green when active, complete with segment glow and a dark board bezel. The nostalgic-yet-modern 'CSS pixel matrix LED button group' for playful dashboards, retro UIs and hardware-style controls.
## HTML
```html
<section class="btn-17" aria-label="Pixel matrix LED button group demo">
<div class="btn-17__board">
<p class="btn-17__label">Transport</p>
<div class="btn-17__keys" role="radiogroup" aria-label="Transport mode">
<input type="radio" name="btn-17" id="btn-17-1" class="btn-17__in" checked>
<label for="btn-17-1" class="btn-17__key btn-17__key--go" aria-label="Run"><span>RUN</span></label>
<input type="radio" name="btn-17" id="btn-17-2" class="btn-17__in">
<label for="btn-17-2" class="btn-17__key btn-17__key--wait" aria-label="Pause"><span>WAIT</span></label>
<input type="radio" name="btn-17" id="btn-17-3" class="btn-17__in">
<label for="btn-17-3" class="btn-17__key btn-17__key--stop" aria-label="Stop"><span>STOP</span></label>
</div>
</div>
</section>
```
## CSS
```css
.btn-17,
.btn-17 *,
.btn-17 *::before,
.btn-17 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.btn-17 {
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: radial-gradient(120% 120% at 50% 0%,#161616,#050505);
padding: 44px 20px;
}
.btn-17__board {
width: min(520px,100%);
background: linear-gradient(180deg,#1c1c1c,#0e0e0e);
border: 1px solid #2c2c2c;
border-radius: 20px;
padding: 24px;
box-shadow: inset 0 2px 10px rgba(0,0,0,.8),0 30px 70px -40px #000;
}
.btn-17__label {
font-family: ui-monospace,Menlo,monospace;
font-size: 11px;
font-weight: 700;
letter-spacing: .24em;
color: #5a5a5a;
margin: 0 0 14px 2px;
}
.btn-17__keys {
display: grid;
grid-template-columns: repeat(3,1fr);
gap: 12px;
}
.btn-17__in {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
}
.btn-17__key {
--led: rgba(120,120,120,.22);
position: relative;
display: flex;
align-items: center;
justify-content: center;
min-height: 80px;
border-radius: 12px;
background: #0a0a0a;
border: 1.5px solid #262626;
cursor: pointer;
overflow: hidden;
box-shadow: inset 0 2px 6px rgba(0,0,0,.7);
}
.btn-17__key::before {
content: "";
position: absolute;
inset: 0;
background: radial-gradient(circle,var(--led) 30%,transparent 34%) 0 0/7px 7px;
transition: background .25s,filter .25s;
}
.btn-17__key span {
position: relative;
z-index: 1;
font-family: ui-monospace,Menlo,monospace;
font-size: 16px;
font-weight: 800;
letter-spacing: .12em;
color: var(--led);
text-shadow: none;
transition: color .25s,text-shadow .25s;
}
.btn-17__key--go.btn-17__key {
}
.btn-17__in:checked + .btn-17__key--go {
--led: #3dff6e;
border-color: #1c7a3a;
}
.btn-17__in:checked + .btn-17__key--wait {
--led: #ffb000;
border-color: #8a6000;
}
.btn-17__in:checked + .btn-17__key--stop {
--led: #ff4242;
border-color: #8a2020;
}
.btn-17__in:checked + .btn-17__key::before {
filter: drop-shadow(0 0 5px var(--led));
}
.btn-17__in:checked + .btn-17__key span {
color: #fff;
text-shadow: 0 0 8px var(--led),0 0 16px var(--led);
}
.btn-17__in:checked + .btn-17__key {
box-shadow: inset 0 2px 6px rgba(0,0,0,.7),0 0 22px -6px var(--led);
}
.btn-17__key::after {
content: "";
position: absolute;
inset: 0;
background: repeating-linear-gradient(0deg,rgba(255,255,255,.04) 0 1px,transparent 1px 3px);
pointer-events: none;
}
.btn-17__in:focus-visible + .btn-17__key {
outline: 3px solid #fff;
outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
.btn-17__key::before,
.btn-17__key span {
transition: none;
}
}
```Here's a working CSS Button Group from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Pixel Matrix Button Group with LED Segment Glow (Retro Display Buttons)
Source: https://codefronts.com/components/css-button-groups/pixel-matrix/
A button group that looks like a retro LED dot-matrix panel — each button is a grid of tiny pixels that light up amber/green when active, complete with segment glow and a dark board bezel. The nostalgic-yet-modern 'CSS pixel matrix LED button group' for playful dashboards, retro UIs and hardware-style controls.
## HTML
```html
<section class="btn-17" aria-label="Pixel matrix LED button group demo">
<div class="btn-17__board">
<p class="btn-17__label">Transport</p>
<div class="btn-17__keys" role="radiogroup" aria-label="Transport mode">
<input type="radio" name="btn-17" id="btn-17-1" class="btn-17__in" checked>
<label for="btn-17-1" class="btn-17__key btn-17__key--go" aria-label="Run"><span>RUN</span></label>
<input type="radio" name="btn-17" id="btn-17-2" class="btn-17__in">
<label for="btn-17-2" class="btn-17__key btn-17__key--wait" aria-label="Pause"><span>WAIT</span></label>
<input type="radio" name="btn-17" id="btn-17-3" class="btn-17__in">
<label for="btn-17-3" class="btn-17__key btn-17__key--stop" aria-label="Stop"><span>STOP</span></label>
</div>
</div>
</section>
```
## CSS
```css
.btn-17,
.btn-17 *,
.btn-17 *::before,
.btn-17 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.btn-17 {
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: radial-gradient(120% 120% at 50% 0%,#161616,#050505);
padding: 44px 20px;
}
.btn-17__board {
width: min(520px,100%);
background: linear-gradient(180deg,#1c1c1c,#0e0e0e);
border: 1px solid #2c2c2c;
border-radius: 20px;
padding: 24px;
box-shadow: inset 0 2px 10px rgba(0,0,0,.8),0 30px 70px -40px #000;
}
.btn-17__label {
font-family: ui-monospace,Menlo,monospace;
font-size: 11px;
font-weight: 700;
letter-spacing: .24em;
color: #5a5a5a;
margin: 0 0 14px 2px;
}
.btn-17__keys {
display: grid;
grid-template-columns: repeat(3,1fr);
gap: 12px;
}
.btn-17__in {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
}
.btn-17__key {
--led: rgba(120,120,120,.22);
position: relative;
display: flex;
align-items: center;
justify-content: center;
min-height: 80px;
border-radius: 12px;
background: #0a0a0a;
border: 1.5px solid #262626;
cursor: pointer;
overflow: hidden;
box-shadow: inset 0 2px 6px rgba(0,0,0,.7);
}
.btn-17__key::before {
content: "";
position: absolute;
inset: 0;
background: radial-gradient(circle,var(--led) 30%,transparent 34%) 0 0/7px 7px;
transition: background .25s,filter .25s;
}
.btn-17__key span {
position: relative;
z-index: 1;
font-family: ui-monospace,Menlo,monospace;
font-size: 16px;
font-weight: 800;
letter-spacing: .12em;
color: var(--led);
text-shadow: none;
transition: color .25s,text-shadow .25s;
}
.btn-17__key--go.btn-17__key {
}
.btn-17__in:checked + .btn-17__key--go {
--led: #3dff6e;
border-color: #1c7a3a;
}
.btn-17__in:checked + .btn-17__key--wait {
--led: #ffb000;
border-color: #8a6000;
}
.btn-17__in:checked + .btn-17__key--stop {
--led: #ff4242;
border-color: #8a2020;
}
.btn-17__in:checked + .btn-17__key::before {
filter: drop-shadow(0 0 5px var(--led));
}
.btn-17__in:checked + .btn-17__key span {
color: #fff;
text-shadow: 0 0 8px var(--led),0 0 16px var(--led);
}
.btn-17__in:checked + .btn-17__key {
box-shadow: inset 0 2px 6px rgba(0,0,0,.7),0 0 22px -6px var(--led);
}
.btn-17__key::after {
content: "";
position: absolute;
inset: 0;
background: repeating-linear-gradient(0deg,rgba(255,255,255,.04) 0 1px,transparent 1px 3px);
pointer-events: none;
}
.btn-17__in:focus-visible + .btn-17__key {
outline: 3px solid #fff;
outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
.btn-17__key::before,
.btn-17__key span {
transition: none;
}
}
```How this works
The board is a dark bezel; each button carries a dotted pixel grid painted with a repeating radial-gradient background — a lattice of tiny unlit LEDs. When a button is :checked, the same lattice switches to a lit color and gains a layered box-shadow plus drop-shadow bloom, so the whole matrix appears to power on.
The unlit dots are a low-alpha color; lit dots are full-chroma with a glow, mimicking real LED falloff. A faint scanline overlay and inset bezel shadow sell the hardware look. Real radios keep it a single-select mode switch (Run / Pause / Stop style), fully keyboard-operable.
background:radial-gradient(circle,var(--led) 32%,transparent 34%) 0 0/7px 7px;
.in:checked + .key{ --led:#ffb000; filter:drop-shadow(0 0 6px #ffb000) }Techniques used: repeating radial-gradient LED lattice · lit/unlit color swap on :checked · box-shadow + drop-shadow segment bloom · scanline overlay + inset bezel · single-select radios · reduced-motion safe (no animation dependency)
Make it yours
- LED color per state via
--led— amber, green, red for different modes. - Pixel density = the radial-gradient tile size (7px here).
- Bezel darkness and inset shadow tune the hardware feel.
- Add a lit "power" dot indicator per key for extra realism.
Gotchas — read before shipping
- Dot-matrix text can be hard to read — pair the pixel look with a clear
aria-labelper key. - Don't rely on glow alone for state; the lit-vs-unlit color contrast must be strong.
- Keep dot tiles small enough to read as pixels but not so small they moiré on low-DPI screens.
- Radios for a single active mode; use checkboxes only if multiple LEDs can be on at once.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| all | all | all | all |
Repeating radial-gradients, box-shadow and drop-shadow are universal. No experimental features required.