split-text-preloader
Файли-джерела
- home-1.html
div.mil-preloader
Бібліотеки
gsap
Summary
Brand-stating preloader with a sequenced GSAP timeline. Phase one stages three muted words (Pioneering / Creative / Excellence) with stagger 0.4 then exits them up. Phase two runs an accent orange box wipe: it appears at -30px, sweeps to 100% width, anchors to the right, and collapses to 0% — revealing the brand string ashley.com underneath. Then the whole loader fades and adds .mil-hidden to disable pointer events.
HTML structure (minimal)
<div class="mil-preloader">
<div class="mil-preloader-animation">
<div class="mil-pos-abs mil-animation-1">
<p class="mil-h3 mil-muted mil-thin">Pioneering</p>
<p class="mil-h3 mil-muted">Creative</p>
<p class="mil-h3 mil-muted mil-thin">Excellence</p>
</div>
<div class="mil-pos-abs mil-animation-2">
<div class="mil-reveal-frame">
<p class="mil-reveal-box"></p>
<p class="mil-h3 mil-muted mil-thin">ashley.com</p>
</div>
</div>
</div>
</div>
Key SCSS tokens
.mil-preloader {
position: fixed; z-index: 9; inset: 0;
width: 100%; height: 100vh;
background-color: $dark;
& .mil-preloader-animation {
opacity: 0; position: relative; height: 100vh;
color: $light;
& .mil-pos-abs {
position: absolute; height: 100vh; width: 100%;
display: flex; justify-content: center; align-items: center;
& p { opacity: 0; margin-right: 15px; }
& .mil-reveal-frame {
position: relative; padding: 0 30px;
& .mil-reveal-box {
z-index: 4; position: absolute; opacity: 0;
height: 100%; background-color: $accent;
}
}
}
}
&.mil-hidden { pointer-events: none; }
}
Animation logic
const timeline = gsap.timeline();
timeline.to(".mil-preloader-animation", { opacity: 1 });
timeline.fromTo(".mil-animation-1 .mil-h3",
{ y: "30px", opacity: 0 },
{ y: "0px", opacity: 1, stagger: 0.4 });
timeline.to(".mil-animation-1 .mil-h3", { opacity: 0, y: '-30' }, "+=.3");
timeline.fromTo(".mil-reveal-box", 0.1, { opacity: 0 }, { opacity: 1, x: '-30' });
timeline.to(".mil-reveal-box", 0.45, { width: "100%", x: 0 }, "+=.1");
timeline.to(".mil-reveal-box", { right: "0" });
timeline.to(".mil-reveal-box", 0.3, { width: "0%" });
timeline.fromTo(".mil-animation-2 .mil-h3", { opacity: 0 }, { opacity: 1 }, "-=.5");
timeline.to(".mil-animation-2 .mil-h3", 0.6, { opacity: 0, y: '-30' }, "+=.5");
timeline.to(".mil-preloader", 0.8, { opacity: 0, ease: 'sine' }, "+=.2");
// hand-off to all .mil-up elements site-wide
timeline.fromTo(".mil-up", 0.8,
{ opacity: 0, y: 40, scale: .98, ease: 'sine' },
{ y: 0, opacity: 1, scale: 1,
onComplete: () => $('.mil-preloader').addClass("mil-hidden"),
}, "-=1");
Notable details
- One single GSAP timeline owns both the preloader and the first-paint reveal of every
.mil-upelement on the page, with the latter starting -1s before the preloader's opacity hits 0 — the hand-off is invisible. - Reveal box anchors switch from left to right mid-animation (
width: 100%, x: 0thenright: "0") so it appears to swipe in from the left and exit to the right — not a typical CSS keyframe trick. - Three text rows alternate between regular and
.mil-thin(100-weight) — the brand voice (mixed weights) is established before any content is visible. - Adding
mil-hiddenrather than removing the element keeps the preloader available for re-use (e.g., on Swup navigations), but the current code doesn't replay it.
Use when
- Brand-first sites that want to set the tonal voice before the hero loads.
- Pages with heavy hero animations where the preloader buys time for assets and primes the eye.
- When you want a single GSAP timeline to own both intro and section reveals (cleaner than separate hooks).
Caveats
- The preloader is only run once at page load — Swup navigations bypass it. If you need it on every navigation, dispatch the timeline from
swup:contentReplacedtoo. .mil-hiddenonly setspointer-events: none; the element remains in the DOM withopacity: 0. Visually fine, but accessibility tools may still announce it.- Preloader screenshot will rarely capture the timeline mid-flight — at 1440×900, by the time the page is
domcontentloadedthe loader is already in phase 2 or hidden. Treat the placeholder as expected.