Get the finished version

Want your website to look more impressive? Import all my designs including this one:

Build it manually from scratch:

All materials:

Download Images:

Classes:

ffy-root

ffy-frame

ffy-slide ffy-slide-0

ffy-word

ffy-bowl

Red:
#8B0024
#C90035

Purple:
#25003D
#7A16C7

Yellow:
#A86A00
#F0B800

Green:
#01451F
#3F9418

CSS:

				
					<!--
  ================================================================
  Freshify Smoothie Slider
  ================================================================
  A 2-slide GSAP-powered carousel built inside Elementor.

  Controls:
    .ffy-prev / .ffy-next  → arrow navigation
    Mouse wheel / trackpad → next or previous slide
    Keyboard ← / →         → prev / next slide
    Touch swipe            → horizontal or vertical swipe (>50 px)

  Requires: GSAP 3.x
  ================================================================
-->

<style>
/* ================================================================
   CSS — layout helpers & animation overrides
   ================================================================ */

.ffy-root.elementor-element {
  --ffy-in: #7078A6;
  --ffy-out: #2E2951;

  background: linear-gradient(
    270deg,
    var(--ffy-in) 0%,
    var(--ffy-out) 100%
  ) !important;

  background-color: transparent !important;
}

.ffy-frame {
  container-type: inline-size;
}

.ffy-nav {
  transform: translateX(-50%);
}

.ffy-word .elementor-heading-title {
  white-space: nowrap;
}

.ffy-bowl img {
  filter: drop-shadow(0 3.2cqw 3.6cqw rgba(0, 0, 0, 0.45));
}

.ffy-ing,
.ffy-ing .elementor-widget-container,
.ffy-title,
.ffy-desc {
  transition: none !important;
  animation: none !important;
}

.ffy-ing img {
  display: block;
  width: 100%;
  height: auto;
  transition: none !important;
  animation: none !important;
  transform-origin: center center;
  will-change: transform, opacity;
}

.ffy-title .elementor-heading-title,
.ffy-desc {
  transform-origin: left bottom;
  will-change: transform, opacity;
}

.ffy-arrow.is-disabled {
  opacity: 0.35;
  pointer-events: none;
}

.ffy-script,
.ffy-script .elementor-widget-container {
  position: absolute !important;
  width: 0 !important;
  height: 0 !important;
  overflow: hidden !important;
  padding: 0 !important;
  margin: 0 !important;
  border: 0 !important;
}

/*
  Keep the slider full-screen and prevent normal page scrolling.
  Scrolling is instead used to change slides.
*/
html,
body.elementor-page-41 {
  overflow: hidden !important;
  height: 100% !important;
}
</style>

<!-- GSAP animation library -->
<script data-minify="1" src="https://nicolaipalmkvist.com/wp-content/cache/min/1/npm/gsap@3.12.5/dist/gsap.min.js?ver=1785936672"></script>

<script>
(function () {
  'use strict';

  /* ==============================================================
     Module-level state
     ============================================================== */

  var tries = 0;
  var idleTweens = [];


  /* ==============================================================
     Helper functions
     ============================================================== */

  function ingImgs(slide) {
    return [].slice.call(slide.querySelectorAll('.ffy-ing img'));
  }

  function infoEls(slide) {
    return [
      slide.querySelector('.ffy-title .elementor-heading-title'),
      slide.querySelector('.ffy-desc')
    ].filter(Boolean);
  }

  function killIdle() {
    idleTweens.forEach(function (t) {
      t.kill();
    });

    idleTweens = [];
  }

  function resetIng(imgs, visible) {
    gsap.set(
      imgs,
      visible
        ? {
            opacity: 1,
            scale: 1,
            x: 0,
            rotation: 0,
            y: 0
          }
        : {
            opacity: 0,
            scale: 0.3,
            x: 0,
            rotation: 0,
            y: 0
          }
    );
  }

  function resetInfo(els, visible) {
    gsap.set(
      els,
      visible
        ? {
            opacity: 1,
            y: 0,
            visibility: 'visible'
          }
        : {
            opacity: 0,
            y: 30,
            visibility: 'hidden'
          }
    );
  }

  function startIdle(imgs) {
    if (
      window.matchMedia('(prefers-reduced-motion: reduce)').matches
    ) {
      return;
    }

    imgs.forEach(function (img, j) {
      idleTweens.push(
        gsap.to(img, {
          y: j % 2 ? 8 : -8,
          rotation: j % 2 ? 4 : -4,
          duration: 2.6 + j * 0.4,
          ease: 'sine.inOut',
          yoyo: true,
          repeat: -1,
          delay: j * 0.3
        })
      );
    });
  }


  /* ==============================================================
     init() — main setup
     ============================================================== */

  function init() {

    /* Skip inside the Elementor editor */
    if (
      document.body.classList.contains('elementor-editor-active')
    ) {
      return;
    }

    /* Wait for GSAP to load */
    if (typeof gsap === 'undefined') {
      if (tries++ < 50) {
        return setTimeout(init, 100);
      }

      return;
    }

    var root = document.querySelector('.ffy-root');

    if (!root) {
      return;
    }


    /* ----------------------------------------------------------
       Collect slide elements
       ---------------------------------------------------------- */

    var SLIDES = 2;
    var slides = [];

    for (var i = 0; i < SLIDES; i++) {
      slides.push(
        root.querySelector('.ffy-slide-' + i)
      );
    }

    if (slides.indexOf(null) > -1) {
      return;
    }

    var words = slides.map(function (slide) {
      return slide.querySelector(
        '.ffy-word .elementor-heading-title'
      );
    });

    var bowls = slides.map(function (slide) {
      return slide.querySelector('.ffy-bowl img');
    });

    var ings = slides.map(ingImgs);
    var infos = slides.map(infoEls);

    var prevBtn = root.querySelector('.ffy-prev');
    var nextBtn = root.querySelector('.ffy-next');


    /* ----------------------------------------------------------
       Background colors
       ---------------------------------------------------------- */

    var PAL = [
      ['#8B0024', '#C90035'],
      ['#25003D', '#7A16C7']
    ];


    /* ----------------------------------------------------------
       Runtime state
       ---------------------------------------------------------- */

    var current = 0;
    var animating = false;

    var reduced = window
      .matchMedia('(prefers-reduced-motion: reduce)')
      .matches;

    var DUR = reduced ? 0.01 : 1.1;
    var SLIDE = 'power3.inOut';

    var bg = {
      inner: PAL[0][0],
      outer: PAL[0][1]
    };

    /*
      Wheel controls.
    */
    var wheelAmount = 0;
    var wheelLocked = false;
    var wheelUnlockTimer = null;

    var WHEEL_THRESHOLD = 35;
    var WHEEL_COOLDOWN = 850;


    /* ----------------------------------------------------------
       Background
       ---------------------------------------------------------- */

    function applyBg() {
      root.style.setProperty(
        '--ffy-in',
        bg.inner
      );

      root.style.setProperty(
        '--ffy-out',
        bg.outer
      );

      root.style.background =
        'linear-gradient(270deg, ' +
        bg.inner +
        ' 0%, ' +
        bg.outer +
        ' 100%)';
    }


    /* ----------------------------------------------------------
       Layer management
       ---------------------------------------------------------- */

    function setLayers(active, entering) {
      slides.forEach(function (slide, j) {
        if (
          entering !== undefined &&
          (j === active || j === entering)
        ) {
          slide.style.zIndex =
            j === entering ? '13' : '12';
        } else {
          slide.style.zIndex =
            j === active ? '12' : '5';
        }

        slide.style.pointerEvents =
          j === active && !animating
            ? 'auto'
            : 'none';
      });
    }


    /* ----------------------------------------------------------
       Initial state
       ---------------------------------------------------------- */

    setLayers(current);

    bg.inner = PAL[current][0];
    bg.outer = PAL[current][1];

    applyBg();

    words.forEach(function (element, index) {
      gsap.set(element, {
        xPercent: index === current ? 0 : 120,
        opacity: index === current ? 1 : 0
      });
    });

    bowls.forEach(function (element, index) {
      gsap.set(element, {
        xPercent: index === current ? 0 : 160,
        rotation: index === current ? 0 : 120
      });
    });

    infos.forEach(function (elements, index) {
      resetInfo(
        elements,
        index === current
      );
    });

    ings.forEach(function (images, index) {
      resetIng(
        images,
        index === current
      );
    });

    startIdle(ings[current]);


    /* ----------------------------------------------------------
       Arrow states
       ---------------------------------------------------------- */

    function updateArrows() {
      if (prevBtn) {
        prevBtn.classList.toggle(
          'is-disabled',
          current === 0
        );
      }

      if (nextBtn) {
        nextBtn.classList.toggle(
          'is-disabled',
          current === SLIDES - 1
        );
      }
    }


    /* ----------------------------------------------------------
       Slide transition
       ---------------------------------------------------------- */

    function goTo(next, dir) {
      if (
        animating ||
        next === current ||
        next < 0 ||
        next >= SLIDES
      ) {
        return false;
      }

      animating = true;

      killIdle();

      var prev = current;

      current = next;

      updateArrows();

      var outImgs = ings[prev];
      var inImgs = ings[next];

      var outInfo = infos[prev];
      var inInfo = infos[next];

      gsap.killTweensOf(outImgs);
      gsap.killTweensOf(inImgs);
      gsap.killTweensOf(outInfo);
      gsap.killTweensOf(inInfo);

      gsap.set(inImgs, {
        opacity: 0,
        scale: 0.3,
        x: 60 * dir,
        rotation: 0,
        y: 0
      });

      gsap.set(inInfo, {
        opacity: 0,
        y: 30,
        visibility: 'visible'
      });

      setLayers(prev, next);

      var tl = gsap.timeline({
        onComplete: function () {
          animating = false;

          gsap.set(words[prev], {
            opacity: 0
          });

          gsap.set(bowls[prev], {
            xPercent: 160 * dir,
            rotation: 120 * dir
          });

          resetIng(outImgs, false);
          resetIng(inImgs, true);

          infos.forEach(function (elements, index) {
            resetInfo(
              elements,
              index === current
            );
          });

          setLayers(current);
          startIdle(inImgs);
        }
      });


      /* Background */
      tl.to(
        bg,
        {
          inner: PAL[next][0],
          outer: PAL[next][1],
          duration: DUR,
          ease: SLIDE,
          onUpdate: applyBg
        },
        0
      );


      /* Giant background word */
      tl.fromTo(
        words[prev],
        {
          xPercent: 0,
          opacity: 1
        },
        {
          xPercent: -120 * dir,
          opacity: 1,
          duration: DUR,
          ease: SLIDE
        },
        0
      );

      tl.fromTo(
        words[next],
        {
          xPercent: 120 * dir,
          opacity: 1
        },
        {
          xPercent: 0,
          duration: DUR,
          ease: SLIDE
        },
        0
      );


      /* Smoothie bowl */
      tl.fromTo(
        bowls[prev],
        {
          xPercent: 0,
          rotation: 0
        },
        {
          xPercent: -160 * dir,
          rotation: -120 * dir,
          duration: DUR,
          ease: SLIDE
        },
        0
      );

      tl.fromTo(
        bowls[next],
        {
          xPercent: 160 * dir,
          rotation: 120 * dir
        },
        {
          xPercent: 0,
          rotation: 0,
          duration: DUR,
          ease: SLIDE
        },
        0
      );


      /* Outgoing ingredients */
      tl.to(
        outImgs,
        {
          opacity: 0,
          scale: 0.3,
          x: 0,
          rotation: 0,
          y: 0,
          duration: 0.25,
          ease: 'power2.in',
          stagger: 0.04,
          overwrite: 'auto'
        },
        0
      );


      /* Incoming ingredients */
      tl.to(
        inImgs,
        {
          opacity: 1,
          scale: 1,
          x: 0,
          rotation: 0,
          y: 0,
          duration: 0.38,
          ease: 'power3.out',
          stagger: 0.05,
          overwrite: 'auto'
        },
        0.32
      );


      /* Outgoing title and description */
      tl.to(
        outInfo,
        {
          opacity: 0,
          y: -24,
          duration: 0.35,
          ease: 'power2.in',
          overwrite: 'auto'
        },
        0
      );


      /* Incoming title and description */
      tl.to(
        inInfo,
        {
          opacity: 1,
          y: 0,
          duration: 0.45,
          ease: 'power3.out',
          overwrite: 'auto'
        },
        0.55
      );

      return true;
    }


    /* ----------------------------------------------------------
       Navigation functions
       ---------------------------------------------------------- */

    function nextS() {
      return goTo(
        current + 1,
        1
      );
    }

    function prevS() {
      return goTo(
        current - 1,
        -1
      );
    }

    function onArrow(event) {
      event.preventDefault();
      event.stopPropagation();
    }


    /* ----------------------------------------------------------
       Arrow navigation
       ---------------------------------------------------------- */

    if (nextBtn) {
      nextBtn.addEventListener(
        'click',
        function (event) {
          onArrow(event);
          nextS();
        }
      );
    }

    if (prevBtn) {
      prevBtn.addEventListener(
        'click',
        function (event) {
          onArrow(event);
          prevS();
        }
      );
    }


    /* ----------------------------------------------------------
       Navigation links
       ---------------------------------------------------------- */

    root
      .querySelectorAll('.ffy-nav-btn a')
      .forEach(function (link) {
        link.addEventListener(
          'click',
          function (event) {
            event.preventDefault();
          }
        );
      });


    /* ----------------------------------------------------------
       Keyboard navigation
       ---------------------------------------------------------- */

    document.addEventListener(
      'keydown',
      function (event) {
        if (event.key === 'ArrowRight') {
          nextS();
        }

        if (event.key === 'ArrowLeft') {
          prevS();
        }

        if (event.key === 'ArrowDown') {
          event.preventDefault();
          nextS();
        }

        if (event.key === 'ArrowUp') {
          event.preventDefault();
          prevS();
        }
      }
    );


    /* ----------------------------------------------------------
       Scroll wheel and trackpad navigation
       ---------------------------------------------------------- */

    function unlockWheel() {
      wheelAmount = 0;
      wheelLocked = false;
    }

    function lockWheel() {
      wheelLocked = true;

      clearTimeout(wheelUnlockTimer);

      wheelUnlockTimer = setTimeout(
        unlockWheel,
        WHEEL_COOLDOWN
      );
    }

    function onWheel(event) {
      event.preventDefault();

      if (wheelLocked || animating) {
        return;
      }

      if (
        wheelAmount !== 0 &&
        Math.sign(event.deltaY) !== Math.sign(wheelAmount)
      ) {
        wheelAmount = 0;
      }

      wheelAmount += event.deltaY;

      if (
        Math.abs(wheelAmount) < WHEEL_THRESHOLD
      ) {
        return;
      }

      if (wheelAmount > 0) {
        if (current < SLIDES - 1) {
          lockWheel();
          nextS();
        } else {
          wheelAmount = 0;
        }
      } else {
        if (current > 0) {
          lockWheel();
          prevS();
        } else {
          wheelAmount = 0;
        }
      }
    }

    window.addEventListener(
      'wheel',
      onWheel,
      {
        passive: false
      }
    );


    /* ----------------------------------------------------------
       Touch navigation
       ---------------------------------------------------------- */

    var touchX = null;
    var touchY = null;

    root.addEventListener(
      'touchstart',
      function (event) {
        touchX = event.touches[0].clientX;
        touchY = event.touches[0].clientY;
      },
      {
        passive: true
      }
    );

    root.addEventListener(
      'touchend',
      function (event) {
        if (
          touchX === null ||
          touchY === null
        ) {
          return;
        }

        var dx =
          event.changedTouches[0].clientX - touchX;

        var dy =
          event.changedTouches[0].clientY - touchY;

        if (
          Math.abs(dx) > Math.abs(dy) &&
          Math.abs(dx) > 50
        ) {
          if (dx < 0) {
            nextS();
          } else {
            prevS();
          }
        } else if (
          Math.abs(dy) > 50
        ) {
          if (dy < 0) {
            nextS();
          } else {
            prevS();
          }
        }

        touchX = null;
        touchY = null;
      },
      {
        passive: true
      }
    );


    /* ----------------------------------------------------------
       Finish setup
       ---------------------------------------------------------- */

    updateArrows();

  }


  /* ==============================================================
     Boot
     ============================================================== */

  if (document.readyState === 'loading') {
    document.addEventListener(
      'DOMContentLoaded',
      init
    );
  } else {
    init();
  }

})();
</script>
				
			

Unlock your best work yet

Launch premium websites and save hours on every project.

All Access — 12 Months

One-time payment. Access for 12 months. Instant access. 

$199

$259

All access — Lifetime

Most people choose

One-time payment. Never pay again.
Instant access.

$249

$459