VibeCoderzVibeCoderz
Telegram
All Prompts
Karaoke-Style Animated Headline Section preview
herosectionanimatedheadlinetexttailwindinteractive

Karaoke-Style Animated Headline Section

Секция с анимированным заголовком: слова появляются поочередно при скролле. Идеально для интро и миссии бренда. Tailwind CSS.

Prompt

<section class="md:px-12 bg-white pt-32 pr-6 pb-32 pl-6">
  <div class="text-center max-w-5xl mr-auto ml-auto">

    <style>
      .k-word {
        opacity: 0.2;
        transition: opacity 0.25s ease;
        display: inline-block;
      }

      .k-word.active {
        opacity: 1;
      }
    </style>

    <span class="inline-block text-neutral-400 text-xs font-medium tracking-[0.2em] uppercase mb-8">
      [ The Collective ]
    </span>

    <h2 class="karaoke-container text-2xl md:text-4xl leading-tight font-normal text-neutral-800 mb-10 tracking-tight">
      We are a collective of dermatologists and designers obsessed with clarity. Rejecting the noise of the industry,
      we engineer solutions that blend clinical precision with botanical purity to
      <span class="italic text-neutral-400 font-serif">nourish and transcend</span>.
    </h2>

    <p class="text-xs text-neutral-400 uppercase tracking-widest mt-12">
      Welcome to the new standard
    </p>

    <script>
      (function () {
        const container = document.querySelector('.karaoke-container');
        if (!container || container.dataset.processed) return;

        const wrapWords = (node) => {
          if (node.nodeType === 3) {
            const words = node.textContent.match(/\S+|\s+/g) || [];
            const fragment = document.createDocumentFragment();

            words.forEach((word) => {
              if (word.trim().length > 0) {
                const span = document.createElement('span');
                span.textContent = word;
                span.className = 'k-word';
                fragment.appendChild(span);
              } else {
                fragment.appendChild(document.createTextNode(word));
              }
            });

            node.replaceWith(fragment);
          } else if (node.nodeType === 1) {
            Array.from(node.childNodes).forEach(wrapWords);
          }
        };

        Array.from(container.childNodes).forEach(wrapWords);
        container.dataset.processed = 'true';

        const observer = new IntersectionObserver(
          (entries) => {
            entries.forEach((entry) => {
              if (entry.isIntersecting) {
                const words = container.querySelectorAll('.k-word');

                words.forEach((word, index) => {
                  setTimeout(() => {
                    word.classList.add('active');
                  }, index * 40); // speed of the karaoke effect
                });

                observer.unobserve(container);
              }
            });
          },
          { threshold: 0.2 }
        );

        observer.observe(container);
      })();
    </script>
  </div>
</section>
All Prompts