Skip to content

Instantly share code, notes, and snippets.

@clqu
Last active August 26, 2022 09:07
Show Gist options
  • Save clqu/72fe23b410e4e29b47998a5f29712f4c to your computer and use it in GitHub Desktop.
Save clqu/72fe23b410e4e29b47998a5f29712f4c to your computer and use it in GitHub Desktop.
HTML5 Animated Tabs with TailwindCSS
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML Animated Tabs</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body>
<div class="tabs-group">
<div class="tabs-container">
<div class="tabs">
<p>Tab 1</p>
</div>
<div class="tabs">
<p>Tab 2</p>
</div>
<div class="tabs">
<p>Tab 3</p>
</div>
<div class="indicator"></div>
</div>
<div class="tab-content">
<div class="tab-content-item">
<p>Tab 1 Content</p>
</div>
<div class="tab-content-item">
<p>Tab 2 Content</p>
</div>
<div class="tab-content-item">
<p>Tab 3 Content</p>
</div>
</div>
</div>
<script>
const allTabsGroup = document.querySelectorAll(".tabs-group");
allTabsGroup.forEach((tabsGroup) => {
for (let i = 0; i < tabsGroup.children.length; i++) {
const tabs = tabsGroup.children[i].querySelectorAll('.tabs');
const tabContent = tabsGroup.children[i].querySelectorAll('.tab-content-item');
const indicator = tabsGroup.children[i].querySelector('.indicator');
const tabsContainer = tabsGroup.children[0];
const content = tabsGroup.children[1].querySelectorAll('.tab-content-item');
if (indicator) {
indicator.classList.add('bg-blue-500', 'h-0.5', 'absolute', 'bottom-0', 'left-0', 'transition-all', 'duration-200');
indicator.style.width = `${100 / tabs.length}%`;
}
if (tabsContainer) {
tabsContainer.classList.add('relative', 'flex', 'flex-row', 'items-center', 'justify-center');
}
if (content) {
content.forEach((item) => {
item.classList.add('hidden', 'relative');
});
content[0].classList.remove('hidden');
}
const updateContent = (old, index) => {
let oldContent = content[old / 100];
let newContent = content[index];
if ((old / 100) === index) return;
if (oldContent && newContent) {
oldContent.classList.add('absolute', 'opacity-0', 'transition-all', 'duration-200');
newContent.classList.add('absolute', 'opacity-0', 'transition-all', 'duration-200');
setTimeout(() => {
oldContent.classList.remove('absolute', 'opacity-0', 'transition-all', 'duration-200');
oldContent.classList.add('hidden');
newContent.classList.add('!opacity-100');
newContent.classList.remove('!left-0', '!opacity-100', 'absolute', 'opacity-0', 'transition-all', 'duration-200');
newContent.classList.remove('hidden');
}, 200);
}
}
tabs.forEach((tab, index) => {
tab.classList.add('p-4', 'text-center', 'w-full', 'cursor-pointer', 'transition-all', 'duration-200', 'hover:bg-gray-200');
tab.addEventListener('click', () => {
let old = (String(indicator.style.transform || 'translateX(0%)').split('translateX(')).filter(Boolean).join('').split('%)')[0];
indicator.style.transform = `translateX(${index * 100}%)`;
updateContent(old, index);
})
});
}
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment