Overview
The Loader component displays an animated loading screen on initial page load, featuring the Adosa logo, a progress bar, and a percentage counter. It uses GSAP for smooth animations and includes intelligent behavior to avoid showing on subsequent navigation.
Location
src/components/Loader.astro
Usage
---
import Loader from '../components/Loader.astro' ;
---
< ! DOCTYPE html >
< html >
< head > ... </ head >
< body >
< Loader />
<!-- Rest of page content -->
</ body >
</ html >
The Loader should be placed at the beginning of the <body> tag to ensure it displays before any content.
Structure
src/components/Loader.astro
< div id = "initial-loader" class = "loader-container" >
< div class = "loader-content" >
< img class = "loader-logo" src = "/Logo_adosa.svg" alt = "Logo Adosa" />
< div class = "loader-progress-bar" >
< div class = "loader-progress-fill" ></ div >
</ div >
< div class = "loader-percentage" > 0% </ div >
</ div >
</ div >
Behavior Logic
The loader uses smart detection to determine when to display:
When Loader Shows
When Loader Skips
The loader appears when:
First visit in session - User hasn’t loaded any page yet
Page reload - User manually refreshes the page (F5, Cmd+R)
Heavy pages - Always shows on /propiedades page
function shouldRunLoader () {
// 1. Check if it's a reload
const navEntries = performance . getEntriesByType ( 'navigation' );
if ( navEntries [ 0 ]?. type === 'reload' ) return true ;
// 2. Always run on propiedades (heavy page)
if ( window . location . pathname . includes ( '/propiedades' )) return true ;
// 3. Check session storage (first visit)
if ( ! sessionStorage . getItem ( 'ADOSA_LOADED' )) return true ;
return false ;
}
The loader is hidden when:
User navigates to a new page (not first load)
Session storage indicates previous load
Not a page reload
Not the properties page
This prevents the “flash” on every page navigation, improving UX.
Inline Script Prevention
An inline script runs immediately during HTML parsing to hide the loader before rendering:
< script is:inline >
( function () {
var isPropiedades = window . location . pathname . indexOf ( '/propiedades' ) !== - 1 ;
if ( isPropiedades ) return ; // Let loader run
var hasLoaded = sessionStorage . getItem ( 'ADOSA_LOADED' );
if ( hasLoaded && ! isReload ) {
var el = document . getElementById ( 'initial-loader' );
if ( el ) el . style . display = 'none' ;
}
})();
</ script >
This inline script is critical for preventing the “0% flash” on heavy pages. Do not remove the is:inline attribute.
Animation Sequence
The loader uses GSAP for smooth animations:
1. Logo Fade In
gsap . to ( logo , {
opacity: 1 ,
y: 0 ,
duration: 0.8 ,
ease: 'power2.out'
});
2. Progress Bar Animation
let progress = { value: 0 };
gsap . to ( progress , {
value: 100 ,
duration: 1.5 ,
ease: 'power2.inOut' ,
onUpdate : () => {
const val = Math . round ( progress . value );
fill . style . width = ` ${ val } %` ;
percentage . textContent = ` ${ val } %` ;
},
onComplete : () => {
// Slide out loader
}
});
3. Slide Out Exit
gsap . to ( loader , {
xPercent: - 100 ,
duration: 1.0 ,
ease: 'power4.inOut' ,
delay: 0.2 ,
onComplete : () => {
document . body . style . overflow = '' ;
loader . style . display = 'none' ;
window . dispatchEvent ( new CustomEvent ( 'loader-complete' ));
}
});
The loader-complete event is dispatched when animation finishes, allowing other components to react.
Styling
Container
Full-screen overlay covering viewport
Highest z-index to stay above all content
background-color
color
default: "var(--color-1)"
Matches site background (beige/cream)
.loader-container {
position : fixed ;
top : 0 ;
left : 0 ;
width : 100 vw ;
height : 100 vh ;
background-color : var ( --color-1 );
z-index : 9999 ;
display : flex ;
justify-content : center ;
align-items : center ;
}
Logo
.loader-logo {
width : 100 % ;
max-width : 280 px ;
height : auto ;
padding : 2 rem ;
}
Progress Bar
.loader-progress-bar {
width : 200 px ;
height : 2 px ;
background-color : rgba ( 0 , 0 , 0 , 0.1 );
position : relative ;
overflow : hidden ;
}
.loader-progress-fill {
position : absolute ;
width : 0 % ;
height : 100 % ;
background-color : var ( --color-3 ); /* Gold accent */
transition : width 0.1 s linear ;
}
Percentage Display
.loader-percentage {
font-size : 0.9 rem ;
font-family : var ( --font-main );
color : var ( --color-2 );
font-weight : 500 ;
}
Customization
Changing Duration
Adjust the animation timing:
gsap . to ( progress , {
value: 100 ,
duration: 2.0 , // Slower: 2 seconds
ease: 'power2.inOut' ,
// ...
});
Changing Exit Animation
Modify the slide-out direction:
// Slide right instead of left
gsap . to ( loader , {
xPercent: 100 , // Changed from -100
duration: 1.0 ,
ease: 'power4.inOut'
});
// Fade out instead of slide
gsap . to ( loader , {
opacity: 0 ,
duration: 0.6 ,
ease: 'power2.inOut'
});
Disabling for Specific Pages
Modify the shouldRunLoader() function:
function shouldRunLoader () {
// Never show on /contact page
if ( window . location . pathname . includes ( '/contacto' )) return false ;
// Your existing logic
// ...
}
Changing Colors
.loader-container {
background-color : #your-bg-color;
}
.loader-progress-fill {
background-color : #your-accent-color;
}
.loader-percentage {
color : #your-text-color;
}
Session Storage
The loader uses sessionStorage to track if a page has been loaded:
// Set flag after loader runs
sessionStorage . setItem ( 'ADOSA_LOADED' , 'true' );
// Check flag before showing
if ( ! sessionStorage . getItem ( 'ADOSA_LOADED' )) {
// Show loader
}
Session storage is cleared when the browser tab is closed, so first load after reopening will show the loader again.
Body Scroll Control
The loader prevents scrolling during animation:
// Disable scroll when loader is active
document . body . style . overflow = 'hidden' ;
// Re-enable after animation
document . body . style . overflow = '' ;
Events
Listen for loader completion in other components:
window . addEventListener ( 'loader-complete' , () => {
console . log ( 'Loader finished!' );
// Initialize other animations
});
Navigation Header navigation component
GSAP Integration Learn about GSAP animations