<div class="task-item">
<label class="checkbox">
<input type="checkbox" />
<svg viewBox="0 0 21 18">
<symbol id="tick-path" viewBox="0 0 21 18" xmlns="http://www.w3.org/2000/svg">
<path d="M5.22003 7.26C5.72003 7.76 7.57 9.7 8.67 11.45C12.2 6.05 15.65 3.5 19.19 1.69" fill="none" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" />
</symbol>
<defs>
<mask id="tick">
<use class="tick mask" href="#tick-path" />
</mask>
</defs>
<path class="shape" d="M1.08722 4.13374C1.29101 2.53185 2.53185 1.29101 4.13374 1.08722C5.50224 0.913124 7.25112 0.75 9 0.75C10.7489 0.75 12.4978 0.913124 13.8663 1.08722C15.4681 1.29101 16.709 2.53185 16.9128 4.13374C17.0869 5.50224 17.25 7.25112 17.25 9C17.25 10.7489 17.0869 12.4978 16.9128 13.8663C16.709 15.4681 15.4682 16.709 13.8663 16.9128C12.4978 17.0869 10.7489 17.25 9 17.25C7.25112 17.25 5.50224 17.0869 4.13374 16.9128C2.53185 16.709 1.29101 15.4681 1.08722 13.8663C0.913124 12.4978 0.75 10.7489 0.75 9C0.75 7.25112 0.913124 5.50224 1.08722 4.13374Z" />
<use class="tick" href="#tick-path" stroke="currentColor" />
<path fill="#2C2C31" mask="url(#tick)" d="M4.03909 0.343217C5.42566 0.166822 7.20841 0 9 0C10.7916 0 12.5743 0.166822 13.9609 0.343217C15.902 0.590152 17.4098 2.09804 17.6568 4.03909C17.8332 5.42566 18 7.20841 18 9C18 10.7916 17.8332 12.5743 17.6568 13.9609C17.4098 15.902 15.902 17.4098 13.9609 17.6568C12.5743 17.8332 10.7916 18 9 18C7.20841 18 5.42566 17.8332 4.03909 17.6568C2.09805 17.4098 0.590152 15.902 0.343217 13.9609C0.166822 12.5743 0 10.7916 0 9C0 7.20841 0.166822 5.42566 0.343217 4.03909C0.590151 2.09805 2.09804 0.590152 4.03909 0.343217Z" />
</svg>
<svg class="lines" viewBox="0 0 11 11">
<path d="M5.88086 5.89441L9.53504 4.26746" />
<path d="M5.5274 8.78838L9.45391 9.55161" />
<path d="M3.49371 4.22065L5.55387 0.79198" />
</svg>
</label>
<div class="text">New domain <a href="https://check.so" target="_blank">check.so</a></div>
<button class="flag">
<svg viewBox="0 0 18 18">
<path d="M7.66 16.75L2.25 2C8 -0.249996 9.5 3.50001 14 1.75C15.5 4.25002 16 8.00002 15.5 9C11 11 9.5 8.50002 5.03377 9.58975" />
<path class="fill" d="M7.66 16.75L2.25 2C8 -0.249996 9.5 3.50001 14 1.75C15.5 4.25002 16 8.00002 15.5 9C11 11 9.5 8.50002 5.03377 9.58975" />
</svg>
</button>
</div>
.task-item {
--text-color: #fff;
--text-line-scale: 0;
--text-x: 0px;
--border-default: #7F7F85;
--border-hover: #E4E4E7;
--checkbox-active: #6E7BF2;
position: relative;
z-index: 1;
display: flex;
align-items: center;
width: 340px;
border-radius: 7px;
overflow: hidden;
-webkit-mask-image: -webkit-radial-gradient(white, black);
transition: background .15s linear;
&:not(.done) {
&:hover {
--blur-x: 372px;
--blur-o: 1;
background: #2C2C31;
}
}
&:before {
content: '';
position: absolute;
width: 32px;
height: 6px;
right: 100%;
top: -11px;
border-radius: 50%;
box-shadow: 0px 4px 4px var(--checkbox-active);
transform: translateX(var(--blur-x, 0));
opacity: var(--blur-o, 0);
transition: opacity .15s, transform 1.2s;
}
&.done {
--checkbox-active: #444449;
--flag-border: #444449;
--text-color: #626268;
}
.text {
display: block;
letter-spacing: -.05px;
text-decoration: none;
color: var(--text-color);
position: relative;
transform: translateX(var(--text-x)) translateZ(0);
transition: color .25s;
&:before {
content: '';
position: absolute;
height: 1px;
left: -2px;
right: -2px;
top: 50%;
transform-origin: 0 50%;
transform: translateY(-50%) scaleX(var(--text-line-scale)) translateZ(0);
background: currentColor;
}
a {
color: inherit;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
.checkbox {
--active-tick: #ffffff;
--checkbox-lines-offset: 13.5px;
display: block;
padding: 15px 12px;
cursor: pointer;
position: relative;
-webkit-tap-highlight-color: transparent;
svg {
display: block;
position: absolute;
}
input {
display: block;
outline: none;
border: none;
background: none;
padding: 0;
margin: 0;
-webkit-appearance: none;
width: 18px;
height: 18px;
& + svg {
width: 21px;
height: 18px;
left: 12px;
top: 15px;
color: var(--checkbox-active);
transition: color .25s linear;
.shape {
stroke-width: 1.5px;
stroke: var(--border, var(--border-default));
fill: var(--background, none);
transition: fill .25s linear, stroke .25s linear;
}
.tick {
stroke-dasharray: 20;
stroke-dashoffset: var(--checkbox-tick-offset, 20px);
transition: stroke-dashoffset var(--checkbox-tick-duration, .15s) var(--checkbox-tick-easing, ease);
&.mask {
stroke: var(--active-tick);
}
}
& + svg {
width: 11px;
height: 11px;
fill: none;
stroke: var(--checkbox-active);
stroke-width: 1.25;
stroke-linecap: round;
top: 9px;
right: 2px;
stroke-dasharray: 4.5px;
stroke-dashoffset: var(--checkbox-lines-offset);
pointer-events: none;
}
}
&:checked {
& + svg {
--background: var(--checkbox-active);
--border: var(--checkbox-active);
--checkbox-tick-duration: .2s;
--checkbox-tick-easing: cubic-bezier(0, .45, 1, .5);
--checkbox-tick-offset: 0;
}
}
}
&:hover {
input {
&:not(:checked) {
& + svg {
--border: var(--border-hover);
}
}
}
}
}
.flag {
--flag-color: #BABAC1;
--flag-fill: var(--checkbox-active);
--flag-fill-percent: 0%;
--flag-scale-x: 1;
--flag-scale-y: 1;
--flag-rotate: 0deg;
--flag-circle-opacity: 0;
--flag-circle-scale: 0;
-webkit-appearance: none;
-webkit-tap-highlight-color: transparent;
cursor: pointer;
outline: none;
border: none;
background: none;
padding: 15px 12px;
margin: 0 0 0 auto;
position: relative;
&.active {
--flag-fill-percent: 150%;
}
svg {
display: block;
width: 18px;
height: 18px;
position: relative;
z-index: 1;
pointer-events: none;
fill: none;
stroke: var(--flag-border, var(--border, var(--border-default)));
stroke-width: 1.5;
stroke-linecap: round;
stroke-linejoin: round;
transform-origin: 7.66px 16.75px;
transform: scale(var(--flag-scale-x), var(--flag-scale-y)) rotate(var(--flag-rotate));
transition: stroke .25s linear;
.fill {
stroke: var(--flag-fill);
fill: var(--flag-fill);
clip-path: circle(var(--flag-fill-percent) at var(--flag-fill-x, 7.66px) var(--flag-fill-y, 16.75px));
transition: fill .25s linear, stroke .25s linear;
}
}
&:hover {
--border: var(--border-hover);
}
&:before {
content: '';
display: block;
width: 24px;
height: 12px;
border-radius: 50%;
position: absolute;
bottom: 6px;
left: 8px;
opacity: var(--flag-circle-opacity);
background: var(--flag-fill);
transform: scale(var(--flag-circle-scale)) translateZ(0);
}
}
}
html {
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
}
* {
box-sizing: inherit;
&:before,
&:after {
box-sizing: inherit;
}
}
// Center & dribbble
body {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: #242428;
padding: 20px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
}
View Compiled
const { to, set, registerPlugin } = gsap
const checkAudio = new Audio('https://assets.codepen.io/165585/check.mp3')
const flagAudio = new Audio('https://assets.codepen.io/165585/flag-2.mp3')
registerPlugin(MorphSVGPlugin)
document.querySelectorAll('.task-item').forEach(task => {
let checkbox = task.querySelector('.checkbox'),
checkboxInput = checkbox.querySelector('input'),
flag = task.querySelector('.flag'),
flagPath = flag.querySelectorAll('path'),
timer
checkboxInput.addEventListener('change', e => {
clearInterval(timer)
if(e.target.checked) {
checkAudio.play()
to(checkbox, {
'--checkbox-lines-offset': '4.5px',
duration: 0.2,
delay: 0.2,
clearProps: true
});
to(task, {
keyframes: [{
'--text-line-scale': 1,
'--text-x': '2px',
duration: .15
}, {
'--text-x': '0px',
duration: .15,
onComplete() {
timer = setTimeout(() => task.classList.add('done'), 500)
}
}]
})
return
}
to(task, {
'--text-line-scale': 0,
duration: .25,
onComplete() {
task.classList.remove('done')
}
})
})
flag.addEventListener('pointerenter', e => {
flag.animating
if(flag.animating) {
return
}
to(flag, {
keyframes: [{
'--flag-rotate': e.offsetX > 21 ? '-4deg' : '4deg',
duration: .1
}, {
'--flag-rotate': e.offsetX > 21 ? '4deg' : '-4deg',
duration: .1
}, {
'--flag-rotate': '0deg',
duration: .1
}],
})
})
flag.addEventListener('click', e => {
if(flag.animating) {
return
}
flag.animating = true
if(flag.classList.contains('active')) {
to(flag, {
keyframes: [{
'--flag-scale-y': .9,
'--flag-fill-percent': '0%',
duration: .15
}, {
'--flag-scale-y': 1,
duration: .25
}],
onComplete() {
flag.classList.remove('active')
flag.animating = false
}
})
return
}
flagAudio.play()
to(flagPath, {
duration: 1.8,
ease: 'sine.out',
keyframes: new Array(2).fill([{
morphSVG: 'M7.66 16.75L2.25 1.99999C8 0.5 9.5 2.54999 14 0.799988C15.5 3.3 16.5 7.00001 16 8C11.5 10 9.5 9.58974 5.03377 9.58974'
}, {
morphSVG: 'M7.66 16.75L2.25 2.00001C9.5 4.50001 9 1 14.5 2C16 4.50001 16 8.00002 15.5 9.00001C10 10.5 9.5 9 5.03377 9.58976'
}, {
morphSVG: 'M7.66 16.75L2.25 2C7 2.75 9.5 1.50001 14 1.75C15.5 4.25001 16 8.00001 15.5 9C11 9 9.5 10.5 5.03377 9.58975'
}, {
morphSVG: 'M7.66 16.75L2.25 2C8 -0.249996 9.5 3.50001 14 1.75C15.5 4.25002 16 8.00002 15.5 9C11 11 9.5 8.50002 5.03377 9.58975'
}]).flat()
})
to(flag, {
'--flag-fill-percent': '150%',
duration: .25,
delay: .2,
clearProps: true,
onStart() {
set(flag, {
'--flag-fill-x': '1.5px',
'--flag-fill-y': '1.5px'
})
},
onComplete() {
flag.classList.add('active')
flag.animating = false
}
})
})
})
This Pen doesn't use any external CSS resources.