https://codepen.io/BlazgoCompany/pen/dyBBRLp
I’m attempting to make a web site with a lot of scroll animations (the textual content has been masked). The primary animation with the zooming in star works very properly, however the second animation would not work. It performs the animation like regular, however as soon as it’s carried out, it would not return to the common scrolling. It also needs to proceed with the textual content beneath it after the animation is completed.
I’m fairly certain I have to set it to relative however can not seem to get it to work.
Additionally, please don’t counsel utilizing ScrollTrigger
as a result of it won’t keep on CodePen eternally, and I don’t wish to get Membership GSAP.
I’m unable to make use of Stack Snippets for some purpose so this is the complete code:
<div class="top-right">
<span class="cta-login">
<button class="my-dash btn-base">Lorem Ipsum</button>
</span>
</div>
<div class="nav">
<span class="brand">
<!-- Emblem Placeholder -->
</span>
<span class="cta-login">
<button class="login btn-base" onclick="openModal()">Login</button>
</span>
</div>
<div class="hero">
<h1 class="hero-text">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</h1>
</div>
<div class="content material">
<small class="subtitle">Sed do eiusmod tempor incididunt.</small>
<h2 model="margin-bottom: 0">
<span class="model gradient teal textual content">Lorem.</span>
<span class="model gradient blue textual content">Ipsum.</span>
</h2>
<h2 class="model gradient crimson textual content">Dolor Sit Amet.</h2>
<p model="shade: #999">Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. <span class="spotlight">Ut enim</span> advert minim veniam, quis nostrud <span class="spotlight">exercitation</span> ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
<button class="getstarted">Get Began</button>
<div class="spacer-240"></div>
<h1 class="tw-heading grey">Placeholder Heading</h1>
<div class="gen-card">
<h2>Placeholder Title</h2>
<h4>Placeholder Subtitle</h4>
<p>Placeholder textual content for description.</p>
</div>
<div class="gen-card">
<h2>Placeholder Title</h2>
<h4>Placeholder Subtitle</h4>
<p>Placeholder textual content for description.</p>
</div>
<div class="gen-card">
<h2>Placeholder Title</h2>
<h4>Placeholder Subtitle</h4>
<p>Placeholder textual content for description.</p>
</div>
<div class="gen-card">
<h2>Placeholder Title</h2>
<h4 class="anim model crimson textual content">Placeholder Subtitle</h4>
<p>Placeholder textual content for description.</p>
</div>
This textual content ought to seem after this scroll animation (but it surely would not!)
</div>
@import url('https://fonts.googleapis.com/css?household=Nunito:200,200i');
@import url('https://fonts.googleapis.com/css?household=Roboto:300,400,500');
@import url('https://fonts.googleapis.com/css?household=Varela+Spherical');
/* Import fonts */
/* International Types */
physique {
background: black;
overflow-x: hidden;
min-height: 800vh;
margin: 0;
font-family: sans-serif;
/* Fallback font */
}
enter {
padding: 12px;
width: 80%;
border-radius: 8px;
border: none;
left: 50%;
place: relative;
remodel: translate(-50%);
margin-top: 42px;
}
.hero {
padding: 16px;
place: fastened;
width: 100%;
top: 100vh;
background: radial-gradient(circle at 0% -10%, var(--gradient-color), clear 38%);
}
.hero-text {
shade: white !essential;
font-size: 64px;
font-family: "Varela Spherical", sans-serif;
/* Default to Varela Spherical, fallback to sans-serif */
show: inline-block;
place: relative;
z-index: 10;
}
.hero-text svg {
remodel: translateY(-4px);
show: inline;
vertical-align: center;
background-color: clear;
}
.content material {
shade: white;
show: none;
font-family: "Varela Spherical";
text-align: heart;
}
.spotlight {
shade: #e3b505;
}
.btn-base,
.modal .login,
.backbtn {
border-radius: 20px;
border: none;
padding: 0 12px;
top: 30px;
background: #e3b505;
font-size: 16px;
font-weight: daring;
}
.btn-base:hover,
.modal .login:hover,
.backbtn:hover {
background: #c8a104;
}
.getstarted {
padding: 8px 16px;
border-radius: 32px;
top: auto;
}
.nav {
place: fastened;
prime: -36px;
background: radial-gradient(circle at 0% heart, #066ab2, clear 80%);
backdrop-filter: blur(8px);
width: calc(100% - 32px);
top: 36px;
z-index: 1000;
left: 50%;
remodel: translate(-50%, 0);
max-width: 500px;
border-radius: 32px;
}
button:energetic {
remodel: scale(0.9)
}
button {
transition: remodel 0.1s;
}
.btncontainer {
margin-top: 48px;
left: 50%;
place: relative;
remodel: translate(-50%);
show: inline-block;
}
.btn-close {
place: absolute;
proper: 8px;
prime: 8px;
width: 32px;
top: 32px;
background: #95190C;
shade: white
}
.btn-close:hover {
background: #711409;
}
.loader {
top: 24px;
width: 24px;
border: 3px stable clear;
border-bottom: 3px stable black;
border-radius: 32px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% {
remodel: rotate(0deg);
}
100% {
remodel: rotate(360deg);
}
}
.login-modal h1 {
font-size: 24px;
font-weight: daring;
text-align: heart;
margin-bottom: -20
}
.model.gradient.teal.textual content {
background: #107E7D;
background: -webkit-linear-gradient(#28E2DF, #0C5A59);
-webkit-background-clip: textual content;
-webkit-text-fill-color: clear;
}
.model.gradient.blue.textual content {
background: #066AB1;
background: -webkit-linear-gradient(#89CBFB, #05528A);
-webkit-background-clip: textual content;
-webkit-text-fill-color: clear;
}
.model.gradient.blue.further {
background: #066AB1;
background: -webkit-linear-gradient(#C4E5FD, #05528A);
-webkit-background-clip: textual content;
-webkit-text-fill-color: clear;
}
.model.gradient.crimson.textual content {
margin-top: 0;
background: #971A0C;
background: -webkit-linear-gradient(#F6877B, #711409);
-webkit-background-clip: textual content;
-webkit-text-fill-color: clear;
}
h2 {
font-size: 32px;
}
.subtitle {
font-size: 14px;
background: -webkit-linear-gradient(#eee, #3f3f3f);
-webkit-background-clip: textual content;
-webkit-text-fill-color: clear;
}
.subtitle::after,
.subtitle::earlier than {
content material: '';
width: 64px;
top: 1px;
show: inline-block;
}
.subtitle::earlier than {
remodel: translate(-8px, -4px);
background: linear-gradient(-90deg, #aaa 0%, clear 100%);
proper: 120%;
prime: 50%;
}
.subtitle::after {
remodel: translate(8px, -4px);
background: linear-gradient(90deg, #aaa 0%, clear 100%);
left: 120%;
prime: 50%;
}
h1.grey.tw-heading {
font-size: 48px;
background: -webkit-linear-gradient(#eee, #333);
-webkit-background-clip: textual content;
-webkit-text-fill-color: clear;
}
.spacer-240 {
top: 240px;
}
.gen-card {
width: calc(25% - 14px);
margin: 0 4px;
show: inline-block;
top: 360;
background: clear;
backdrop-filter: blur(4px);
opacity: 0;
border-radius: 16px;
text-align: heart;
padding: 12px;
border: 1px stable #555
}
.gen-card h2 {
margin: 0;
}
.fastened {
place: fastened;
}
.relative{
place: relative;
}
/* .anim.model.crimson.textual content{
margin-top: 0;
background: #971A0C;
background: -webkit-linear-gradient(#F6877B, #711409);
-webkit-background-clip: textual content;
-webkit-text-fill-color: clear;
} */
perform setTransformOriginToChild() {
const mother or father = doc.querySelector('.hero-text');
const baby = doc.querySelector('.hero-text .star');
const parentRect = mother or father.getBoundingClientRect();
const childRect = baby.getBoundingClientRect();
const childCenterX = (childRect.left - 10 + childRect.proper) / 2;
const childCenterY = (childRect.prime + 4 + childRect.backside) / 2;
const transformOriginX = (childCenterX - parentRect.left) / parentRect.width * 100;
const transformOriginY = (childCenterY - parentRect.prime) / parentRect.top * 100;
mother or father.model.transformOrigin = `${transformOriginX}% ${transformOriginY}%`;
}
window.addEventListener('resize', setTransformOriginToChild);
// Perform to separate textual content into a number of spans
perform splitTextIntoSpans() {
// Get the container factor
const container = doc.querySelector('.hero-text');
// Get the textual content content material of the container
const textual content = container.textContent;
// Create a doc fragment to carry the brand new span parts
const fragment = doc.createDocumentFragment();
// Outline phrases to model
const wordsToStyle = {
'future': '#066AB2',
'sit': '#066AB2'
};
// Helper perform to create span parts for textual content
perform createSpansForText(textual content, shade="") {
const fragment = doc.createDocumentFragment();
for (let char of textual content) {
const span = doc.createElement('span');
span.textContent = char;
if (shade) {
span.classList.add("model")
span.classList.add("gradient")
span.classList.add("blue")
span.classList.add("textual content")
span.classList.add("further")
}
fragment.appendChild(span);
}
return fragment;
}
// Course of the textual content letter by letter
let index = 0;
whereas (index < textual content.size) {
// Discover the subsequent phrase or house
let nextSpace = textual content.indexOf(' ', index);
if (nextSpace === -1) {
nextSpace = textual content.size;
}
var phrase = textual content.slice(index, nextSpace);
// Add an area character after the phrase
if (nextSpace < textual content.size) {
phrase += ' ';
}
// Create spans for every letter of the phrase
const shade = wordsToStyle[word.trim()] || '';
const wordFragment = createSpansForText(phrase, shade);
fragment.appendChild(wordFragment);
// If the phrase add a particular span factor after it
if (phrase.trim() === 'sit') {
const starSpan = doc.createElement('span');
starSpan.className="star";
starSpan.innerHTML = `
<svg width="32" top="24">
<path d="M 2 12 q 10 0 10 -10 q 0 10 10 10 q -10 0 -10 10 q 0 -10 -10 -10 M 0 12 A 1 1 0 0 0 24 12 A 1 1 0 0 0 0 12"></path>
</svg>`;
fragment.appendChild(starSpan);
}
// Transfer to the subsequent phrase
index = nextSpace + 1;
}
// Clear the unique container
container.textContent="";
// Append the fragment to the container
container.appendChild(fragment);
}
perform calculateTravelDistance() {
// Get the .star factor
const starElement = doc.querySelector('.hero-text .star');
// Get the bounding rectangle of the .star factor
const starRect = starElement.getBoundingClientRect();
// Get the middle of the .star factor
const starCenterX = starRect.left + starRect.width / 2;
const starCenterY = starRect.prime + starRect.top / 2;
// Get the middle of the display
const screenCenterX = window.innerWidth / 2;
const screenCenterY = window.innerHeight / 2;
// Calculate the quantity to maneuver the factor
const moveX = screenCenterX - starCenterX;
const moveY = screenCenterY - starCenterY;
return { moveX, moveY };
}
// Name the perform to separate the textual content
window.addEventListener('load', () => {
splitTextIntoSpans();
setTransformOriginToChild()
tl = gsap.timeline({
})
tl.set(".hero-text span", { filter: "blur(32px)" })
tl.set(".hero", { "--gradient-color": "#FFD700" })
tl.set(".hero-text svg", { fill: "white" })
tl.to(".hero-text span", { filter: "blur(0px)", period: 0.5, stagger: 0.05 })
tl.to(".top-right", { opacity: 0, period: 0.8 }, "<+=1.2")
tl.to(".hero-text", { y: calculateTravelDistance().moveY, x: calculateTravelDistance().moveX, period: 3, fill: "black", ease: "power4.in" }, "+=0.5")
tl.to(".hero-text", { scale: 90, period: 3, ease: "power4.in" }, "<")
tl.to(".hero-text svg", { period: 1, fill: "black", background: "clear" }, "-=1")
tl.to(".hero", { period: 1, "--gradient-color": "#000" }, "-=1")
tl.to(".nav", { period: 1, prime: "16px" }, "-=1")
tl.pause(0.5)
});
var gentlmarker = 1000000
var gentl = 0
doc.addEventListener("scroll", () => {
//get scroll place
const scrollPosition = window.scrollY;
if ((scrollPosition / 200) + 0.5 < 5.8) {
gsap.set(".hero", { show: "block" })
gsap.set(".content material", { show: "none" })
tl.pause((scrollPosition / 200) + 0.5)
}
else {
gsap.set(".hero", { show: "block" })
gsap.set(".content material", { show: "none" })
tl.pause((scrollPosition / 200) + 0.5)
gsap.set(".hero", { show: "none" })
gsap.set(".content material", { place: "relative", prime: 1060 + window.innerHeight, show: "block" })
}
if(doc.querySelector(".tw-heading").getBoundingClientRect().prime < 200 && scrollPosition > 1800){
//"pin" the tw-heading and the gencards for 300 px of scrolling
gsap.set(".tw-heading", {place: "fastened", prime: 200-32, left: "50%", xPercent: -50, width: "100%"})
gc = doc.querySelectorAll(".gen-card")
gcw = gc[0].getBoundingClientRect().width
gsap.set(".gen-card", {place: "fastened", opacity: 1, prime: 264, proper: -gcw})
gentl=gsap.timeline({})
// gentl.to(gc[0], {place: "fastened", prime: 264, left: 8})
// gentl.to(gc[1], {place: "fastened", prime: 264, left: 8+gcw+8})
// gentl.to(gc[2], {place: "fastened", prime: 264, left: 8+gcw+8+gcw+8})
// gentl.to(gc[3], {place: "fastened", prime: 264, left: 8+gcw+8+gcw+8+gcw+8})
// Widespread properties for the animation
const commonProps = {
place: "fastened",
prime: 264
};
// Outline the beginning place and finish positions for gc parts
const startPosition = -200;
const endPositionFirst = -gcw;
const endPositionLast = 32;
// Create a timeline animation with stagger
gentl.to(gc, {
...commonProps,
left: endPositionFirst,
stagger: 0.2, // Stagger by 0.1 seconds for every factor
period: 1, // Regulate period to your choice
ease: "power1.inOut" // Instance easing perform
})
.to(gc[gc.length - 1], {
left: endPositionLast,
period: 1, // Similar period as above to maintain consistency
ease: "power1.inOut" // Use the identical easing perform
}, "-=1")
.to(gc[3], {
width: "50%",
left: "50%",
x: "-50%",
period: 1, // Similar period as above to maintain consistency
ease: "power1.inOut"
})
.addLabel("fgenfocus")
.to(gc[3].querySelector("h2"), {
opacity: 0
}, "fgenfocus")
.to(gc[3].querySelector("h2"), {
opacity: 0,
top: "0px",
margin: 0
}, "fgenfocus")
.add(perform(){
gc[3].querySelector("h4").innerHTML="Now the th scrolling ought to proceed as regular"
}, "fgenfocus")
.to(gc[3].querySelector("h4"), {
fontSize: "32px",
margin: 0
}, "fgenfocus")
// gentl.to([gc[0], gc[1], gc[2]], {width: 0})
gentl.pause()
gentlmarker = scrollPosition
}
if(scrollPosition>gentlmarker){
gc = doc.querySelectorAll(".gen-card")
gcw = gc[0].getBoundingClientRect().width
console.log(gentlmarker)
console.log((scrollPosition-gentlmarker)/300)
console.log("----------------")
gentl.pause((scrollPosition-gentlmarker)/300)
}
if((scrollPosition-gentlmarker)/300 < 0){
gsap.set(".tw-heading", {place: "static", xPercent: 0})
gsap.set(".gen-card", { opacity: 0 })
}
})
doc.querySelector(".getstarted").addEventListener("click on", () => {
let clickTl = gsap.timeline({})
clickTl.to(".getstarted", { scale: 100, period: 2, ease: "power4.in" })
clickTl.to(".getstarted", { background: "black", shade: "black", period: 1, ease: "power4.in" }, "-=1")
})
Thanks!