WEBLEB
Inicio
Editora de código
Iniciar sesión
Pro
Español
English
Français
Español
Secciones continuas animadas con GSAP Observer
1696
Andev.web
Abrir en el editor
Publica tu código
1
Recomendado
12 July 2025
Encabezado fijo controlado por desplazamiento
31 January 2026
Casa secundaria con fondo colorido
23 May 2025
Inicio de sesión con tarjeta
HTML
Copy
Andev Web
Scroll down
Animated with GSAP
GreenSock
Animation platform
Keep scrolling
CSS
Copy
@import url("https://fonts.googleapis.com/css2?family=Bebas+Neue&display=swap"); @import url("https://fonts.googleapis.com/css2?family=Cormorant+Garamond&display=swap"); * { box-sizing: border-box; user-select: none; } a { color: #fff; text-decoration: none; } body { margin: 0; padding: 0; height: 100vh; color: white; background: black; font-family: "Cormorant Garamond", serif; text-transform: uppercase; } h2 { font-size: clamp(1rem, 5vw, 5rem); font-weight: 400; text-align: center; letter-spacing: 0.5em; margin-right: -0.5em; color: #cccccc; width: 90vw; max-width: 1200px; } header { position: fixed; display: flex; align-items: center; justify-content: space-between; padding: 0 5%; width: 100%; z-index: 3; height: 7em; font-family: "Bebas Neue", sans-serif; font-size: clamp(0.66rem, 2vw, 1rem); letter-spacing: 0.5em; } section { height: 100%; width: 100%; top: 0; position: fixed; visibility: hidden; } section .outer, section .inner { width: 100%; height: 100%; overflow-y: hidden; } section .bg { display: flex; align-items: center; justify-content: center; position: absolute; height: 100%; width: 100%; top: 0; background-size: cover; background-position: center; } section .bg h2 { z-index: 2; } section .bg .clip-text { overflow: hidden; } .first .bg { background-image: linear-gradient(180deg, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.3) 100%), url(https://images.unsplash.com/photo-1617478755490-e21232a5eeaf?crop=entropy&cs=srgb&fm=jpg&ixid=MnwxNDU4OXwwfDF8cmFuZG9tfHx8fHx8fHx8MTYxNzU1NjM5NA&ixlib=rb-1.2.1&q=75&w=1920); } .second .bg { background-image: linear-gradient(180deg, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.3) 100%), url("https://images.unsplash.com/photo-1617128734662-66da6c1d3505?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxNDU4OXwwfDF8cmFuZG9tfHx8fHx8fHx8MTYxNzc3NTM3MA&ixlib=rb-1.2.1&q=75&w=1920"); } .third .bg { background-image: linear-gradient(180deg, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.3) 100%), url(https://images.unsplash.com/photo-1617438817509-70e91ad264a5?crop=entropy&cs=srgb&fm=jpg&ixid=MnwxNDU4OXwwfDF8cmFuZG9tfHx8fHx8fHx8MTYxNzU2MDk4Mg&ixlib=rb-1.2.1&q=75&w=1920); } .fourth .bg { background-image: linear-gradient(180deg, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.3) 100%), url(https://images.unsplash.com/photo-1617412327653-c29093585207?crop=entropy&cs=srgb&fm=jpg&ixid=MnwxNDU4OXwwfDF8cmFuZG9tfHx8fHx8fHx8MTYxNzU2MDgzMQ&ixlib=rb-1.2.1&q=75&w=1920); } .fifth .bg { background-image: linear-gradient(180deg, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.3) 100%), url("https://images.unsplash.com/photo-1617141636403-f511e2d5dc17?crop=entropy&cs=srgb&fm=jpg&ixid=MnwxNDU4OXwwfDF8cmFuZG9tfHx8fHx8fHx8MTYxODAzMjc4Mw&ixlib=rb-1.2.1&q=75w=1920"); background-position: 50% 45%; } h2 * { will-change: transform; }
JS
Copy
gsap.registerPlugin(Observer); let sections = document.querySelectorAll("section"), images = document.querySelectorAll(".bg"), headings = gsap.utils.toArray(".section-heading"), outerWrappers = gsap.utils.toArray(".outer"), innerWrappers = gsap.utils.toArray(".inner"), splitHeadings = headings.map(heading => new SplitText(heading, { type: "chars,words,lines", linesClass: "clip-text" })), currentIndex = -1, wrap = gsap.utils.wrap(0, sections.length), animating; gsap.set(outerWrappers, { yPercent: 100 }); gsap.set(innerWrappers, { yPercent: -100 }); function gotoSection(index, direction) { index = wrap(index); // make sure it's valid animating = true; let fromTop = direction === -1, dFactor = fromTop ? -1 : 1, tl = gsap.timeline({ defaults: { duration: 1.25, ease: "power1.inOut" }, onComplete: () => animating = false }); if (currentIndex >= 0) { // The first time this function runs, current is -1 gsap.set(sections[currentIndex], { zIndex: 0 }); tl.to(images[currentIndex], { yPercent: -15 * dFactor }) .set(sections[currentIndex], { autoAlpha: 0 }); } gsap.set(sections[index], { autoAlpha: 1, zIndex: 1 }); tl.fromTo([outerWrappers[index], innerWrappers[index]], { yPercent: i => i ? -100 * dFactor : 100 * dFactor }, { yPercent: 0 }, 0) .fromTo(images[index], { yPercent: 15 * dFactor }, { yPercent: 0 }, 0) .fromTo(splitHeadings[index].chars, { autoAlpha: 0, yPercent: 150 * dFactor }, { autoAlpha: 1, yPercent: 0, duration: 1, ease: "power2", stagger: { each: 0.02, from: "random" } }, 0.2); currentIndex = index; } Observer.create({ type: "wheel,touch,pointer", wheelSpeed: -1, onDown: () => !animating && gotoSection(currentIndex - 1, -1), onUp: () => !animating && gotoSection(currentIndex + 1, 1), tolerance: 10, preventDefault: true }); gotoSection(0, 1);