Member
Account Settings
Share AgencyGenius
Know someone who might benefit from AgencyGenius? We'd love it if you shared our platform with your networking group!

Documentation
Step 1: Add HTML, Css & JavaScript
<!-- Vanilla JS Scroll Progress Bar - Shows scroll progress under the header - Place this HTML code anywhere on your page --> <div id="vanilla-progress-bar-container"> <div class="progress-bar-wrap"> <div class="progress-bar"></div> </div> </div>
/* Progress Bar Styles - These styles will be applied to the progress bar container - They'll be moved to the fixed container via JavaScript */ /* Initially hide the container - JS will create the fixed version */ #vanilla-progress-bar-container { display: none; } /* These styles will be applied to the fixed container created by JavaScript */ #progress-bar-fixed-container { position: fixed; top: 0; /* Will be adjusted by JavaScript to position below header */ left: 0; width: 100vw; height: 1.5rem; z-index: 999; } #progress-bar-fixed-container .progress-bar-wrap { width: 100%; height: 100%; cursor: pointer; transition: background-color .2s; } #progress-bar-fixed-container .progress-bar-wrap:hover { background-color: #0000000d; } #progress-bar-fixed-container .progress-bar { transform-origin: 0%; transform-style: preserve-3d; background-color: #ad24a6; width: 100%; height: 100%; transform: scale3d(0, 1, 1); }
/** * Vanilla JavaScript Progress Bar * - Creates a progress bar that positions itself below the header * - Tracks scroll progress and allows click-to-scroll functionality */ (function() { // Self-executing function to create a closure and avoid global variables // Function to initialize the progress bar when DOM is ready function initProgressBar() { // Get container reference to scope all our selectors const container = document.getElementById('vanilla-progress-bar-container'); // If container not found, exit if (!container) return; // Create a function to move the progress bar into the document body function moveProgressBarToBody() { // First, create a new container for the fixed progress bar const fixedContainer = document.createElement('div'); fixedContainer.id = 'progress-bar-fixed-container'; // Clone the progress bar elements const originalWrap = container.querySelector('.progress-bar-wrap'); const progressBarWrap = originalWrap.cloneNode(true); // Add to our fixed container fixedContainer.appendChild(progressBarWrap); // Add the fixed container to the body document.body.appendChild(fixedContainer); // Hide the original container container.style.display = 'none'; // Return references to the new elements return { container: fixedContainer, wrap: progressBarWrap, bar: progressBarWrap.querySelector('.progress-bar') }; } // Move the progress bar to a fixed position in the body const elements = moveProgressBarToBody(); const progressBarContainer = elements.container; const progressBarWrap = elements.wrap; const progressBar = elements.bar; // Function to position the progress bar under the header function positionProgressBar() { // Try to find header elements by common IDs and classes // First check for Duda's header container let header = document.getElementById('dmFlexHeaderContainer'); // If Duda header isn't found, try other common header selectors if (!header) { // Try common header selectors const commonHeaderSelectors = [ 'header', '.header', '#header', '.site-header', '.main-header', '#site-header', '.navbar', '.navigation', '.nav-container', '.top-bar' ]; // Try each selector until we find a header for (const selector of commonHeaderSelectors) { header = document.querySelector(selector); if (header) break; } } // If we found a header, position the progress bar right below it if (header) { const headerRect = header.getBoundingClientRect(); progressBarContainer.style.top = headerRect.bottom + 'px'; } else { // Fallback: if no header found, position at the top progressBarContainer.style.top = '0px'; } } // Position progress bar on load positionProgressBar(); // Reposition on window resize window.addEventListener('resize', positionProgressBar); // Function to update progress bar based on scroll position function updateProgressBar() { // Calculate scroll progress (0 to 1) const scrollTop = window.scrollY || document.documentElement.scrollTop; const scrollHeight = document.documentElement.scrollHeight; const clientHeight = document.documentElement.clientHeight; const scrollProgress = scrollTop / (scrollHeight - clientHeight); // Ensure progress is between 0 and 1 to prevent visual glitches const boundedProgress = Math.min(Math.max(scrollProgress, 0), 1); // Update progress bar scale progressBar.style.transform = `scale3d(${boundedProgress}, 1, 1)`; } // Initial update when page loads updateProgressBar(); // Add scroll event listener to update progress during scrolling window.addEventListener('scroll', updateProgressBar); // Click listener to scroll to a specific position (optional feature) progressBarWrap.addEventListener('click', (event) => { // Calculate the horizontal position of the click as a percentage const clickX = event.clientX; const progress = clickX / progressBarWrap.offsetWidth; // Calculate the actual scroll position based on that percentage const scrollPosition = progress * (document.body.scrollHeight - window.innerHeight); // Smooth scroll to that position smoothScrollTo(scrollPosition, 725); // 725ms animation duration }); /** * Smooth scroll function for animated scrolling * @param {number} targetPosition - Target scroll position in pixels * @param {number} duration - Animation duration in milliseconds */ function smoothScrollTo(targetPosition, duration) { const startPosition = window.scrollY || document.documentElement.scrollTop; const distance = targetPosition - startPosition; const startTime = performance.now(); function scrollAnimation(currentTime) { const elapsedTime = currentTime - startTime; const progress = Math.min(elapsedTime / duration, 1); // Clamp to 1 // Use cubic easing for smooth animation const easeProgress = 1 - Math.pow(1 - progress, 3); window.scrollTo(0, startPosition + distance * easeProgress); // Continue animation if not complete if (progress < 1) { requestAnimationFrame(scrollAnimation); } } // Start the animation requestAnimationFrame(scrollAnimation); } } // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initProgressBar); } else { // DOM already loaded, initialize immediately initProgressBar(); } })();
<div id="snippet-4evbhub1"> <!-- HTML SECTION START --> <!-- Vanilla JS Scroll Progress Bar - Shows scroll progress under the header - Place this HTML code anywhere on your page --> <div id="vanilla-progress-bar-container"> <div class="progress-bar-wrap"> <div class="progress-bar"></div> </div> </div> <!-- HTML SECTION END --> <!-- CSS SECTION START --> <style> /* Progress Bar Styles - These styles will be applied to the progress bar container - They'll be moved to the fixed container via JavaScript */ /* Initially hide the container - JS will create the fixed version */ #vanilla-progress-bar-container { display: none; } /* These styles will be applied to the fixed container created by JavaScript */ #progress-bar-fixed-container { position: fixed; top: 0; /* Will be adjusted by JavaScript to position below header */ left: 0; width: 100vw; height: 1.5rem; z-index: 999; } #progress-bar-fixed-container .progress-bar-wrap { width: 100%; height: 100%; cursor: pointer; transition: background-color .2s; } #progress-bar-fixed-container .progress-bar-wrap:hover { background-color: #0000000d; } #progress-bar-fixed-container .progress-bar { transform-origin: 0%; transform-style: preserve-3d; background-color: #ad24a6; width: 100%; height: 100%; transform: scale3d(0, 1, 1); } </style> <!-- CSS SECTION END --> <!-- JAVASCRIPT SECTION START --> <script> /** * Vanilla JavaScript Progress Bar * - Creates a progress bar that positions itself below the header * - Tracks scroll progress and allows click-to-scroll functionality */ (function() { // Self-executing function to create a closure and avoid global variables // Function to initialize the progress bar when DOM is ready function initProgressBar() { // Get container reference to scope all our selectors const container = document.getElementById('vanilla-progress-bar-container'); // If container not found, exit if (!container) return; // Create a function to move the progress bar into the document body function moveProgressBarToBody() { // First, create a new container for the fixed progress bar const fixedContainer = document.createElement('div'); fixedContainer.id = 'progress-bar-fixed-container'; // Clone the progress bar elements const originalWrap = container.querySelector('.progress-bar-wrap'); const progressBarWrap = originalWrap.cloneNode(true); // Add to our fixed container fixedContainer.appendChild(progressBarWrap); // Add the fixed container to the body document.body.appendChild(fixedContainer); // Hide the original container container.style.display = 'none'; // Return references to the new elements return { container: fixedContainer, wrap: progressBarWrap, bar: progressBarWrap.querySelector('.progress-bar') }; } // Move the progress bar to a fixed position in the body const elements = moveProgressBarToBody(); const progressBarContainer = elements.container; const progressBarWrap = elements.wrap; const progressBar = elements.bar; // Function to position the progress bar under the header function positionProgressBar() { // Try to find header elements by common IDs and classes // First check for Duda's header container let header = document.getElementById('dmFlexHeaderContainer'); // If Duda header isn't found, try other common header selectors if (!header) { // Try common header selectors const commonHeaderSelectors = [ 'header', '.header', '#header', '.site-header', '.main-header', '#site-header', '.navbar', '.navigation', '.nav-container', '.top-bar' ]; // Try each selector until we find a header for (const selector of commonHeaderSelectors) { header = document.querySelector(selector); if (header) break; } } // If we found a header, position the progress bar right below it if (header) { const headerRect = header.getBoundingClientRect(); progressBarContainer.style.top = headerRect.bottom + 'px'; } else { // Fallback: if no header found, position at the top progressBarContainer.style.top = '0px'; } } // Position progress bar on load positionProgressBar(); // Reposition on window resize window.addEventListener('resize', positionProgressBar); // Function to update progress bar based on scroll position function updateProgressBar() { // Calculate scroll progress (0 to 1) const scrollTop = window.scrollY || document.documentElement.scrollTop; const scrollHeight = document.documentElement.scrollHeight; const clientHeight = document.documentElement.clientHeight; const scrollProgress = scrollTop / (scrollHeight - clientHeight); // Ensure progress is between 0 and 1 to prevent visual glitches const boundedProgress = Math.min(Math.max(scrollProgress, 0), 1); // Update progress bar scale progressBar.style.transform = `scale3d(${boundedProgress}, 1, 1)`; } // Initial update when page loads updateProgressBar(); // Add scroll event listener to update progress during scrolling window.addEventListener('scroll', updateProgressBar); // Click listener to scroll to a specific position (optional feature) progressBarWrap.addEventListener('click', (event) => { // Calculate the horizontal position of the click as a percentage const clickX = event.clientX; const progress = clickX / progressBarWrap.offsetWidth; // Calculate the actual scroll position based on that percentage const scrollPosition = progress * (document.body.scrollHeight - window.innerHeight); // Smooth scroll to that position smoothScrollTo(scrollPosition, 725); // 725ms animation duration }); /** * Smooth scroll function for animated scrolling * @param {number} targetPosition - Target scroll position in pixels * @param {number} duration - Animation duration in milliseconds */ function smoothScrollTo(targetPosition, duration) { const startPosition = window.scrollY || document.documentElement.scrollTop; const distance = targetPosition - startPosition; const startTime = performance.now(); function scrollAnimation(currentTime) { const elapsedTime = currentTime - startTime; const progress = Math.min(elapsedTime / duration, 1); // Clamp to 1 // Use cubic easing for smooth animation const easeProgress = 1 - Math.pow(1 - progress, 3); window.scrollTo(0, startPosition + distance * easeProgress); // Continue animation if not complete if (progress < 1) { requestAnimationFrame(scrollAnimation); } } // Start the animation requestAnimationFrame(scrollAnimation); } } // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initProgressBar); } else { // DOM already loaded, initialize immediately initProgressBar(); } })(); </script> <!-- JAVASCRIPT SECTION END --> </div>
Implementation
The Vanilla JS Progress Bar creates a sleek, fixed-position scroll indicator that positions itself beneath your website's header. As users scroll down the page, the bar fills proportionally to represent their progress. The implementation also includes an optional click-to-scroll feature that allows users to jump to different parts of the page by clicking on the bar.
HTML Structure
The HTML structure is minimal and can be placed anywhere on your page:
- A container vanilla-progress-bar-container holds the basic structure
- Inside is a wrapper progress-bar-wrap which handles user interaction
- The actual indicator progress-bar shows the scroll progress
CSS Styling
The CSS handles positioning, appearance, and animations:
- Uses position: fixed to keep the bar in view at all times
- Sets width: 100vw to ensure the bar spans the full viewport width
- Uses z-index: 999 to display above other page elements
- Creates a subtle hover effect with background-color: #0000000d
- The progress indicator uses transform: scale3d() for smooth performance
- Sets background-color: #ad24a6 for the purple progress indicator
- Uses transform-origin: 0% to ensure scaling happens from left to right
JavaScript Functionality
The JavaScript handles dynamic positioning and interaction:
- Header Detection:
- Automatically finds your site's header element
- First looks for Duda's #dmFlexHeaderContainer
- Falls back to common header selectors if Duda's header isn't found
- Element Creation:
- Creates a fixed container directly in the document body
- Moves the progress bar into this container for proper positioning
- Positions the bar immediately below the detected header
- Scroll Tracking:
- Calculates current scroll position relative to total page height
- Updates the scale3d transform to represent scroll percentage
- Ensures values are bounded between 0 and 1 to prevent visual glitches
- Click Navigation:
- Captures click position relative to the bar width
- Calculates corresponding scroll position as a percentage of total page height
- Implements smooth scrolling with cubic easing function
- Uses requestAnimationFrame for butter-smooth animations
Customization Tips
The progress bar can be easily customized to match your site:
- Bar color: Change the background-color property of .progress-bar
- Bar height: Adjust the height property in both the container and progress bar
- Animation speed: Modify the duration parameter in the smoothScrollTo function
- Hover effect: Customize the background-color value for .progress-bar-wrap:hover
- Z-index: Adjust the z-index value if the bar needs to appear above or below certain elements
- Header detection: Add additional selectors to the commonHeaderSelectors array for custom headers
Integration Tips
To integrate this widget into your site:
- Placement: Add the HTML code anywhere on pages where you want the progress bar to appear
- Styling conflicts: If your site already uses similar class names, change the IDs and class names in the code
- Multiple instances: The script prevents duplicate progress bars if you accidentally add it multiple times
- Click navigation: Remove the click event listener code if you don't want the click-to-scroll functionality
- Performance: The code uses efficient transform properties and requestAnimationFrame for smooth performance
- Responsive design: The progress bar automatically adjusts on window resize to stay below the header

How to edit code using AI →
Resource Details:
Vanilla JS Progress Bar adds a sleek scroll indicator beneath your site's header. The bar fills as users scroll, visually showing their position on the page. Features automatic header detection, click-to-navigate functionality, and smooth animations. Pure JavaScript implementation with no dependencies, customizable colors, and responsive positioning that works across different platforms and screen sizes.

NO-ACCESS
Only for Desktop Users
This page is only available on desktop.
Please Log in on a desktop to gain access.