Skip to content

Instantly share code, notes, and snippets.

@divienginesupport
Created July 10, 2025 12:14
Show Gist options
  • Save divienginesupport/716516da036e9f4b0eb9a673fbdd2b19 to your computer and use it in GitHub Desktop.
Save divienginesupport/716516da036e9f4b0eb9a673fbdd2b19 to your computer and use it in GitHub Desktop.
scroll-tabs.js
<script>
jQuery(document).ready(function($) {
// --- UTILITY: Throttle function to limit execution frequency ---
// Prevents the scroll handler from firing too often, improving performance
function throttle(func, limit) {
let inThrottle;
return function() {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args); // Call the function
inThrottle = true;
setTimeout(() => inThrottle = false, limit); // Reset throttle after limit
}
}
}
// Get the main scroll section container
const scrollSection = $('.scroll-tabs');
if (scrollSection.length === 0) return; // Exit early if not found
// Get all tabs and tab controls (the clickable tab headers)
const tabs = scrollSection.find('.et_pb_tab');
const controls = scrollSection.find('.et_pb_tabs_controls li');
const tabCount = tabs.length;
if (tabCount === 0) return; // Exit if no tabs found
const windowHeight = $(window).height();
// --- Fix for Divi's layout quirks ---
// Ensure parent containers do not clip sticky or animated content
scrollSection.parents().css('overflow', 'visible');
// === STEP 1: SET SCROLL RUNWAY HEIGHT ===
// Increase section height to allow enough scrolling room to trigger tab changes
// Adds 1 extra screen height as a buffer after the last tab
const totalScrollHeight = windowHeight * (tabCount + 1);
scrollSection.height(totalScrollHeight);
// === STEP 2: ACTIVATE INITIAL TAB ===
// Ensure only the first tab is shown on page load
tabs.removeClass('active-tab');
controls.removeClass('et_pb_tab_active');
tabs.first().addClass('active-tab');
controls.first().addClass('et_pb_tab_active');
// === STEP 3: HANDLE SCROLL TO TRIGGER TAB CHANGES ===
function handleScroll() {
const sectionTop = scrollSection.offset().top;
const scrollTop = $(window).scrollTop();
const scrollAmount = scrollTop - sectionTop;
// Only run tab logic when within the scrollable section
if (scrollAmount >= 0 && scrollAmount <= totalScrollHeight - windowHeight) {
// Calculate which tab index should be active based on scroll position
let index = Math.floor(scrollAmount / windowHeight);
index = Math.max(0, Math.min(tabCount - 1, index)); // Clamp index to valid range
// Only update if this tab is not already active
if (!controls.eq(index).hasClass('et_pb_tab_active')) {
controls.removeClass('et_pb_tab_active');
controls.eq(index).addClass('et_pb_tab_active');
tabs.removeClass('active-tab');
tabs.eq(index).addClass('active-tab');
}
}
}
// Attach the scroll event using the throttled scroll handler
$(window).on('scroll', throttle(handleScroll, 50));
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment