Smash to submit button

Smash to submit button developed using HTML, JavaScript and SCSS. This button from Aaron Iker really makes you work for it. Keep clicking and lifting to submit, you got this.

See the Pen Smash to submit button by Aaron Iker (@aaroniker) on CodePen.

Created on March 12, 2020 Updated on March 17, 2020. A Pen by Aaron Iker on CodePen. License.

<button class="button">
    <div class="inner">
        <div class="icon">
            <div class="person">
                <div class="arm"></div>
                <div class="arm right"></div>
                <div class="leg"></div>
                <div class="leg right"></div>
            </div>
            <div class="weight"></div>
        </div>
        <div class="text">
            <span>Smash to submit</span>
            <span>Yaay! Submitted.</span>
        </div>
    </div>
</button>
let confettiAmount = 100,
    confettiColors = [
        '#7d32f5',
        '#f6e434',
        '#63fdf1',
        '#e672da',
        '#295dfe',
        '#6e57ff'
    ],
    random = (min, max) => {
        return Math.floor(Math.random() * (max - min + 1) + min);
    },
    createConfetti = to => {
        let elem = document.createElement('i'),
            set = Math.random() < 0.5 ? -1 : 1;
        elem.style.setProperty('--x', random(-360, 360) + 'px');
        elem.style.setProperty('--y', random(-200, 200) + 'px');
        elem.style.setProperty('--r', random(0, 360) + 'deg');
        elem.style.setProperty('--s', random(.6, 1));
        elem.style.setProperty('--b', confettiColors[random(0, 5)]);
        to.appendChild(elem);
    };

