پیشنمایش زنده
کد HTML
<div class="glitch-radio-wrapper">
<label class="glitch-radio-container">
<input type="radio" name="protocol" checked="" />
<div class="radio-circle">
<div class="radio-dot"></div>
<div class="pulse" style="--d:0s;"></div>
<div class="pulse" style="--d:0.3s;"></div>
</div>
<span class="radio-label" data-text="PROTOCOL_TCP">PROTOCOL_TCP</span>
</label>
<label class="glitch-radio-container">
<input type="radio" name="protocol" />
<div class="radio-circle">
<div class="radio-dot"></div>
<div class="pulse" style="--d:0s;"></div>
<div class="pulse" style="--d:0.3s;"></div>
</div>
<span class="radio-label" data-text="PROTOCOL_UDP">PROTOCOL_UDP</span>
</label>
<label class="glitch-radio-container">
<input type="radio" name="protocol" disabled="" />
<div class="radio-circle">
<div class="radio-dot"></div>
<div class="pulse" style="--d:0s;"></div>
<div class="pulse" style="--d:0.3s;"></div>
</div>
<span class="radio-label" data-text="[LEGACY_SYSTEM]">[LEGACY_SYSTEM]</span>
</label>
</div>
کد CSS
/* --- Root Variables & Wrapper --- */
.glitch-radio-wrapper {
--bg-color: #0d0d0d;
--primary-color: #00f2ea;
--secondary-color: #a855f7;
--text-color: #e5e5e5;
--disabled-color: #555;
--font-family: "Fira Code", Consolas, "Courier New", Courier, monospace;
--glitch-anim-duration: 0.4s;
display: flex;
flex-direction: column;
gap: 1.5rem;
font-family: var(--font-family);
background-color: #050505;
padding: 2rem;
border-radius: 1rem;
}
/* --- Radio Container --- */
.glitch-radio-container {
display: flex;
align-items: center;
gap: 0.75rem;
cursor: pointer;
user-select: none;
position: relative;
}
.glitch-radio-container input[type="radio"] {
position: absolute;
opacity: 0;
width: 0;
height: 0;
}
/* --- Radio Circle Visual --- */
.radio-circle {
width: 1.5em;
height: 1.5em;
border: 2px solid var(--primary-color);
border-radius: 50%;
position: relative;
transition: all 0.3s ease;
display: flex;
justify-content: center;
align-items: center;
}
.radio-dot {
width: 60%;
height: 60%;
background-color: var(--primary-color);
border-radius: 50%;
transform: scale(0);
opacity: 0;
transition: all 0.3s cubic-bezier(0.18, 0.89, 0.32, 1.28);
}
.radio-label {
color: var(--text-color);
font-weight: 500;
font-size: 1rem;
text-transform: uppercase;
letter-spacing: 0.1em;
position: relative;
}
/* --- Pulse Element --- */
.pulse {
position: absolute;
inset: 0;
border: 2px solid var(--primary-color);
border-radius: 50%;
opacity: 0;
}
/* --- Checked State --- */
.glitch-radio-container input:checked + .radio-circle .radio-dot {
transform: scale(1);
opacity: 1;
}
.glitch-radio-container input:checked ~ .radio-label {
color: var(--primary-color);
text-shadow: 0 0 8px rgba(0, 242, 234, 0.7);
}
.glitch-radio-container input:checked + .radio-circle .pulse {
animation: pulse-wave 1.2s cubic-bezier(0, 0, 0.2, 1) infinite;
animation-delay: var(--d);
}
/* --- Hover State --- */
.glitch-radio-container:hover .radio-circle {
box-shadow: 0 0 10px var(--primary-color);
}
.glitch-radio-container:hover .radio-label::before,
.glitch-radio-container:hover .radio-label::after {
content: attr(data-text);
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #050505;
}
.glitch-radio-container:hover .radio-label::before {
color: var(--secondary-color);
animation: glitch-anim-text var(--glitch-anim-duration)
cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
}
.glitch-radio-container:hover .radio-label::after {
color: var(--primary-color);
animation: glitch-anim-text var(--glitch-anim-duration)
cubic-bezier(0.25, 0.46, 0.45, 0.94) reverse both;
}
/* --- Disabled State --- */
.glitch-radio-container:has(input:disabled) {
cursor: not-allowed;
}
.glitch-radio-container input:disabled + .radio-circle {
border-color: var(--disabled-color);
opacity: 0.5;
}
.glitch-radio-container input:disabled ~ .radio-label {
color: var(--disabled-color);
}
.glitch-radio-container:has(input:disabled):hover .radio-circle {
box-shadow: none;
}
.glitch-radio-container:has(input:disabled):hover .radio-label::before,
.glitch-radio-container:has(input:disabled):hover .radio-label::after {
content: none;
}
/* Keyframes */
@keyframes glitch-anim-text {
0% {
transform: translate(0);
clip-path: inset(0 0 0 0);
}
20% {
transform: translate(-3px, 2px);
clip-path: inset(50% 0 20% 0);
}
40% {
transform: translate(2px, -1px);
clip-path: inset(20% 0 60% 0);
}
60% {
transform: translate(-2px, 1px);
clip-path: inset(80% 0 5% 0);
}
80% {
transform: translate(2px, -2px);
clip-path: inset(30% 0 45% 0);
}
100% {
transform: translate(0);
clip-path: inset(0 0 0 0);
}
}
/* Keyframes for Pulse Wave */
@keyframes pulse-wave {
from {
transform: scale(1);
opacity: 0.7;
}
to {
transform: scale(2.5);
opacity: 0;
}
}