Last active
July 29, 2021 07:22
-
-
Save Sheraff/9bdcd37bf0e3e901acb357247697540a to your computer and use it in GitHub Desktop.
jumpy dot radio group
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "scripts": [], | |
| "styles": [] | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <input id="1" type="radio" name="radios" value="1" /> | |
| <label for="1"><div class="dot"></div>Hello</label> | |
| <input id="2" type="radio" name="radios" value="2" /> | |
| <label for="2"><div class="dot"></div>Bonjour</label> | |
| <input id="3" type="radio" name="radios" value="3" /> | |
| <label for="3"><div class="dot"></div>Hola</label> | |
| <input id="4" type="radio" name="radios" value="4" /> | |
| <label for="4"><div class="dot"></div>안녕하세요</label> | |
| <input id="5" type="radio" name="radios" value="5" /> | |
| <label for="5"><div class="dot"></div>Guten Tag</label> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const radios = Array.from(document.querySelectorAll('label')) | |
| let previous | |
| radios.forEach(radio => radio.addEventListener('click', async ({ target }) => { | |
| const current = target.closest('label') | |
| if (previous && previous !== current) { | |
| const y = current.offsetTop - previous.offsetTop | |
| const distorsion = Math.abs(y)**.8 | |
| const duration = distorsion + 300 | |
| await new Promise(resolve => previous.firstElementChild.animate([ | |
| // keyframes | |
| { transform: 'none' }, | |
| { transform: `translateY(${y / 2}px) translateX(${- distorsion / 10}px) scaleY(${1.2 + distorsion / 50}) scaleX(1.2)` } | |
| ], { | |
| // timing options | |
| duration, | |
| easing: `cubic-bezier(${.2 + distorsion / 100},-0.4,.83,.67)`, | |
| }).onfinish = resolve); | |
| previous.classList.remove('checked') | |
| current.classList.add('checked') | |
| await new Promise(resolve => current.firstElementChild.animate([ | |
| // keyframes | |
| { transform: `translateY(${- y / 2}px) translateX(${- distorsion / 10}px) scaleY(${1.2 + distorsion / 50}) scaleX(1.2)` }, | |
| { transform: 'none' } | |
| ], { | |
| // timing options | |
| duration, | |
| easing: 'cubic-bezier(.57,1.55,.17,.33)', | |
| }).onfinish = resolve); | |
| } | |
| if(!previous) { | |
| current.classList.add('checked') | |
| await Promise.all([ | |
| new Promise(resolve => current.firstElementChild.animate([ | |
| // keyframes | |
| { transform: `scaleY(1.7) scaleX(1.7)` }, | |
| { transform: 'none' } | |
| ], { | |
| // timing options | |
| duration: 500, | |
| easing: 'cubic-bezier(.57,1.55,.17,.33)', | |
| }).onfinish = resolve), | |
| new Promise(resolve => current.firstElementChild.animate([ | |
| // keyframes | |
| { opacity: 0 }, | |
| { opacity: 1 } | |
| ], { | |
| // timing options | |
| duration: 300, | |
| }).onfinish = resolve), | |
| ]) | |
| } | |
| if(previous) | |
| previous.classList.remove('checked') | |
| previous = current | |
| current.classList.add('checked') | |
| })) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| body { | |
| background-color: #1f1f1f; | |
| color: white; | |
| } | |
| [type=radio] { | |
| display: none; | |
| } | |
| label.checked .dot { | |
| background: currentColor; | |
| } | |
| label { | |
| --margin: 1rem; | |
| --dot: .7rem; | |
| --radio: 1rem; | |
| position: relative; | |
| display: block; | |
| margin: var(--margin); | |
| padding-left: calc(var(--radio) + 1rem); | |
| height: var(--radio); | |
| line-height: var(--radio); | |
| cursor: pointer; | |
| } | |
| label::after, | |
| label .dot { | |
| content: ''; | |
| display: block; | |
| position: absolute; | |
| border-radius: calc(var(--radio) / 2); | |
| } | |
| label::after { | |
| left: 0; | |
| top: 0; | |
| height: var(--radio); | |
| width: var(--radio); | |
| box-shadow: 0 0 0 1px currentColor; | |
| } | |
| label .dot { | |
| left: calc(var(--radio) / 2 - var(--dot) / 2); | |
| top: calc(var(--radio) / 2 - var(--dot) / 2); | |
| height: var(--dot); | |
| width: var(--dot); | |
| transform-origin: center center; | |
| z-index: 1; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment