How to build a looping word section in Elementor with GSAP

SHARE

SIGN UP FOR THE NEWSLETTER

Your subscription could not be saved. Please try again.
Your subscription has been successful.


Code:

Javascript/GSAP

<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>

<script>

document.addEventListener('DOMContentLoaded', function() {
  const wordList = document.querySelector('[data-looping-words-list]');
  const words = Array.from(wordList.children);
  const totalWords = words.length;
  const wordHeight = 100 / totalWords; // Offset as a percentage
  const edgeElement = document.querySelector('[data-looping-words-selector]');
  let currentIndex = 0;
  function updateEdgeWidth() {
    const centerIndex = (currentIndex + 1) % totalWords;
    const centerWord = words[centerIndex];
    const centerWordWidth = centerWord.getBoundingClientRect().width;
    const listWidth = wordList.getBoundingClientRect().width;
    const percentageWidth = (centerWordWidth / listWidth) * 100;
    gsap.to(edgeElement, {
      width: `${percentageWidth}%`,
      duration: 0.5,
      ease: 'Expo.easeOut',
    });
  }
  function moveWords() {
    currentIndex++;
    gsap.to(wordList, {
      yPercent: -wordHeight * currentIndex,
      duration: 1.2,
      ease: 'elastic.out(1, 0.85)',
      onStart: updateEdgeWidth,
      onComplete: function() {
        if (currentIndex >= totalWords - 3) {
          wordList.appendChild(wordList.children[0]);
          currentIndex--;
          gsap.set(wordList, { yPercent: -wordHeight * currentIndex });
          words.push(words.shift());
        }
      }
    });
  }
  updateEdgeWidth();
  gsap.timeline({ repeat: -1, delay: 1 })
    .call(moveWords)
    .to({}, { duration: 2 })
    .repeat(-1);
});

</script>

CSS


.clonable {
  padding: 1.5em;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  display: flex;
  position: relative;
}

.looping-words {
  height: 3em;
  font-size: 11vw;
  line-height: .9;
  position: relative;
}

.looping-words__list {
  text-align: center;
  text-transform: uppercase;
}

.looping-words__edge {
  border-top: .045em solid red;
  border-left: .045em solid red;
  width: .25em;
  height: .25em;
  position: absolute;
  top: 0;
  left: 0;
}

.looping-words__edge.is_2 {
  left: auto;
  right: 0;
  transform: rotate(90deg);
}

.looping-words__edge.is_3 {
  inset: auto 0 0 auto;
  transform: rotate(180deg);
}

.looping-words__edge.is_4 {
  top: auto;
  bottom: 0;
  transform: rotate(270deg);
}

.looping-words__containers {
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;
}

.looping-words__p {
  margin: 0;
}

  



Video:

SIGN UP FOR THE NEWSLETTER

Your subscription could not be saved. Please try again.
Your subscription has been successful.