Page Loader
Overview
The Page Loader provides a smooth transition effect when navigating between pages or when the page is loading. It displays a loading animation that covers the entire viewport until the page content is fully loaded, then gracefully transitions away using a circular animation effect.
Implementation
The Page Loader can be implemented in any frontend project without requiring WordPress. Here's how to add it to your HTML page:
1. HTML Structure
Add the following HTML structure to your page, preferably right after the opening <body>
tag:
<div class="px-page-loader" style="position: fixed; top:0; left:0; z-index: 999999999; width: 100vw; height: 100vh; background-color: var(--body-bg, #FFF); text-align: center;">
<!-- Content Box -->
<div class="content-box" style="position: absolute; top: 50%; left: 50%; transform: translateX(-50%) translateY(-50%)">
<!-- Spinner (Choose one of the options below) -->
<!-- Option 1: Image Spinner -->
<img class="spinner" src="path/to/your/spinner.svg" alt="Loading" style="width: 3.5rem; height: auto!important" />
<!-- Option 2: Custom HTML/SVG Spinner -->
<!-- <div class="custom-spinner">Your custom spinner HTML here</div> -->
<!-- Loading Text (Optional) -->
<p style="margin-bottom: 0; font-size: 1rem; padding: 0.625rem 0.313rem;">Loading</p>
</div>
</div>
2. CSS Styles
Add these CSS styles to your stylesheet or in a <style>
tag in the <head>
section:
.px-page-loader {
clip-path: circle(150% at 50% 50%);
transition: clip-path 0.8s cubic-bezier(.77,0,.18,1), opacity 0.3s;
}
.px-page-loader.hide {
clip-path: circle(0% at 50% 50%);
}
3. JavaScript
Add this JavaScript code before the closing </body>
tag:
<script>
// Unblock any scripts that might be loading asynchronously
const phenixJsScript = document.querySelector('#phenix-js') || document.querySelector("script[src*='phenix.js']");
if(phenixJsScript) phenixJsScript.removeAttribute('async');
// Defer image loading for better performance
document.querySelectorAll('img:not([loading])').forEach(image => image.setAttribute('loading', 'lazy'));
// Hide loader when page is fully loaded
window.addEventListener('load', () => {
// Get the loader element
const pxLoader = document.querySelector('.px-page-loader');
if (!pxLoader) return;
// Add hide effect
pxLoader.classList.add('hide');
// Remove loader after transition completes
pxLoader.addEventListener('transitionend', function pxHideHandler(e) {
if (e.propertyName === 'clip-path') {
// Hide loader
pxLoader.style.display = 'none';
// Remove transition event listener
pxLoader.removeEventListener('transitionend', pxHideHandler);
}
});
});
// Show loader before leaving the page
window.addEventListener('beforeunload', () => {
// Get the loader element
const pxLoader = document.querySelector('.px-page-loader');
if (!pxLoader) return;
// Show loader
pxLoader.style.display = '';
// Remove hide effect after a brief timeout to ensure proper rendering
setTimeout(() => {
pxLoader.classList.remove('hide');
}, 10);
});
</script>
Customization Options
Background Color
You can customize the background color by changing the background-color
property in the inline style of the .px-page-loader
element. The default uses CSS variables with a fallback to white:
background-color: var(--body-bg, #FFF);
Spinner Types
The Page Loader supports two types of spinners:
Image Spinner: Use an image file (SVG recommended for best quality)
html<img class="spinner" src="path/to/your/spinner.svg" alt="Loading" style="width: 3.5rem; height: auto!important" />
Custom HTML/SVG: Insert custom HTML or inline SVG
html<div class="custom-spinner"> <!-- Your custom spinner HTML/SVG here --> </div>
Loading Text
You can customize the loading text or remove it entirely:
<p style="margin-bottom: 0; font-size: 1rem; padding: 0.625rem 0.313rem;">Your custom loading text</p>
Transition Effect
The circular transition effect can be customized by modifying the CSS properties:
.px-page-loader {
clip-path: circle(150% at 50% 50%); /* Initial state (fully visible) */
transition: clip-path 0.8s cubic-bezier(.77,0,.18,1), opacity 0.3s; /* Duration and easing */
}
.px-page-loader.hide {
clip-path: circle(0% at 50% 50%); /* Final state (fully hidden) */
}
Advanced Usage
Programmatically Controlling the Loader
Inline Loading Status with px-loading
For Ajax operations and similar dynamic content loading, it's recommended to use the px-loading
class for inline loading indicators rather than the full-page loader. This provides a better user experience by showing loading status only in the relevant section of the page.
<!-- Button with inline loading state -->
<button class="btn primary" id="load-data-btn">
<span>Load Data</span>
</button>
<!-- Content area that will show loading state -->
<div id="content-area">
<p>Content will appear here</p>
</div>
// Add loading state to a button or content area
function showInlineLoading(element) {
// Add px-loading class to show loading indicator
element.classList.add('px-loading');
}
// Remove loading state
function hideInlineLoading(element) {
// Remove px-loading class when operation completes
element.classList.remove('px-loading');
}
// Example: Using with fetch API and inline loading
async function fetchDataWithInlineLoading(url, targetElement) {
const button = document.getElementById('load-data-btn');
const contentArea = document.getElementById('content-area');
// Show loading state on button and content area
showInlineLoading(button);
showInlineLoading(contentArea);
try {
const response = await fetch(url);
const data = await response.json();
// Update content area with data
contentArea.innerHTML = data.html || JSON.stringify(data);
return data;
} catch (error) {
console.error('Error:', error);
contentArea.innerHTML = `<p class="tx-danger">Error loading data: ${error.message}</p>`;
} finally {
// Remove loading state
hideInlineLoading(button);
hideInlineLoading(contentArea);
}
}
// Add event listener to button
document.getElementById('load-data-btn').addEventListener('click', () => {
fetchDataWithInlineLoading('/api/data', document.getElementById('content-area'));
});
Full-Page Loader Control
For operations that require a full-page loading state, you can use the following functions to control the page loader:
// Show the full-page loader
function showLoader() {
const pxLoader = document.querySelector('.px-page-loader');
if (!pxLoader) return;
pxLoader.style.display = '';
// Use setTimeout to ensure proper rendering before removing the hide class
setTimeout(() => {
pxLoader.classList.remove('hide');
}, 10);
}
// Hide the full-page loader
function hideLoader() {
const pxLoader = document.querySelector('.px-page-loader');
if (!pxLoader) return;
pxLoader.classList.add('hide');
pxLoader.addEventListener('transitionend', function pxHideHandler(e) {
if (e.propertyName === 'clip-path') {
pxLoader.style.display = 'none';
pxLoader.removeEventListener('transitionend', pxHideHandler);
}
});
}
// Example: Using full-page loader with fetch API
async function fetchDataWithFullPageLoader(url) {
showLoader();
try {
const response = await fetch(url);
const data = await response.json();
// Process data
return data;
} catch (error) {
console.error('Error:', error);
} finally {
hideLoader();
}
}
Dynamic Loader Creation
If you need to create the loader dynamically via JavaScript:
function createLoader() {
// Check if loader already exists
if (document.querySelector('.px-page-loader')) return;
// Create loader element
const loaderWrapper = document.createElement('div');
loaderWrapper.innerHTML = `
<div class="px-page-loader" style="position: fixed; top:0; left:0; z-index: 999999999; width: 100vw; height: 100vh; background-color: var(--body-bg, #FFF); text-align: center;">
<div class="content-box" style="position: absolute; top: 50%; left: 50%; transform: translateX(-50%) translateY(-50%)">
<img class="spinner" src="data:image/svg+xml,%3Csvg width='42' height='42' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cstyle%3E.spinner_9y7u%7Banimation:spinner_fUkk 2.4s linear infinite;animation-delay:-2.4s%7D.spinner_DF2s%7Banimation-delay:-1.6s%7D.spinner_q27e%7Banimation-delay:-.8s%7D@keyframes spinner_fUkk%7B8.33%25%7Bx:13px;y:1px%7D25%25%7Bx:13px;y:1px%7D33.3%25%7Bx:13px;y:13px%7D50%25%7Bx:13px;y:13px%7D58.33%25%7Bx:1px;y:13px%7D75%25%7Bx:1px;y:13px%7D83.33%25%7Bx:1px;y:1px%7D%7D%3C/style%3E%3Crect class='spinner_9y7u' x='1' y='1' rx='1' width='10' height='10'/%3E%3Crect class='spinner_9y7u spinner_DF2s' x='1' y='1' rx='1' width='10' height='10'/%3E%3Crect class='spinner_9y7u spinner_q27e' x='1' y='1' rx='1' width='10' height='10'/%3E%3C/svg%3E%0A" alt="Loading" style="width: 3.5rem; height: auto!important" />
<p style="margin-bottom: 0; font-size: 1rem; padding: 0.625rem 0.313rem;">Loading</p>
</div>
</div>
`;
// Add styles
const style = document.createElement('style');
style.textContent = `
.px-page-loader {clip-path: circle(150% at 50% 50%); transition: clip-path 0.8s cubic-bezier(.77,0,.18,1), opacity 0.3s;}
.px-page-loader.hide {clip-path: circle(0% at 50% 50%);}
`;
document.head.appendChild(style);
// Add loader to document
document.body.appendChild(loaderWrapper.firstElementChild);
}
Browser Compatibility
The Page Loader is compatible with all modern browsers that support CSS clip-path
(Chrome, Firefox, Safari, Edge). For older browsers that don't support clip-path
, the loader will still work but without the circular transition effect.
Best Practices
- Placement: Add the loader as early as possible in the HTML to ensure it appears before other content.
- Performance: Use SVG for spinners instead of GIFs for better performance.
- Accessibility: Include appropriate ARIA attributes for screen readers.
- Fallbacks: Provide fallbacks for browsers that don't support modern CSS features.
- Timing: Adjust transition timing based on your site's typical loading speed.