Welcoming Words Loader

Lightweight GSAP loader that cycles through a list of greeting words (e.g. Hello, Bonjour, Olá) before fading out. Words are defined in a single data attribute — no configuration needed in JavaScript.

gsaploadertextanimationgreeting

Setup — External Scripts

CDN — GSAP (add before </body>)
html
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/gsap.min.js"></script>

Code

HTML
html
<div data-loading-container class="loading-container">
  <div class="loading-screen">
    <div
      data-loading-words="Hello, Bonjour, स्वागत हे, Ciao, Olá, おい, Hallå, Guten tag, Hallo"
      class="loading-words"
    >
      <div class="loading-words__dot"></div>
      <p data-loading-words-target class="loading-words__word">Hello</p>
    </div>
  </div>
</div>
CSS
css
.loading-container {
  z-index: 500;
  pointer-events: none;
  position: fixed;
  inset: 0;
  overflow: hidden;
}

.loading-screen {
  pointer-events: auto;
  color: #fff;
  background-color: #000;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  display: flex;
  position: absolute;
  top: 0;
  left: 0;
}

.loading-words {
  grid-column-gap: 2em;
  grid-row-gap: 2em;
  align-items: center;
  display: flex;
  opacity: 0;
}

.loading-words__dot {
  background-color: #fff;
  border-radius: 50%;
  width: .75em;
  height: .75em;
}

.loading-words__word {
  font-size: 4.5em;
  font-weight: 500;
  line-height: 1;
  margin: 0;
}

@media screen and (max-width: 767px) {
  .loading-words {
    font-size: 2.75vw;
  }
}
JavaScript
javascript
function initWelcomingWordsLoader() {
  const loadingContainer = document.querySelector('[data-loading-container]');
  if (!loadingContainer) return;

  const loadingWords = loadingContainer.querySelector('[data-loading-words]');
  const wordsTarget = loadingWords.querySelector('[data-loading-words-target]');
  const words = loadingWords.getAttribute('data-loading-words').split(',').map(w => w.trim());

  const tl = gsap.timeline();

  tl.set(loadingWords, { yPercent: 50 });

  tl.to(loadingWords, {
    opacity: 1,
    yPercent: 0,
    duration: 1,
    ease: "Expo.easeInOut"
  });

  words.forEach(word => {
    tl.call(() => { wordsTarget.textContent = word; }, null, '+=0.15');
  });

  tl.to(loadingWords, {
    opacity: 0,
    yPercent: -75,
    duration: 0.8,
    ease: "Expo.easeIn"
  });

  tl.to(loadingContainer, {
    autoAlpha: 0,
    duration: 0.6,
    ease: "Power1.easeInOut"
  }, "-=0.2");
}

document.addEventListener('DOMContentLoaded', () => {
  initWelcomingWordsLoader();
});

Attributes

NameTypeDefaultDescription
[data-loading-container]attributeAdd to the outermost loader div. The script uses this as the main wrapper and fades it out at the end of the animation.
[data-loading-words]attributeAdd to the words container. Set its value to a comma-separated list of words or phrases — e.g. "Hello, Bonjour, Olá". The script splits this string and cycles through each entry.
[data-loading-words-target]attributeAdd to the child element that displays the current word. The script injects each word from the list into this element in sequence using textContent.

Notes

  • Requires GSAP loaded via CDN before the script runs. No additional plugins needed.
  • Add as many words as you like to the data-loading-words attribute — the timing per word is fixed at 0.15s between each swap.
  • The initial text content of [data-loading-words-target] is replaced immediately by the first word in the list. It is only there for a visual fallback.
  • The loader fades out automatically after cycling through all words. No manual trigger or page-ready callback is needed.