Another overly elaborate radio animation
A Pen by Beibit Sakhanov on CodePen.
<div class="bulgy-radios" role="radiogroup" aria-labelledby="bulgy-radios-label"> | |
<h2 id="bulgy-radios-label">Select an option</h2> | |
<label> | |
<input type="radio" name="options" checked /> | |
<span class="radio"></span> | |
<span class="label">First option</span> | |
</label> | |
<label> | |
<input type="radio" name="options" /> | |
<span class="radio"></span> | |
<span class="label">Second option</span> | |
</label> | |
<label> | |
<input type="radio" name="options" /> | |
<span class="radio"></span> | |
<span class="label">Third option</span> | |
</label> | |
<label> | |
<input type="radio" name="options" /> | |
<span class="radio"></span> | |
<span class="label">Fourth option</span> | |
</label> | |
<label> | |
<input type="radio" name="options" /> | |
<span class="radio"></span> | |
<span class="label">Last option</span> | |
</label> | |
</div> | |
//This is sort of CSS-only; the JS below just sticks a span around each letter, so i can animate each independantly. | |
//(oh for an :nth-letter selector!) | |
const labels = document.querySelectorAll('.label'); | |
labels.forEach(label => { | |
const chars = label.textContent.split(''); | |
label.innerHTML = ''; | |
chars.forEach(char => { | |
label.innerHTML += `<span>${char === ' ' ? ' ' : char}</span>`; | |
}); | |
}) |
Another overly elaborate radio animation
A Pen by Beibit Sakhanov on CodePen.
html { box-sizing: border-box; height: 100%; font-size: 10px; } *, *::before, *::after { box-sizing: inherit; } | |
body { | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
min-height: 100vh; | |
font-family: 'Lato', sans-serif; | |
background: #2f2f2f; | |
} | |
h2 { | |
font-size: 3rem; | |
font-weight: bold; | |
margin: 0 0 3rem; | |
} | |
.bulgy-radios { | |
width: 38rem; | |
background: #fff; | |
padding: 3rem 0 3rem 5rem; | |
border-radius: 1rem; | |
label { | |
display: block; | |
position: relative; | |
height: 1em; | |
padding-left: 4rem; | |
margin-bottom: 1.75rem; | |
cursor: pointer; | |
font-size: 2.5rem; | |
user-select: none; | |
color: #555; | |
letter-spacing: 1px; | |
&:hover input:not(:checked) ~ .radio { | |
opacity: 0.8; | |
} | |
} | |
.label { | |
display: flex; | |
align-items: center; | |
padding-right: 3rem; | |
span { | |
line-height: 1em; | |
} | |
} | |
input { | |
position: absolute; | |
cursor: pointer; | |
height: 0; | |
width: 0; | |
left: -2000px; | |
&:checked { | |
~ .radio { | |
background-color: #0ac07d; | |
transition: background .3s; | |
&::after { | |
opacity: 1; | |
} | |
} | |
~ .label { | |
color: #0bae72; | |
span { | |
animation: bulge .5s forwards; | |
} | |
//adjust this if label is going to be more than 20 chars | |
@for $i from 1 to 20 { | |
span:nth-child(#{$i}) { animation-delay: $i * 0.025s; } | |
} | |
} | |
} | |
} | |
} | |
.radio { | |
position: absolute; | |
top: 0.2rem; | |
left: 0; | |
height: 2.5rem; | |
width: 2.5rem; | |
background: #c9ded6; | |
border-radius: 50%; | |
&::after { | |
content: ''; | |
position: absolute; | |
opacity: 0; | |
top: .5rem; | |
left: .5rem; | |
width: 1.5rem; | |
height: 1.5rem; | |
border-radius: 50%; | |
background: #fff; | |
} | |
} | |
@keyframes bulge { | |
50% { | |
transform: rotate(4deg); | |
font-size: 1.5em; | |
font-weight: bold; | |
} | |
100% { | |
transform: rotate(0); | |
font-size: 1em; | |
font-weight: bold; | |
} | |
} |