پیشنمایش زنده
کد HTML
<div class="radio-group">
<div class="radio-container">
<label for="" class="radio-button"></label>
<input type="radio" name="option" value="yes" class="radio-input-element" />
<svg
class="radio-icon-element"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
>
<circle cx="12" cy="12" r="8"></circle>
</svg>
<div class="glow"></div>
</div>
<div class="radio-container danger">
<label for="" class="radio-button"></label>
<input type="radio" name="option" value="no" class="radio-input-element" />
<svg
class="radio-icon-element"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
>
<path d="M6 18 18 6M6 6l12 12"></path>
</svg>
<div class="glow"></div>
</div>
</div>
کد CSS
/* Radio group styles */
.radio-group {
--radio-size-total: 120px; /* Total size */
--radio-border: 12px; /* Border thickness */
--radio-bg-hue: 220; /* Background hue */
--radio-border-hue: 210; /* Border hue */
--transition-speed: 0.05s; /* Transition speed for hover effects */
--glow-speed: 1.25s; /* Speed for glow animation */
--glow-times: 3; /* Number of times the glow animation runs */
display: flex;
flex-wrap: wrap;
gap: 3rem;
align-items: center;
justify-content: center;
}
/* Base */
.radio-container {
position: relative;
width: var(--radio-size-total);
height: var(--radio-size-total);
border-radius: 50%;
background-color: hsl(var(--radio-border-hue), 20%, 20%);
box-shadow: 0 calc(var(--radio-border) / 3) 4px 0 #0007;
}
/* Base bevels */
.radio-container::before {
content: "";
pointer-events: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 50%;
background-color: hsla(var(--radio-border-hue), 20%, 10%, 1);
mask: radial-gradient(
circle at 50% 50%,
transparent calc(var(--radio-size-total) / 2 - var(--radio-border)),
black calc(var(--radio-size-total) / 2 - var(--radio-border) + 1px),
black calc(var(--radio-size-total) / 2 - var(--radio-border) + 3px),
transparent calc(var(--radio-size-total) / 2 - var(--radio-border) + 5px),
transparent calc(var(--radio-size-total) / 2 - 5px),
black calc(var(--radio-size-total) / 2 - 3px)
);
z-index: 1;
}
.radio-button {
position: absolute;
top: calc(var(--radio-border) / 1);
left: calc(var(--radio-border) / 1);
width: calc(var(--radio-size-total) - var(--radio-border) * 2);
height: calc(var(--radio-size-total) - var(--radio-border) * 2);
border-radius: 50%;
background-color: hsl(var(--radio-bg-hue), 100%, 50%);
background-image: linear-gradient(
to bottom,
hsl(var(--radio-bg-hue), 100%, 60%) 0%,
hsl(var(--radio-bg-hue), 100%, 50%) 70%,
hsl(var(--radio-bg-hue), 100%, 30%) 100%
);
box-shadow: 0 calc(var(--radio-border) * 2) 6px 6px #0003;
transition: box-shadow var(--transition-speed) ease-in-out;
}
/* Gloss effects 1 */
.radio-button::before {
content: "";
position: absolute;
pointer-events: none;
top: calc(-1 * var(--radio-border));
left: calc(-1 * var(--radio-border));
width: var(--radio-size-total);
height: var(--radio-size-total);
border-radius: 50%;
background-image: radial-gradient(
circle at 50% 50%,
transparent calc(var(--radio-size-total) / 2 - var(--radio-border)),
hsla(var(--radio-border-hue), 100%, 0%, 0.5) 75%
),
conic-gradient(
from 20deg at 50% 50%,
#fff 0%,
transparent 1%,
#fff4 20%,
#0002 50%,
#fff8 75%,
transparent 85%,
#fffa 86%,
#fff6 87%,
transparent 99%,
#fff 100%
);
mask-image: radial-gradient(
circle at 50% 50%,
transparent 0,
transparent 30%,
black 35%,
black calc(var(--radio-size-total) / 2),
transparent calc(var(--radio-size-total) / 2 + 2px)
);
}
/* Gloss effects 2 */
.radio-button::after {
content: "";
position: absolute;
pointer-events: none;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 50%;
background-image:
/* Small reflection */
radial-gradient(
ellipse 6% 4% at 43% 29%,
#fffe 35%,
#fff8 55%,
transparent 100%
),
/* Repeating small reflections */
radial-gradient(
ellipse 3% 2% at 75% 20%,
#fffd 45%,
#fff8 50%,
transparent 100%
),
radial-gradient(
ellipse 2% 1% at 70% 30%,
#fffc 15%,
#fff7 50%,
transparent 100%
),
radial-gradient(
ellipse 2% 1% at 65% 40%,
#fffa 15%,
#fff5 50%,
transparent 100%
),
radial-gradient(
ellipse 3% 2% at 25% 22%,
#fffd 45%,
#fff8 50%,
transparent 100%
),
radial-gradient(
ellipse 2% 1% at 30% 32%,
#fffc 15%,
#fff7 50%,
transparent 100%
),
radial-gradient(
ellipse 2% 1% at 35% 42%,
#fffa 15%,
#fff5 50%,
transparent 100%
),
/* Large reflection */
radial-gradient(
ellipse 70% 50% at 50% 37%,
transparent 0%,
#fff2 45%,
#fff3 51%,
transparent 57%
),
radial-gradient(
circle at 50% 50%,
transparent 40%,
#fff2 47%,
#fff1 68%,
transparent 59%,
transparent 100%
);
box-shadow: 0 0 calc(var(--radio-border) / 3) 3px #000c inset;
z-index: 1;
transition:
box-shadow var(--transition-speed) ease-in-out,
background-image var(--transition-speed) ease-in-out;
}
/* Radio input (no appearance) */
.radio-input-element {
position: absolute;
top: calc(var(--radio-border) / 1);
left: calc(var(--radio-border) / 1);
width: calc(var(--radio-size-total) - var(--radio-border) * 2);
height: calc(var(--radio-size-total) - var(--radio-border) * 2);
appearance: none;
border-radius: 50%;
background-color: transparent;
opacity: 0;
margin: 0;
cursor: pointer;
}
/* Radio icon */
.radio-icon-element {
position: absolute;
pointer-events: none;
width: 75%;
height: 75%;
top: 12.5%;
left: 12.5%;
fill: none;
stroke: rgba(230, 230, 230, 0.9);
stroke-width: 3px;
stroke-linecap: square;
filter: drop-shadow(0 14px 3px rgba(0, 0, 0, 0.4));
/* Simulate spherical shading */
mask-image: radial-gradient(circle at center, black 40%, transparent 100%);
mask-composite: exclude;
-webkit-mask-image: radial-gradient(
circle at center,
black 40%,
transparent 100%
);
-webkit-mask-composite: destination-out;
z-index: 0;
transition:
transform calc(var(--transition-speed) * 0.25) ease-in-out,
filter calc(var(--transition-speed) * 0.25) ease-in-out;
}
.glow {
pointer-events: none;
position: absolute;
top: -15%;
left: 0;
width: 100%;
height: 100%;
border-radius: 50%;
background-color: color-mix(
in hsl,
hsl(var(--radio-bg-hue), 100%, 60%),
rgb(255, 225, 92) 15%
);
filter: blur(2em);
opacity: 0.45;
transform: perspective(100px) rotateX(10deg) scale(0.8);
z-index: 1;
opacity: 0;
}
/* Checked state styles */
.radio-container:has(.radio-input-element:checked) {
.radio-button {
box-shadow: 0 calc(var(--radio-border) * 2) 12px 2px #0004;
}
.radio-button::after {
box-shadow: 0 0 var(--radio-border) calc(var(--radio-border) / 2) #000c
inset;
}
.glow {
animation: pulse var(--glow-speed) ease-in-out var(--glow-times) forwards;
}
.radio-icon-element {
filter: drop-shadow(0 12px 2px rgba(0, 0, 0, 0.5));
}
}
.radio-container:has(.radio-input-element:checked):hover {
.radio-icon-element {
filter: drop-shadow(0 16px 4px rgba(0, 0, 0, 0.4));
}
}
.radio-container:has(.radio-input-element:checked):active {
.radio-icon-element {
filter: drop-shadow(0 10px 2px rgba(0, 0, 0, 0.4));
}
}
/* Hover effect */
.radio-container:hover {
.radio-button {
box-shadow: 0 calc(var(--radio-border) * 2.5) 12px 2px #0003;
}
.radio-button::after {
box-shadow: 0 0 calc(var(--radio-border) / 3) 3px #0005 inset;
scale: 1.05;
}
.radio-icon-element {
transform: scale(1.05);
filter: drop-shadow(0 16px 4px rgba(0, 0, 0, 0.4));
}
}
/* Active state styles */
.radio-container:active {
.radio-button {
box-shadow: 0 calc(var(--radio-border) * 1.5) 6px 4px #0003;
}
.radio-button::after {
box-shadow: 0 0 calc(var(--radio-border) / 1) var(--radio-border) #0009
inset;
scale: 1;
}
.radio-icon-element {
transform: scale(0.95);
filter: drop-shadow(0 10px 2px rgba(0, 0, 0, 0.4));
}
}
/* Pulse animation for glow effect */
@keyframes pulse {
0% {
transform: perspective(100px) rotateX(10deg) scale(0.8);
opacity: 0.45;
}
50% {
transform: perspective(100px) rotateX(10deg) scale(1);
opacity: 0.75;
}
100% {
transform: perspective(100px) rotateX(10deg) scale(0.8);
opacity: 0.45;
}
}
/* Color themes */
.success {
--radio-bg-hue: 145;
}
.warning {
--radio-bg-hue: 40;
}
.danger {
--radio-bg-hue: 355;
}
.info {
--radio-bg-hue: 200;
}