<button id="js-btn" class="btn btn-green btn-lg">
<span class="text">Submit</span>
<div class="timer">
<svg id="js-timer" viewBox="0 0 120 120" xmlns='http://www.w3.org/2000/svg'><circle cx="60" cy="60" r="55"/></svg>
</div>
<div class="icon-success"><svg viewBox="0 0 50 45" xmlns='http://www.w3.org/2000/svg'><path d="M20,42 L3, 25"/><path d="M20,42 L47,3"/></svg></div>
</button>
<button id="js-reset" class="btn btn-sm btn-black top-left">Reset</button>
<!-- https://uimovement.com/ui/2380/submit-button/ -->
$green: #2BCB96
$gray: #BBBBBB
$btn_w: 380px
$btn_h: 120px
$timer_w: $btn_h
$success_w: 50px
$success_h: 45px
/* -------------------------------- resets */
body, button, div, span, svg
margin: 0
padding: 0
box-sizing: border-box
/* --------------------------- base styles */
body
display: flex
align-items: center
justify-content: center
width: 100vw
height: 100vh
svg
width: 100%
height: 100%
/* ------------------------------- buttons */
.btn
position: relative
display: flex
align-items: center
justify-content: center
margin-bottom: 50px
font-family: 'Work Sans', sans-serif
transition: all .5s ease-in-out
outline: none
.btn-lg
width: $btn_w
height: $btn_h
border: 5px solid
border-radius: $btn_h/2
font-size: 30px
font-weight: 600
letter-spacing: 1.5px
.btn-sm
width: 100px
height: 40px
border: none
border-radius: 3px
font-size: 16px
.btn-green
color: $green
background: white
border-color: $green
&:hover
color: white
background: $green
.btn-black
color: white
background: darkgray
&:hover
background: black
/* --------------------------------- timer */
.timer
position: absolute
left: calc(50% - #{$timer_w}/2)
width: $timer_w
height: $timer_w
opacity: 0
svg
fill: none
stroke: $green
stroke-width: 10px
transform: rotate(-.25turn)
transform-origin: center center
stroke-dasharray: 383
stroke-dashoffset: 383
transition: stroke-dashoffset .3s ease-in-out
/* -------------------------- icon success */
.icon-success
position: absolute
top: 35px
left: calc(50% - #{$success_w}/2)
width: $success_w
height: $success_h
border: black
svg
fill: none
stroke: white
stroke-width: 6px
stroke-linecap: round
stroke-dasharray: 50
stroke-dashoffset: 50
transition: stroke-dashoffset .2s .2s linear
opacity: 0
/* ------------------------- button states */
/* ----------------------- do submit */
.do-submit
color: white
background: $green
border-color: $green
animation: closeButton .3s .3s ease-in forwards
.text
animation: hideText .3s forwards
.timer
transition: opacity .1s .6s linear
opacity: 1
z-index: 1
/* -------------------------- succes */
.success
border-color: $green
animation: openButton .3s ease-in forwards
.timer
opacity: 0
transition: opacity .01s linear
.icon-success svg
opacity: 1
stroke-dashoffset: 0
/* --------------------------- reset */
.reset
animation: resetButton .5s ease-in forwards
.icon-success
opacity: 0
.text
animation: showText .8s ease-in forwards
/* ----------------------------- keyframes */
@keyframes closeButton
90%
width: $timer_w
height: $timer_w
background: white
border-width: 10px
border-color: $gray
100%
width: $timer_w
height: $timer_w
background: white
border-width: 10px
border-color: $gray
border-radius: 50%
@keyframes openButton
from
width: $timer_w
height: $timer_w
background: white
border-color: $green
border-width: 10px
border-radius: 50%
90%
width: $btn_w
height: $btn_h
background: $green
border-width: 5px
100%
width: $btn_w
height: $btn_h
background: $green
border-color: $green
border-width: 5px
border-radius: $btn_h/2
@keyframes resetButton
to
background: white
color: $green
@keyframes hideText
from
opacity: 1
transform: scaleX(1)
20%
transform: scaleX(1.1)
40%
opacity: 1
transform: scaleX(1)
to
opacity: 0
@keyframes showText
from
opacity: 0
to
opacity: 1
/* ----------------------- utility classes */
.top-left
position: absolute
top: 30px
left: 20px
View Compiled
var button = document.getElementById('js-btn'),
timer = document.getElementById('js-timer'),
reset = document.getElementById('js-reset');
button.addEventListener('click', doSubmit);
reset.addEventListener('click', resetButton);
function doSubmit() {
if (button.classList.contains('do-submit')) { return; }
// do clicked animation
button.classList.add('do-submit');
// TODO handle submit, should return amountLoaded
// manually feed amountLoaded as if receiving 0-100% values
setTimeout(function() {
doTimer(0);
}, 1200);
setTimeout(function() {
doTimer(15);
}, 1200);
setTimeout(function() {
doTimer(75);
}, 2000);
setTimeout(function() {
doTimer(100);
}, 2800);
}
function doTimer(amountLoaded) {
timer.style.strokeDashoffset = 3.83 * (100 - amountLoaded) + 'px';
if (amountLoaded === 100) {
setTimeout(function() {
button.classList.add('success');
}, 500);
}
}
function resetButton() {
// reset button classes
button.classList.add('reset');
setTimeout(function() {
button.classList.remove('success');
button.classList.remove('do-submit');
button.classList.remove('reset');
}, 500);
// reset timer animation
timer.style.strokeDashoffset = '383px';
// reset timer counter
time = 110;
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.