HTML Copy
<button class="pp-tape" type="button" aria-pressed="false" aria-label="Play" data-pp>
<span class="pp-tape-body" aria-hidden="true">
<span class="pp-tape-reel pp-tape-reel-l">
<span class="pp-tape-spoke"></span>
<span class="pp-tape-spoke"></span>
<span class="pp-tape-spoke"></span>
</span>
<span class="pp-tape-reel pp-tape-reel-r">
<span class="pp-tape-spoke"></span>
<span class="pp-tape-spoke"></span>
<span class="pp-tape-spoke"></span>
</span>
<span class="pp-tape-label">SIDE A</span>
</span>
</button> CSS Copy
.pp-tape {
width: 110px;
height: 70px;
border: 0;
padding: 0;
background: transparent;
cursor: pointer;
border-radius: 10px;
}
.pp-tape:focus-visible {
outline: 3px solid rgba(180, 83, 9, 0.5);
outline-offset: 3px;
}
.pp-tape-body {
position: relative;
display: block;
width: 100%;
height: 100%;
background: linear-gradient(180deg, #92400e 0%, #78350f 100%);
border-radius: 8px;
border: 1px solid rgba(0, 0, 0, 0.4);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.18),
inset 0 -2px 6px rgba(0, 0, 0, 0.35),
0 8px 20px -6px rgba(0, 0, 0, 0.55);
}
.pp-tape-reel {
position: absolute;
top: 50%;
width: 32px;
height: 32px;
margin-top: -16px;
border-radius: 50%;
background: radial-gradient(circle, #1f1f1f 28%, #444 30%, #444 60%, #1f1f1f 62%);
border: 1.5px solid #1a1a1a;
display: grid;
place-items: center;
}
.pp-tape-reel-l {
left: 12px;
}
.pp-tape-reel-r {
right: 12px;
}
.pp-tape-spoke {
position: absolute;
width: 2px;
height: 100%;
background: #888;
border-radius: 1px;
}
.pp-tape-spoke:nth-child(2) {
transform: rotate(60deg);
}
.pp-tape-spoke:nth-child(3) {
transform: rotate(-60deg);
}
.pp-tape[aria-pressed="true"] .pp-tape-reel {
animation: ppTapeSpin 1.6s linear infinite;
}
@keyframes ppTapeSpin {
to {
transform: rotate(360deg);
}
}
.pp-tape-label {
position: absolute;
left: 50%;
bottom: 6px;
transform: translateX(-50%);
font-family: "JetBrains Mono", monospace;
font-size: 8px;
font-weight: 700;
color: #fed7aa;
letter-spacing: 0.2em;
background: rgba(0, 0, 0, 0.4);
padding: 1px 8px;
border-radius: 2px;
pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
.pp-tape,
.pp-tape * {
animation: none !important;
}
}
JS Copy
// ── Drop this on every page where you render a play/pause button ──
// Toggles aria-pressed + aria-label on click. The CSS handles all visuals.
document.querySelectorAll('[data-pp]').forEach(function (btn) {
btn.addEventListener('click', function () {
var playing = btn.getAttribute('aria-pressed') === 'true';
btn.setAttribute('aria-pressed', String(!playing));
btn.setAttribute('aria-label', !playing ? 'Pause' : 'Play');
});
});