document.querySelectorAll('.button').forEach(button => {

    let complete = false,
        timeline = gsap.timeline({
            paused: true,
            ease: 'none',
            onComplete() {
                complete = true;
                button.classList.add('complete');
                for(let i = 0; i < confettiAmount; i++) {
                    createConfetti(button);
                }
                setTimeout(() => {
                    button.classList.add('confetti');
                    setTimeout(() => button.querySelectorAll('i').forEach(i => i.remove()), 600);
                }, 300);
                // Reset
                setTimeout(() => {
                    button.classList.remove('complete', 'confetti');
                    complete = false;
                }, 2000);
            }
        }),
        up = 0;

    timeline.to(button, {
        keyframes: [{
            '--weight-y': -6,
            '--arm-rotate-s-x': 90,
            duration: .3
        }, {
            '--weight-y': -10,
            '--arm-rotate-s-x': 45,
            '--arm-rotate-s': 130,
            duration: .2
        }, {
            '--weight-y': -12,
            '--arm-rotate-s': 130,
            '--arm-rotate-s-x': 0,
            duration: .1
        }, {
            '--weight-y': -20,
            '--person-y': -4,
            '--arm-rotate': 100,
            '--arm-rotate-s': 90,
            '--leg-y': 0,
            '--leg-rotate': 20,
            '--leg-rotate-s': -20,
            duration: .2
        }, {
            '--weight-y': -25,
            '--arm-rotate': 150,
            '--arm-rotate-s': 30,
            duration: .2
        }]
    });

    button.addEventListener('click', e => {

        up = 1;

        const rippleDiv = document.createElement('div');

        rippleDiv.className = 'ripple';

        const boundingClientRect = button.getBoundingClientRect();

        button.style.setProperty('--ripple-x', e.clientX - boundingClientRect.left);
        button.style.setProperty('--ripple-y', e.clientY - boundingClientRect.top);

        button.querySelector('.inner').appendChild(rippleDiv);

        setTimeout(() => rippleDiv.remove(), 500);

    });

    setInterval(() => {

        up = up > 0 ? up - .1 : 0;

        let progress = timeline.progress(),
            direction = up > 0 ? 1 : -1.5;

        if(!complete) {
            timeline.progress(progress + .01 * direction);
        }

    }, 1000 / 60);

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.4/gsap.min.js"></script>
.button {
    --color: #F6F8FF;
    --background: #171827;
    --background-hover: #0D0F18;
    --shadow: #{rgba(#00093D, .12)};
    --person: #F6F8FF;
    --person-arm: var(--person);
    --person-leg: #D1D6EE;
    --weight: #275EFE;
    --weight-disk: #5C86FF;
    //
    --person-y: 0;
    --weight-y: 0;
    --arm-rotate: 40;
    --arm-rotate-s: -40;
    --arm-rotate-s-x: 0;
    --leg-y: -2;
    --leg-rotate: 45;
    --leg-rotate-s: -70;
    display: table;
    outline: none;
    border: none;
    background: none;
    padding: 0;
    position: relative;
    cursor: pointer;
    line-height: 24px;
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    -webkit-appearance: none;
    -webkit-tap-highlight-color: transparent;
    .inner {
        padding: 14px 20px;
        transition: transform .2s, background .4s;
        color: var(--color);
        position: relative;
        display: flex;
        z-index: 1;
        min-width: 190px;
        border-radius: 13px;
        background: var(--b, var(--background));
        box-shadow: 0 1px 3px var(--shadow), 0 3px 7px var(--shadow);
        transform: scale(var(--scale, 1)) translateZ(0);
        &:active {
            --scale: .95;
        }
        &:hover {
            --b: var(--background-hover);
        }
    }
    .icon {
        width: 24px;
        height: 24px;
        margin-right: 12px;
        display: block;
        position: relative;
        .person,
        .weight {
            position: absolute;
        }
        .person {
            top: 7px;
            left: 9px;
            width: 6px;
            height: 10px;
            transform: translateY(calc(var(--person-y) * 1px));
            &:before,
            &:after {
                content: '';
                position: absolute;
                left: 0;
            }
            &:before {
                top: -5px;
                width: 6px;
                height: 6px;
                border-radius: 50%;
                background: var(--person);
                transform: scale(.7);
                transform-origin: 50% 25%;
            }
            &:after {
                top: 0;
                right: 0;
                bottom: 0;
                z-index: 1;
                border-radius: 2px 2px 3px 3px;
                background: var(--person);
            }
            .arm,
            .leg {
                position: absolute;
                left: var(--left, 0);
                top: var(--top, 0);
                width: 2px;
                height: 7px;
                border-radius: 1px;
                transform-origin: 1px 1px;
                background: var(--background);
                transform: translate(calc(var(--x, 0) * 1px), calc(var(--y, 0) * 1px)) rotateZ(calc(var(--rotate, 0) * 1deg));
                &:before {
                    content: '';
                    position: absolute;
                    left: 0;
                    top: 5px;
                    width: 2px;
                    height: 7px;
                    border-radius: 1px;
                    transform-origin: 1px 1px;
                    background: inherit;
                    transform: rotateZ(calc(var(--rotate-s, 0) * 1deg)) rotateX(calc(var(--rotate-s-x, 0) * 1deg));
                }
                &.right {
                    --left: 4px;
                    transform: translate(calc(var(--x, 0) * -1px), calc(var(--y, 0) * 1px)) rotateZ(calc(var(--rotate, 0) * -1deg));
                    &:before {
                        transform: rotateZ(calc(var(--rotate-s, 0) * -1deg)) rotateX(calc(var(--rotate-s-x, 0) * 1deg));
                    }
                }
            }
            .arm {
                --background: var(--person-arm);
                --rotate: var(--arm-rotate);
                --rotate-s: var(--arm-rotate-s);
                --rotate-s-x: var(--arm-rotate-s-x);
                z-index: 1;
            }
            .leg {
                --top: 8px;
                --background: var(--person-leg);
                --y: var(--leg-y);
                --rotate: var(--leg-rotate);
                --rotate-s: var(--leg-rotate-s);
            }
        }
        .weight {
            top: 17px;
            left: 0;
            width: 24px;
            height: 2px;
            border-radius: 1px;
            background: var(--weight);
            transform: translateY(calc(var(--weight-y, 0) * 1px));
            &:before,
            &:after {
                content: '';
                position: absolute;
                border-radius: 1px;
                left: var(--l, 1px);
                top: var(--t, -2px);
                width: var(--w, 2px);
                height: var(--h, 6px);
                background: var(--weight-disk);
                box-shadow: var(--bx, 20px) 0 0 var(--weight-disk);
            }
            &:after {
                --l: 3px;
                --t: -3px;
                --h: 8px;
                --bx: 16px;
            }
        }
    }
    .text {
        position: relative;
        span {
            display: block;
            white-space: nowrap;
            opacity: var(--o, 1);
            transform: translateX(var(--x, 0));
            transition: transform .3s, opacity .2s;
            &:last-child {
                --o: 0;
                --x: 8px;
                position: absolute;
                left: 0;
                top: 0;
            }
        }
    }
    .ripple {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        overflow: hidden;
        border-radius: inherit;
        pointer-events: none;
        &:before {
            content: '';
            position: absolute;
            top: calc(var(--ripple-y, 0) * 1px);
            left: calc(var(--ripple-x, 0) * 1px);
            transform: translate(-50%, -50%) scale(0);
            opacity: 0;
            width: 200%;
            padding-bottom: 200%;
            border-radius: 50%;
            background: currentColor;
            animation: ripple .5s ease-in;
        }
    }
    i {
        position: absolute;
        display: block;
        width: 4px;
        height: 4px;
        top: 50%;
        left: 50%;
        margin: -2px 0 0 -2px;
        opacity: var(--o, 0);
        background: var(--b);
        transform: translate(var(--x), var(--y)) scale(var(--s, 1));
    }
    &.complete {
        .text {
            span {
                &:first-child {
                    --o: 0;
                    --x: -8px;
                }
                &:last-child {
                    --o: 1;
                    --x: 0;
                }
            }
        }
        &.confetti {
            i {
                animation: confetti .6s ease-out forwards;
            }
        }
    }
}

@keyframes confetti {
    from {
        transform: translate(0, 0);
        opacity: 1;
    }
}

@keyframes ripple {
    25% {
        opacity: .07;
    }
    100% {
        transform: translate(-50%, -50%) scale(1);
    }
}

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;
    font-family: 'Inter', Arial;
    justify-content: center;
    align-items: center;
    background: #E4ECFA;
    .dribbble {
        position: fixed;
        display: block;
        right: 20px;
        bottom: 20px;
        img {
            display: block;
            height: 28px;
        }
    }
    .twitter {
        position: fixed;
        display: block;
        right: 64px;
        bottom: 14px;
        svg {
            width: 32px;
            height: 32px;
            fill: #1da1f2;
        }
    }
}
<link href="https://fonts.googleapis.com/css?family=Inter:400,500,600,700&display=swap" rel="stylesheet" />
Categories:
W3TWEAKS
Latest posts by W3TWEAKS (see all)

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *