<div class="hero-002">
<!-- Slider -->
<div class="slides-container">
<!-- Loader Overlay (Slide 0) -->
<div class="slide slide-0">
<div class="loader-content">
<div class="loading-label">
LOADING
</div>
<div class="loading-numbers-wrapper">
<div class="col col-hundreds">
<div class="num">
0
</div>
<div class="num">
1
</div>
</div>
<div class="col col-tens">
<div class="num">
0
</div>
<div class="num">
1
</div>
<div class="num">
2
</div>
<div class="num">
3
</div>
<div class="num">
4
</div>
<div class="num">
5
</div>
<div class="num">
6
</div>
<div class="num">
7
</div>
<div class="num">
8
</div>
<div class="num">
9
</div>
<div class="num">
0
</div>
</div>
<div class="col col-units">
<div class="num">
0
</div>
<div class="num">
1
</div>
<div class="num">
2
</div>
<div class="num">
3
</div>
<div class="num">
4
</div>
<div class="num">
5
</div>
<div class="num">
6
</div>
<div class="num">
7
</div>
<div class="num">
8
</div>
<div class="num">
9
</div>
<div class="num">
0
</div>
<div class="num">
1
</div>
<div class="num">
2
</div>
<div class="num">
3
</div>
<div class="num">
4
</div>
<div class="num">
5
</div>
<div class="num">
6
</div>
<div class="num">
7
</div>
<div class="num">
8
</div>
<div class="num">
9
</div>
<div class="num">
0
</div>
</div>
</div>
<div class="loading-percent">
%
</div>
<div class="loader-line">
</div>
</div>
</div>
<!-- Images -->
<div class="slide slide-img" style="background-image: url('https://storage.maquinaespacial.com/media/models/1.jpg');">
</div>
<div class="slide slide-img" style="background-image: url('https://storage.maquinaespacial.com/media/models/2.jpg');">
</div>
<div class="slide slide-img" style="background-image: url('https://storage.maquinaespacial.com/media/models/3.jpg');">
</div>
<div class="slide slide-img" style="background-image: url('https://storage.maquinaespacial.com/media/models/7.jpg');">
</div>
<div class="slide slide-img" style="background-image: url('https://storage.maquinaespacial.com/media/models/8.jpg');">
</div>
<div class="slide slide-img" style="background-image: url('https://storage.maquinaespacial.com/media/models/9.jpg');">
</div>
<div class="slide slide-img" style="background-image: url('https://storage.maquinaespacial.com/media/models/6.jpg');">
</div>
<div class="slide slide-img" style="background-image: url('https://storage.maquinaespacial.com/media/models/5.jpg');">
</div>
<div class="slide slide-img" style="background-image: url('https://storage.maquinaespacial.com/media/models/4.jpg');">
</div>
<!-- Overlay -->
<div class="image-overlay">
</div>
</div>
<!-- UI Layer -->
<div class="ui-layer">
<div class="header">
<div class="logo">
LOGO
</div>
<div class="center-menu">
<a href="#">
WORK
</a>
<a href="#">
STUDIO
</a>
<a href="#">
NEWS
</a>
<a href="#">
CONTACT
</a>
</div>
<div class="menu">
MENU
</div>
</div>
<div class="center-text">
<div class="char-wrapper">
<span class="char">
E
</span>
</div>
<div class="char-wrapper">
<span class="char">
S
</span>
</div>
<div class="char-wrapper">
<span class="char">
P
</span>
</div>
<div class="char-wrapper">
<span class="char">
A
</span>
</div>
<div class="char-wrapper">
<span class="char">
C
</span>
</div>
<div class="char-wrapper">
<span class="char">
I
</span>
</div>
<div class="char-wrapper">
<span class="char">
A
</span>
</div>
<div class="char-wrapper">
<span class="char">
L
</span>
</div>
</div>
</div>
</div>
/* BIT_CSS_START */
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@300;500;700&display=swap');
body {
margin: 0;
padding: 0;
}
.hero-002 {
position: relative;
width: 100vw;
height: 100vh;
overflow: hidden;
background: #000;
font-family: 'Montserrat', 'Helvetica Neue', Arial, sans-serif;
}
.slides-container {
position: absolute;
width: 100%;
height: 100%;
}
.slide {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
/* Images start off-screen to the right */
transform: translateX(100%);
will-change: transform;
}
.slide-0 {
background-color: #dfce19;
/* Yellow matching the screenshot */
transform: translateX(0%);
z-index: 2;
}
.loader-content {
position: absolute;
bottom: 5%;
right: 5%;
display: flex;
align-items: flex-end;
font-size: clamp(3rem, 7vw, 7rem);
/* Responsive limits */
color: #111;
line-height: 1.2;
/* Taller to prevent font clipping */
}
.loading-label {
font-size: 0.4em;
font-weight: 300;
margin-right: 0.2em;
margin-bottom: 0.15em;
/* Optical alignment with numbers */
}
.loading-numbers-wrapper {
display: flex;
height: 1.2em;
/* Extremely safe height */
overflow: hidden;
font-weight: 700;
}
.col {
display: flex;
flex-direction: column;
}
.num {
height: 1.2em;
display: flex;
align-items: center;
justify-content: center;
line-height: 1.2;
}
.loading-percent {
font-size: 1em;
font-weight: 700;
line-height: 1;
margin-left: 0.1em;
}
.loader-line {
position: absolute;
bottom: 0.15em;
/* Match optical text baseline */
left: 100%;
/* Start exactly after the % symbol */
width: 200vw;
/* Extremely long to cover the screen as it moves left */
height: 0.08em;
/* Thick and elegant underline */
background-color: #111;
opacity: 0;
/* Hidden initially */
}
.ui-layer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 10;
display: flex;
flex-direction: column;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 40px 60px;
font-size: 1.2rem;
font-weight: 700;
color: #dfce19;
/* Yellow text */
opacity: 0;
/* hidden initially */
text-transform: uppercase;
letter-spacing: 0.1em;
}
.center-menu {
display: flex;
gap: 40px;
font-weight: 300;
font-size: 0.95rem;
}
.center-menu a {
color: #dfce19;
/* Yellow text */
text-decoration: none;
transition: opacity 0.3s ease;
}
.center-menu a:hover {
opacity: 0.7;
}
.center-text {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
font-size: 10vw;
font-weight: 700;
color: #dfce19;
/* Yellow text */
letter-spacing: 0.05em;
padding-bottom: 10vh;
/* Optical centering */
}
.image-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(255, 255, 255, 0.30);
/* Transparent white */
z-index: 1;
pointer-events: none;
}
.char-wrapper {
overflow: hidden;
display: inline-block;
padding-right: 0.5rem;
}
.char {
display: inline-block;
transform: translateY(100%);
opacity: 0;
}
/* Responsive Overrides */
@media (max-width: 768px) {
.header {
padding: 25px 20px;
font-size: 1rem;
}
.center-menu {
display: none;
/* Hide link list on mobile, rely on MENU button */
}
}
/* BIT_CSS_END */
// BIT_JS_START
document.addEventListener('DOMContentLoaded', () => {
// Check if GSAP is available
if (typeof gsap === 'undefined') {
console.error("GSAP is required for this animation to work.");
return;
}
const tl = gsap.timeline();
// 1. Loader Animation (Slot Machine Effect)
// Numbers wrapper is now 1.2em tall to avoid clipping
tl.to('.col-hundreds', {
y: '-1.2em',
duration: 3,
ease: 'power3.inOut'
}, 0);
tl.to('.col-tens', {
y: '-12em', // 10 steps * 1.2em (to reach index 10, which is the final '0')
duration: 3,
ease: 'power3.inOut'
}, 0);
tl.to('.col-units', {
y: '-24em', // 20 steps * 1.2em
duration: 3,
ease: 'power3.inOut'
}, 0);
// Fade in the line when counting reaches 100%
tl.to('.loader-line', {
opacity: 1,
duration: 0.4,
ease: 'power2.inOut'
}, 3.0);
// 2. Hide Loader Text (Slides to left)
tl.to('.loader-content', {
x: '-100vw',
duration: 0.8,
ease: 'power2.in'
}, 3.5);
// Fade out the line before images start
tl.to('.loader-line', {
opacity: 0,
duration: 0.4,
ease: 'power2.out'
}, 4.3);
// 3. Slides Sequence (Cascading Overlap)
const slides = gsap.utils.toArray('.slide-img');
// First image pushes the yellow background (slide-0)
tl.to('.slide-0', {
x: '-100%',
duration: 1.2,
ease: 'power3.inOut'
}, 4.5);
tl.to(slides[0], {
x: '0%',
duration: 1.2,
ease: 'power3.inOut'
}, 4.5);
// The rest of the images cascade immediately
let slideStartTime = 4.5 + 1.2 - 0.95; // 4.75
for (let i = 1; i < slides.length; i++) {
tl.to(slides[i], {
x: '0%',
duration: 1.2, // Smooth, longer travel
ease: 'power2.out'
}, slideStartTime);
slideStartTime += (1.2 - 0.95); // Increment by 0.25s
}
// 4. Reveal ESPACIAL text and UI
tl.to('.char', {
y: '0%',
opacity: 1,
duration: 0.8,
stagger: 0.08,
ease: 'back.out(1.5)'
}, slideStartTime + 0.3);
tl.to('.header', {
opacity: 1,
duration: 1,
ease: 'power2.out'
}, '<');
});
// BIT_JS_END
Technical Skills & Techniques Used
This Bit showcases an extremely precise orchestration of CSS Layout mathematics and GSAP timeline sequencing.
1. Advanced GSAP Timeline Sequencing
- Cascading Overlaps: Instead of chaining animations linearly, the slideshow utilizes negative relative delays (
-=0.95). This allows a new image to begin its entrance animation while the previous image is barely halfway done, creating a wave of multiple moving elements simultaneously.
- Absolute Timestamp Precision: The preloader and the trailing underline use absolute timestamps (e.g., triggering exactly at
3.0s or 4.5s) to perfectly synchronize the fade-in, the sliding text, and the line fade-out in a tight 0.5-second window.
2. Mathematical Typographic Scaling
em-Based Clipping: Standard slot machine preloaders often break or clip letters due to font ascenders/descenders across different operating systems. This layout uses a strict height: 1.2em window.
- Precise GSAP Math: By ensuring the window is precisely
1.2em tall, the GSAP y translations can be mathematically perfect. To reach the 11th number in a column, the code moves it exactly -12em (10 steps × 1.2em), locking the numbers perfectly into the vertical center without guesswork.
3. Fluid Typography
- CSS
clamp() Function: The primary loader text (LOADING 100%) uses font-size: clamp(3rem, 7vw, 7rem). This modern CSS function replaces the need for multiple media queries, guaranteeing the text naturally scales down to fit mobile screens but stops growing on ultra-wide monitors, preventing horizontal overflow entirely.
Cinematic Loader Hero
This Bit is a high-end, highly animated Hero Header section designed for premium creative portfolios or agency websites. It sequences a mathematically precise preloader into a rapid cascading image slideshow, culminating in a bold typographic reveal.
Features
- Slot Machine Preloader: A custom, GSAP-powered rolling numbers animation that accurately scales through columns of numbers to land perfectly on "100%", avoiding the jitter commonly associated with standard counter animations.
- Trailing Underline Effect: As the preloader exits the screen, an elegant black line is dragged across the yellow background, providing a cinematic scene transition.
- Continuous Overlap Slideshow: A sequence of 9 high-quality placeholder images cascade into the viewport. Instead of waiting for one to finish, multiple images overlap in rapid motion, creating a dynamic fluid wave.
- Staggered Text Reveal: The central brand name ("ESPACIAL") appears letter-by-letter precisely as the slideshow settles, paired with the fading in of the top navigation menu.
- Legibility Overlay: A subtle, transparent white overlay permanently sits above the imagery, ensuring the bright yellow text remains completely readable against chaotic or high-contrast background images.
Usage
This Bit relies on the GreenSock Animation Platform (GSAP) to orchestrate the complex timeline. Ensure the GSAP CDN is loaded in your project. The structure is heavily reliant on absolute positioning and em-based typography scaling to prevent clipping on mobile devices.
Design Decisions
Visual Concept
The aesthetic of this Bit is heavily inspired by high-fashion editorials and experimental creative agencies. It rejects standard static headers in favor of a narrative, multi-stage entrance that captures user attention immediately before revealing the main interface.
Color Palette & Legibility
- Hero Yellow (
#dfce19): A striking, aggressive yellow acts as the primary accent color. It is used both as the background for the initial preloader phase, and as the text color for the final brand reveal.
- White Legibility Overlay (
rgba(255, 255, 255, 0.15)): To guarantee that the yellow typography is always legible, a permanent, non-interactive transparent white overlay covers the photographic backgrounds. This creates a slightly muted, frosted environment that allows bright colors to pop.
Typography
- Montserrat & Helvetica Neue: Thick, imposing sans-serif typography is used for the preloader numbers (
700 weight) and the central brand name, creating a brutalist contrast with the very thin, elegant 300 weight navigation links in the header.
Mobile Layout Optimization
On mobile screens (below 768px), the complex center navigation menu (WORK, STUDIO, NEWS, CONTACT) is completely hidden (display: none;). Instead, the UI defaults to a premium standard: "LOGO" on the far left, and "MENU" on the far right. This prevents textual clutter and honors the negative space required by the central animation.