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

  1. Russellveilk Avatar

    Your comment is awaiting moderation.

    Нейросетевые поисковые системы для поиска информации становятся всё более удобными.
    Они помогают изучать доступные данные из интернета.
    Такие решения применяются для журналистики.
    Они способны оперативно систематизировать большие объёмы информации.
    бот глаз бога в телеграмм
    Это позволяет получить более точную картину событий.
    Отдельные системы также включают удобные отчёты.
    Такие сервисы популярны среди исследователей.
    Совершенствование технологий превращает поиск информации более точным и наглядным.

Leave a Reply

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