All Prompts
All Prompts

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>