v0.1

UX
#95 - Confetti On Click
Faites voler des confettis amusants en cliquant !
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