v0.1

UX
#95 - Confeti al clic
¡Haz volar un divertido confeti al hacer clic!
Auto‑switch horizontal tabs in Webflow as you scroll, locking the scroll inside the tab section.
Watch the video for step-by-step implementation instructions
<!-- 💙 MEMBERSCRIPT #162 v0.1 💙 - CHANGE HORIZONTAL TABS WHEN PAGE IS SCROLLED -->
<script>
(function() {
// Disable on tablet and funcmobile(only run on desktop ≥ 992px)
if (window.matchMedia('(max-width: 991px)').matches) return;
const tabSection = document.querySelector('[data-ms-code="tab-section"]');
if (!tabSection) return;
const tabButtons = Array.from(tabSection.querySelectorAll('[data-ms-code^="tab-"]'))
.filter(btn => !btn.hasAttribute('data-ms-code') || !btn.getAttribute('data-ms-code').startsWith('tab-content-'));
const tabContents = Array.from(tabSection.querySelectorAll('[data-ms-code^="tab-content-"]'));
if (!tabButtons.length || !tabContents.length) return;
let isLocked = true;
let isTouching = false;
let touchStartY = 0;
let lastTabChange = 0;
const cooldown = 500; // ms
function getCurrentTabIndex() {
return tabButtons.findIndex(btn => btn.classList.contains('w--current'));
}
function activateTab(index) {
if (index < 0 || index >= tabButtons.length) return;
tabButtons[index].click();
}
function isTabSectionInView() {
const rect = tabSection.getBoundingClientRect();
return rect.top < window.innerHeight && rect.bottom > 0;
}
function tryTabChange(direction, event) {
const now = Date.now();
if (now - lastTabChange < cooldown) return;
let currentTab = getCurrentTabIndex();
if (direction > 0 && currentTab < tabButtons.length - 1) {
event.preventDefault();
activateTab(currentTab + 1);
isLocked = true;
} else if (direction < 0 && currentTab > 0) {
event.preventDefault();
activateTab(currentTab - 1);
isLocked = true;
} else {
isLocked = false;
const rect = tabSection.getBoundingClientRect();
window.scrollBy({
top: direction > 0 ? rect.bottom - 1 : rect.top - window.innerHeight + 1,
left: 0,
behavior: 'smooth'
});
}
lastTabChange = now;
}
function onWheel(e) {
if (!isTabSectionInView()) return;
if (e.deltaY > 0) {
tryTabChange(1, e);
} else if (e.deltaY < 0) {
tryTabChange(-1, e);
}
}
function onTouchStart(e) {
if (!isTabSectionInView()) return;
isTouching = true;
touchStartY = e.touches[0].clientY;
}
function onTouchMove(e) {
if (!isTabSectionInView() || !isTouching) return;
const now = Date.now();
if (now - lastTabChange < cooldown) return;
const deltaY = touchStartY - e.touches[0].clientY;
if (Math.abs(deltaY) > 30) {
tryTabChange(deltaY > 0 ? 1 : -1, e);
isTouching = false;
}
}
function onTouchEnd() {
isTouching = false;
}
function preventScroll(e) {
if (isLocked && isTabSectionInView()) {
e.preventDefault();
e.stopPropagation();
return false;
}
}
window.addEventListener('scroll', () => {
const currentTab = getCurrentTabIndex();
isLocked = isTabSectionInView() && currentTab > 0 && currentTab < tabButtons.length - 1;
});
tabSection.addEventListener('wheel', onWheel, { passive: false });
tabSection.addEventListener('touchstart', onTouchStart, { passive: false });
tabSection.addEventListener('touchmove', onTouchMove, { passive: false });
tabSection.addEventListener('touchend', onTouchEnd, { passive: false });
document.addEventListener('wheel', preventScroll, { passive: false });
document.addEventListener('touchmove', preventScroll, { passive: false });
const initialTab = getCurrentTabIndex();
isLocked = initialTab > 0 && initialTab < tabButtons.length - 1;
})();
</script>More scripts in UX