پیشنمایش زنده
کد HTML
<div class="combination-lock">
<div class="help">Working 3D lock</div>
<div class="dial">
<div class="nonagon">
<div class="face face-0">
<input type="radio" name="wheel-1" class="radio radio-0" />
<span>0</span>
</div>
<div class="face face-1">
<input type="radio" name="wheel-1" class="radio radio-1" />
<span>1</span>
</div>
<div class="face face-2">
<input type="radio" name="wheel-1" class="radio radio-2" />
<span>2</span>
</div>
<div class="face face-3">
<input type="radio" name="wheel-1" class="radio radio-3" checked="" />
<span>3</span>
</div>
<div class="face face-4">
<input type="radio" name="wheel-1" class="radio radio-4" />
<span>4</span>
</div>
<div class="face face-5">
<input type="radio" name="wheel-1" class="radio radio-5" />
<span>5</span>
</div>
<div class="face face-6">
<input type="radio" name="wheel-1" class="radio radio-6" />
<span>6</span>
</div>
<div class="face face-7">
<input type="radio" name="wheel-1" class="radio radio-7" />
<span>7</span>
</div>
<div class="face face-8">
<input type="radio" name="wheel-1" class="radio radio-8" />
<span>8</span>
</div>
<div class="face face-9">
<input type="radio" name="wheel-1" class="radio radio-9" />
<span>9</span>
</div>
</div>
</div>
<div class="dial">
<div class="nonagon">
<div class="face face-0">
<input type="radio" name="wheel-2" class="radio radio-0" />
<span>0</span>
</div>
<div class="face face-1">
<input type="radio" name="wheel-2" class="radio radio-1" />
<span>1</span>
</div>
<div class="face face-2">
<input type="radio" name="wheel-2" class="radio radio-2" />
<span>2</span>
</div>
<div class="face face-3">
<input type="radio" name="wheel-2" class="radio radio-3" />
<span>3</span>
</div>
<div class="face face-4">
<input type="radio" name="wheel-2" class="radio radio-4" checked="" />
<span>4</span>
</div>
<div class="face face-5">
<input type="radio" name="wheel-2" class="radio radio-5" />
<span>5</span>
</div>
<div class="face face-6">
<input type="radio" name="wheel-2" class="radio radio-6" />
<span>6</span>
</div>
<div class="face face-7">
<input type="radio" name="wheel-2" class="radio radio-7" />
<span>7</span>
</div>
<div class="face face-8">
<input type="radio" name="wheel-2" class="radio radio-8" />
<span>8</span>
</div>
<div class="face face-9">
<input type="radio" name="wheel-2" class="radio radio-9" />
<span>9</span>
</div>
</div>
</div>
<div class="dial">
<div class="nonagon">
<div class="face face-0">
<input type="radio" name="wheel-3" class="radio radio-0" />
<span>0</span>
</div>
<div class="face face-1">
<input type="radio" name="wheel-3" class="radio radio-1" />
<span>1</span>
</div>
<div class="face face-2">
<input type="radio" name="wheel-3" class="radio radio-2" />
<span>2</span>
</div>
<div class="face face-3">
<input type="radio" name="wheel-3" class="radio radio-3" />
<span>3</span>
</div>
<div class="face face-4">
<input type="radio" name="wheel-3" class="radio radio-4" />
<span>4</span>
</div>
<div class="face face-5">
<input type="radio" name="wheel-3" class="radio radio-5" />
<span>5</span>
</div>
<div class="face face-6">
<input type="radio" name="wheel-3" class="radio radio-6" />
<span>6</span>
</div>
<div class="face face-7">
<input type="radio" name="wheel-3" class="radio radio-7" checked="" />
<span>7</span>
</div>
<div class="face face-8">
<input type="radio" name="wheel-3" class="radio radio-8" />
<span>8</span>
</div>
<div class="face face-9">
<input type="radio" name="wheel-3" class="radio radio-9" />
<span>9</span>
</div>
</div>
</div>
</div>
کد CSS
.combination-lock {
position: relative;
display: flex;
gap: 1.25rem;
user-select: none;
}
.dial {
width: 34px;
height: 120px;
overflow: hidden;
perspective: 500px;
border-radius: 10px / 250px;
outline: solid 3px #000;
outline-offset: 1px;
filter: drop-shadow(4px 0 0px #0006) drop-shadow(8px -1px 1px #0003)
drop-shadow(8px 10px 1px #0003)
drop-shadow(12px 16px 32px rgba(255, 231, 201, 0.5))
drop-shadow(-12px -16px 64px rgba(255, 231, 201, 0.5)) contrast(1.6);
box-shadow:
-2px -3px 0 4px #1115,
0 -3px 0 2px #fff,
0 2px 0 3px #eee,
0 4px 0 4px #0009;
}
.dial::after {
content: "";
position: absolute;
inset: 0;
background-image: radial-gradient(circle at 50% 50%, #000 40%, 40.5%, #fff0),
linear-gradient(to bottom, #fff, 50%, #111);
background-position:
0 16px,
0 0;
background-repeat: no-repeat;
mix-blend-mode: soft-light;
pointer-events: none;
}
.nonagon {
width: 100%;
height: 100%;
position: relative;
top: 36px;
transform-style: preserve-3d;
transform-origin: 0 24px;
transform: rotateX(0deg);
transition: transform 300ms ease;
}
.face {
position: absolute;
display: grid;
place-items: center;
width: 34px;
height: 47px;
background-color: #bbbab8;
box-shadow:
0 -3px 1px 2px #000a,
0 0px 1px 3px #fffe;
font-family: "Lucida Console", Courier, monospace;
font-size: 1.75em;
font-weight: bolder;
text-shadow:
1px 1px 0.5px #fff,
-1px -1px 0.5px #ccc,
-0.5px -0.5px 0.5px #0005;
color: #000b;
-webkit-text-stroke: 01px #aaa6;
}
.face::before,
.face::after {
content: "";
position: absolute;
height: 100%;
width: 4px;
border: 0.5px solid #0005;
}
.face::before {
left: 0;
background-color: #fff;
}
.face::after {
right: 0;
background-color: #0004;
}
.face span {
position: absolute;
pointer-events: none;
}
.face .radio {
position: absolute;
width: 100%;
height: 100%;
cursor: pointer;
appearance: none;
opacity: 0.5;
z-index: 0;
}
.nonagon:has(.radio-0:checked) {
transform: rotateX(0deg);
}
.nonagon:has(.radio-1:checked) {
transform: rotateX(36deg);
}
.nonagon:has(.radio-2:checked) {
transform: rotateX(72deg);
}
.nonagon:has(.radio-3:checked) {
transform: rotateX(108deg);
}
.nonagon:has(.radio-4:checked) {
transform: rotateX(144deg);
}
.nonagon:has(.radio-5:checked) {
transform: rotateX(180deg);
}
.nonagon:has(.radio-6:checked) {
transform: rotateX(216deg);
}
.nonagon:has(.radio-7:checked) {
transform: rotateX(252deg);
}
.nonagon:has(.radio-8:checked) {
transform: rotateX(288deg);
}
.nonagon:has(.radio-9:checked) {
transform: rotateX(324deg);
}
.face-0 {
transform: rotateX(0deg) translateZ(71px);
}
.face-1 {
transform: rotateX(-36deg) translateZ(71px);
}
.face-2 {
transform: rotateX(-72deg) translateZ(71px);
}
.face-3 {
transform: rotateX(-108deg) translateZ(71px);
}
.face-4 {
transform: rotateX(-144deg) translateZ(71px);
}
.face-5 {
transform: rotateX(-180deg) translateZ(71px);
}
.face-6 {
transform: rotateX(-216deg) translateZ(71px);
}
.face-7 {
transform: rotateX(-252deg) translateZ(71px);
}
.face-8 {
transform: rotateX(-288deg) translateZ(71px);
}
.face-9 {
transform: rotateX(-324deg) translateZ(71px);
}
.help {
position: absolute;
width: 100%;
transform: translateY(-50px);
text-align: center;
bottom: -40;
text-wrap: nowrap;
font-family: "Gill Sans", "Gill Sans MT", Calibri, "Trebuchet MS", sans-serif;
font-weight: lighter;
font-size: 1em;
font-style: italic;
color: #0007;
}