Mind-Blowing Cards to Button Scroll Effects in Elementor 🔥

 

Want to get this as ready made template with just 1 CLICK INSTALL?

I want it as Ready Template

 

Code Snippet for Scroll Effects:

<style>
body{
	--smooth-scroll: true;
}
.mdw-scroll-effect-143{
    --circle-size: 50;
}
.mdw-scroll-effect-143 .e-con{
	transition: 0s !important;
}
html:not(.elementor-html) .mdw-scroll-effect-143 .sticky{
    position: fixed;
    top: 0;
}
html:not(.elementor-html) .mdw-scroll-effect-143 .sticky-end{
    position: absolute;
    bottom: 0;
    top: auto !important;
}
.mdw-scroll-effect-143-top:before{
    background-size: auto 80%;
}
.mdw-scroll-effect-143-cards > .e-con{
    max-width: 220px;
    will-change: transform;
    transform: translate(calc(var(--tx,0px) - 50%), calc(var(--ty,0px) - 50%));
}
.mdw-scroll-effect-143-card-bg{
	height: 100%;
}
html.elementor-html .mdw-scroll-effect-143-card-bg{
    transform: none !important;
    left: 0 !important;
    top: 0 !important;
    height: 100% !important;
    width: 100% !important;
}
html.elementor-html .mdw-scroll-effect-143-bottom{
    position: relative !important;
}
html:not(.elementor-html) .mdw-scroll-effect-143-bottom{
    opacity: 0;
}
html:not(.elementor-html) .mdw-scroll-effect-143-bottom.mdw-show{
    opacity: 1;
}
html:not(.elementor-html) .mdw-scroll-effect-143-bottom .elementor-widget:not(.elementor-widget-button){
	will-change: transform, opacity;
	transform: translateY(-100px);
	opacity: 0;
}
.mdw-scroll-effect-143-bottom .elementor-widget-text-editor p:last-child{
    margin-bottom: 0;
}
.mdw-scroll-effect-143-button,
.mdw-scroll-effect-143-button .elementor-button,
.mdw-scroll-effect-143-button .elementor-button-text{
    transition: 0s !important;
}
.mdw-scroll-effect-143-button{
    display: flex;
    align-items: center;
    justify-content: center;
}
.mdw-scroll-effect-143-button > *:not(.mdw-scroll-effect-143-button-inner){
    z-index: 1;
}
.mdw-scroll-effect-143-button-inner{
    display: inline-block;
    position: absolute;
    height: 100%;
    width: 100%;
    border-radius: 50px;
    opacity: 0;
}
.mdw-scroll-effect-143-button a{
    outline: none;
}
@media(min-width: 768px){
html:not(.elementor-html) .mdw-scroll-effect-143-cards{
    pointer-events: none;
}
.mdw-tranparent{
    background: transparent !important;
    border-color: transparent !important;
}
}
@media(max-width: 767px){
.mdw-scroll-effect-143 > .e-con{
    position: relative !important;
    top: 0 !important;
    left: 0 !important;
}
.mdw-scroll-effect-143-top:before{
    background-size: auto 100% !important;
}
.mdw-scroll-effect-143-cards > .e-con{
    position: relative !important;
    top: unset !important;
    left: unset !important;
    opacity: 1 !important;
    transform: unset !important;
}
.mdw-scroll-effect-143-cards > .e-con,
.mdw-scroll-effect-143-cards > .e-con .elementor-widget-heading{
    opacity: 1 !important;
}
.mdw-scroll-effect-143-bottom{
    position: relative !important;
}
.mdw-scroll-effect-143-bottom .elementor-widget:not(.elementor-widget-button){
	transform: translateY(0) !important;
	opacity: 1 !important;
}
.mdw-scroll-effect-143-button{
    transform: none !important;
}
.mdw-scroll-effect-143-button .elementor-button-text{
    opacity: 1 !important;
}
.mdw-scroll-effect-143-button-inner{
    display: none;
}
}
</style>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script>
if (!MDWNonce143){
var MDWNonce143 = true
jQuery(document).ready(function($){

var selector = '.mdw-scroll-effect-143'

$(selector).each(function(){

var $this = $(this),
content = $this.find('.mdw-scroll-effect-143-top'),
cards = $this.find('.mdw-scroll-effect-143-cards > .e-con'),
cardBgs = $this.find('.mdw-scroll-effect-143-card-bg'),
bottom = $this.find('.mdw-scroll-effect-143-bottom'),
button = $this.find('.mdw-scroll-effect-143-button'),
windowHeight,
windowWidth,
cardStartDimensions = [],
cardTop = [],
cardLeft = [],
buttonStyles = {},
buttonMiddleDistance,
bgColors = [],
borderColors = [],
borderWidth = [],
borderRadius = [],
circleSize = parseFloat(getProp($this[0], '--circle-size')),
progress

function resetCards(){
    if(windowWidth < 768){
        cardBgs.each(function(){
            $(this).removeAttr('style')
        })
    }
}

function getProp(el, prop){
    return window.getComputedStyle(el).getPropertyValue(prop)
}

function getValues(){
    cardBgs.each(function(i){
        var cardBg = $(this)[0]
        bgColors[i] = getProp(cardBg, 'background-color')
        borderColors[i] = getProp(cardBg, 'border-color')
        borderWidth[i] = parseFloat(getProp(cardBg, 'border-width'))
        borderRadius[i] = parseFloat(getProp(cardBg, 'border-radius'))
    })
}

function setButonStyles(){
    var btn = button.find('.elementor-button')
    buttonStyles.width = button.outerWidth()
    buttonStyles.height = button.outerHeight()
    buttonStyles.bg = btn.css('background-color')
    buttonStyles.borderColor = btn.css('border-color')
    buttonStyles.border = parseFloat(btn.css('border').split(' ')[0])
    buttonStyles.borderRadius = parseFloat(btn.css('border-radius').split(' ')[0])
    btn.addClass('mdw-tranparent')
}

function updateValues(){
    windowHeight = $(window).height()
    windowWidth = $(window).width()
    cards.each(function(i){
        var card = $(this)
        cardStartDimensions.push({
            width: card.outerWidth(),
            height: card.outerHeight()
        })
    })
    butonTop = button[0].offsetTop + (button.outerHeight() / 2)
    buttonMiddleDistance = bottom.outerHeight() / 2 - butonTop
}

function setValues(){
    cardTop = []
    cardLeft = []
    cards.each(function(i){
        var top = parseFloat(getProp(this, 'top')),
        left = parseFloat(getProp(this, 'left'))
        cardTop[i] = top - (windowHeight / 2)
        cardLeft[i] = left - (windowWidth / 2)
    })
}

function setSticky(){
    var rect = $this[0].getBoundingClientRect(),
        inner = $this.children('.e-con:not(.mdw-scroll-effect-143-top)')

    if (windowWidth < 768){
        inner.removeClass('sticky sticky-end')
        return
    }
    rect.top <= 0 ? inner.addClass('sticky') : inner.removeClass('sticky')
    rect.bottom < windowHeight ? inner.addClass('sticky-end') : inner.removeClass('sticky-end')
}

function cahngeZIndex(){
    var start = 0.85
    if(progress <= start){
        bottom.css('z-index', 'unset')
        content.css('z-index', 10)
    }else{
        content.css('z-index', 'unset')
        bottom.css('z-index', 10)
    }
}

function animateCards(){
    var start = 0, end = 0.6
    if (progress >= start && progress <= end){
        var p = progress / (end - start)
        cards.each(function(i){
            var ty = (cardTop[i] * p) * -1,
                tx = (cardLeft[i] * p) * -1

            this.style.setProperty('--tx', tx + 'px')
            this.style.setProperty('--ty', ty + 'px')
        })
        cardBgs.each(function(i){
            var d = cardStartDimensions[i],
            w = d.width + (circleSize - d.width) * p,
            h = d.height + (circleSize - d.height) * p,
            br = borderRadius[i] + (buttonStyles.borderRadius - borderRadius[i]) * p,
            bw = borderWidth[i] + (buttonStyles.border - borderWidth[i]) * p
                
            $(this).css({
                width: w + 'px',
                height: h + 'px',
                borderRadius: br + 'px',
                borderWidth: bw + 'px'
            })
        })

        var featureElements = $this.find('.mdw-scroll-effect-143-cards > .e-con > .elementor-element:not(.mdw-scroll-effect-143-card-bg)'),
        start2 = 0,
        end2 = 0.1,
        startScale = 1,
        endScale = 0.9

        if(progress <= end2){
            var op = 1 - (progress / end2),
            scale = startScale + (progress - start2) * (endScale - startScale) / (end2 - start2)
            scale = Math.max(endScale, Math.min(1, scale))
            featureElements.css({ opacity: op, transform: `scale(${scale})` })
        }else{
            featureElements.css({ opacity: 0, transform: `scale(${endScale})` })
        }
    }
    cards.css('opacity', progress >= end ? 0 : 1)
}

function parseRGB(color){
    var m = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/)
    return m ? { r:+m[1], g:+m[2], b:+m[3] } : { r:0, g:0, b:0 }
}

function mixColor(from, to, t){
    return {
        r: from.r + (to.r - from.r) * t,
        g: from.g + (to.g - from.g) * t,
        b: from.b + (to.b - from.b) * t
    }
}

function animateCardColors(){
    var start = 0, end = 0.6,
    p = Math.min(Math.max(progress, start), end) / (end - start)
    
    cardBgs.each(function(i){
        var fromBg = parseRGB(bgColors[i]),
        toBg = parseRGB(buttonStyles.bg),
        cBg = mixColor(fromBg, toBg, p),
        fromB = parseRGB(borderColors[i]),
        toB = parseRGB(buttonStyles.borderColor),
        cBorder = mixColor(fromB, toB, p)
        
        $(this).css({
            backgroundColor: `rgb(${cBg.r},${cBg.g},${cBg.b})`,
            borderColor: `rgb(${cBorder.r},${cBorder.g},${cBorder.b})`
        })
    })
}

function animateBottom(){
    var bottomContent = $this.find('.mdw-scroll-effect-143-bottom .elementor-widget:not(.elementor-widget-button)'),
    buttonText = button.find('.elementor-button-text'),
    start = 0.85, end = 1,
    trY = -40,
    startTextScale = 0.9,
    endTextScale = 1,
    textScale = startTextScale + ( (progress - start) / (end - start) ) * (endTextScale - startTextScale)
        
    if(progress >= start){
        var p = (progress - start) / (end - start)
        bottomContent.css({
            transform: `translateY(${trY - (p * trY)}px)`,
            opacity: p
        })
        buttonText.css({'opacity': p, 'transform': `scale(${textScale})`})
    }else{
        bottomContent.css({
            transform: `translateY(${trY}px)`,
            opacity: 0
        })
        buttonText.css('opacity', 0)
    }
}

function animateButton(){
    var buttonInner = button.find('.mdw-scroll-effect-143-button-inner'),
    start = .6, end = 1
    buttonInner.css('opacity', progress >= start ? 1 : 0)

    if(progress >= start && progress <= end){
        var p = (progress - start) / (end - start),
        w = circleSize + (buttonStyles.width - circleSize) * p,
        h = circleSize + (buttonStyles.height - circleSize) * p,
        ty = buttonMiddleDistance * (1 - p)
        buttonInner.css({
            width: w + 'px',
            height: h + 'px'
        })
        button.css({
            transform: 'translate(0,' + ty + 'px)'
        })
    }else if(progress > end){
        buttonInner.css({
            width: buttonStyles.width + 'px',
            height: buttonStyles.height + 'px',
            transform: 'translate(0,0)'
        })
    }
}

function isMobileOrEditor(){
    return windowWidth < 768 || $('html').hasClass('elementor-html')
}

function runAnimation(){
    if (isMobileOrEditor()) return
    var wrapTop = $this.offset().top,
    scrollTop = $(window).scrollTop(),
    wrapHeight = $this.height()
    
    progress = (scrollTop - wrapTop) / (wrapHeight - windowHeight)
    progress = Math.max(0, Math.min(1, progress))
    
    cahngeZIndex()
    animateCards()
    animateCardColors()
    animateBottom()
    animateButton()
}

function init(){
    bottom.addClass('mdw-show')
    getValues()
    setButonStyles()
    button.append('<span class="mdw-scroll-effect-143-button-inner"></span>')
    setTimeout(function(){
        button.find('.mdw-scroll-effect-143-button-inner').css({
            backgroundColor: buttonStyles.bg,
            border: buttonStyles.border + 'px solid ' + buttonStyles.borderColor
        })
    },50)
}
function calculateLayout(){
    updateValues()
    setValues()
    setSticky()
    runAnimation()
}
function render(){
    setSticky()
    runAnimation()
}
$(window).on('load', function(){
    resetCards()
    if (isMobileOrEditor()) return
    init()
    calculateLayout()
})

$(window).on('resize', function(){
    resetCards()
    calculateLayout()
})

$(window).on('scroll', function(){
    render()
})
})
}) 
}
</script>

<!-- Smooth Scroll -->
<style>
html.lenis,
html.lenis body {
	height: auto;
}
.lenis.lenis-smooth {
	scroll-behavior: auto !important;
}
.lenis.lenis-smooth [data-lenis-prevent] {
	overscroll-behavior: contain;
}
.lenis.lenis-stopped {
	overflow: hidden;
}
.lenis.lenis-smooth iframe {
	pointer-events: none;
}
</style>
<script src="https://unpkg.com/lenis@1.1.11/dist/lenis.min.js"></script>
<script>
$(document).ready(function () {
	var smoothScroll = getComputedStyle(document.body).getPropertyValue('--smooth-scroll'),
		smoothScroll = smoothScroll && smoothScroll == 'true'

	if (true) {
		var lenis = new Lenis()
		function raf(time) {
			lenis.raf(time)
			requestAnimationFrame(raf)
		}
		requestAnimationFrame(raf)
	}
})
</script>