<input type="checkbox" id="checkbox">
<label for="checkbox" id="spin">Spin</label>
<div id="wheel">
<div id="wheel-contents">
<div class="wheel-stripe">💸</div>
<div class="wheel-stripe"></div>
<div class="wheel-stripe">🌴</div>
<div class="wheel-stripe"></div>
<div class="wheel-stripe">💻</div>
<div class="wheel-stripe"></div>
<div class="wheel-stripe">🍦</div>
<div class="wheel-stripe"></div>
<div class="wheel-stripe">⛰️</div>
<div class="wheel-stripe"></div>
<div class="wheel-stripe">🌭</div>
<div class="wheel-stripe"></div>
<div class="wheel-stripe">🎸</div>
<div class="wheel-stripe"></div>
<div class="wheel-stripe">🍰</div>
<div class="wheel-stripe"></div>
</div>
</div>
html, body { width: 100%; height: 100%; margin: 0; padding: 0; }
body {
background-color: #0b1e46;
display: grid;
grid-template-rows: 1fr min-content;
justify-items: center;
align-items: center;
}
#spin {
display: inline-block;
background-color: green;
color: white;
padding: 10px;
grid-row: 2;
border-radius: 10px;
box-shadow: 0 -4px 0 rgba(0,0,0,0.2) inset;
font-family: system-ui;
font-size: 20px;
font-weight: 900;
text-transform: uppercase;
letter-spacing: 3px;
margin: 20px;
-webkit-user-select: none;
transition: opacity 0.5s, visibility 0.5s;
&:hover {
background-color: color-mix(in srgb, black 10%, green);
}
&:hover:active {
background-color: color-mix(in srgb, black 15%, green);
box-shadow: 0 2px 0 rgba(0,0,0,0.2) inset;
}
}
#checkbox {
display: none;
&:checked ~ #wheel #wheel-contents,
&:checked ~ #wheel::before {
animation-play-state: running;
}
&:checked ~ #spin {
visibility: hidden;
opacity: 0;
}
}
@keyframes spin {
from {
rotate: 0deg;
}
to {
rotate: 10turn; /* Fallback for browsers that don't support `random()` */
rotate: random(2turn, 10turn, by 20deg);
}
}
@keyframes wiggle-indicator {
from {
rotate: -10deg;
}
to {
rotate: 0deg;
}
}
#wheel {
--radius: 150px;
--circumference: calc(2 * pi * var(--radius));
--num-items: 16;
--spin-duration: 20s;
width: calc(var(--radius) * 2);
height: calc(var(--radius) * 2);
position: relative;
box-shadow: 0 3px 10px rgba(0,0,0,0.8);
border-radius: 100%;
grid-row: 1;
-webkit-user-select: none;
user-select: none;
&::before {
content: "";
clip-path: polygon(0% 0%, 100% 0%, 50% 100%);
width: 10px;
height: 18px;
background-color: black;
position: absolute;
top: 0;
left: 50%;
translate: -50% calc(-40% + .2em);
z-index: 2;
animation: wiggle-indicator 1s calc(var(--spin-duration) / 1s) ease paused;
}
&::after {
content: "";
background-color: #222;
box-shadow: 0 0 10px rgba(0,0,0,0.4);
width: 100px;
height: 100px;
border-radius: 100%;
position: absolute;
left: 50%;
top: 50%;
translate: -50% -50%;
}
}
#wheel-contents {
display: inline-grid;
background-color: black;
justify-content: center;
width: 100%;
height: 100%;
overflow: hidden;
border-radius: 100%;
animation: spin 20s forwards ease paused;
}
.wheel-stripe {
grid-area: 1/1;
display: flex;
flex-direction: column;
justify-content: space-between;
width: calc(var(--circumference) / var(--num-items));
height: 50%;
box-sizing: border-box;
background-color: #f1f1f1;
background-image: radial-gradient(circle, transparent 0, black 0, black 70%, transparent 80%);
background-size: 4px 4px;
background-position: top .2em center;
background-repeat: no-repeat;
font-size: 30px;
rotate: calc(1turn / var(--num-items) * var(--id));
transform-origin: center bottom;
text-align: center;
padding-block: .4em;
clip-path: polygon(0% 0%, 100% 0%, 50% 100%);
&:nth-child(1) { --id: 1 }
&:nth-child(2) { --id: 2 }
&:nth-child(3) { --id: 3 }
&:nth-child(4) { --id: 4 }
&:nth-child(5) { --id: 5 }
&:nth-child(6) { --id: 6 }
&:nth-child(7) { --id: 7 }
&:nth-child(8) { --id: 8 }
&:nth-child(9) { --id: 9 }
&:nth-child(10) { --id: 10 }
&:nth-child(11) { --id: 11 }
&:nth-child(12) { --id: 12 }
&:nth-child(13) { --id: 13 }
&:nth-child(14) { --id: 14 }
&:nth-child(15) { --id: 15 }
}