WEBLEB
Home
Editor
Login
Pro
English
English
Français
Español
Português
Deutsch
Italiano
हिंदी
Galería de sitios animada y 3D
1758
Andev.web
Open In Editor
Publish Your Code
Recommended
22 May 2025
3d Three figures Sliders
16 December 2024
A Code by smartfunction263
28 May 2024
Delete button
HTML
Copy
Andev Web
Christ the
Redeemer
Rio de Janeiro
Iconic symbol of Brazil
Pyramids of
Teotihuacan
Mexico
Architectural wonder of ancient Mesoamerica
Machu Picchu
Peru
Lost city of the Incas
Loading...
CSS
Copy
@import url("https://fonts.googleapis.com/css2?family=Montserrat:wght@500;600;700;800&display=swap"); :root { --card-width: 200px; --card-height: 300px; --card-transition-duration: 800ms; --card-transition-easing: ease; } * { box-sizing: border-box; margin: 0; padding: 0; } body { width: 100%; height: 100vh; display: flex; justify-content: center; align-items: center; background: rgba(0, 0, 0, 0.787); overflow: hidden; } button { border: none; background: none; cursor: pointer; } button:focus { outline: none; border: none; } .app { position: relative; width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; } .app__bg { position: absolute; width: 100%; height: 100%; z-index: -5; filter: blur(8px); pointer-events: none; user-select: none; overflow: hidden; } .app__bg::before { content: ""; position: absolute; left: 0; top: 0; width: 100%; height: 100%; background: #000; z-index: 1; opacity: 0.8; } .app__bg__image { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%) translateX(var(--image-translate-offset, 0)); width: 180%; height: 180%; transition: transform 1000ms ease, opacity 1000ms ease; overflow: hidden; } .app__bg__image img { width: 100%; height: 100%; object-fit: cover; } .app__bg__image.current--image { opacity: 1; --image-translate-offset: 0; } .app__bg__image.previous--image, .app__bg__image.next--image { opacity: 0; } .app__bg__image.previous--image { --image-translate-offset: -25%; } .app__bg__image.next--image { --image-translate-offset: 25%; } .cardList { position: absolute; width: calc(3 * var(--card-width)); height: auto; } .cardList__btn { --btn-size: 35px; width: var(--btn-size); height: var(--btn-size); position: absolute; top: 50%; transform: translateY(-50%); z-index: 100; } .cardList__btn.btn--left { left: -5%; } .cardList__btn.btn--right { right: -5%; } .cardList__btn .icon { width: 100%; height: 100%; } .cardList__btn .icon svg { width: 100%; height: 100%; } .cardList .cards__wrapper { position: relative; width: 100%; height: 100%; perspective: 1000px; } .card { --card-translateY-offset: 100vh; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%) translateX(var(--card-translateX-offset)) translateY(var(--card-translateY-offset)) rotateY(var(--card-rotation-offset)) scale(var(--card-scale-offset)); display: inline-block; width: var(--card-width); height: var(--card-height); transition: transform var(--card-transition-duration) var(--card-transition-easing); user-select: none; } .card::before { content: ""; position: absolute; left: 0; top: 0; width: 100%; height: 100%; background: #000; z-index: 1; transition: opacity var(--card-transition-duration) var(--card-transition-easing); opacity: calc(1 - var(--opacity)); } /*Andev Web*/ .card__image { position: relative; width: 100%; height: 100%; } .card__image img { position: absolute; left: 0; top: 0; width: 100%; height: 100%; object-fit: cover; } .card.current--card { --current-card-rotation-offset: 0; --card-translateX-offset: 0; --card-rotation-offset: var(--current-card-rotation-offset); --card-scale-offset: 1.2; --opacity: 0.8; } .card.previous--card { --card-translateX-offset: calc(-1 * var(--card-width) * 1.1); --card-rotation-offset: 25deg; } .card.next--card { --card-translateX-offset: calc(var(--card-width) * 1.1); --card-rotation-offset: -25deg; } .card.previous--card, .card.next--card { --card-scale-offset: 0.9; --opacity: 0.4; } .infoList { position: absolute; width: calc(3 * var(--card-width)); height: var(--card-height); pointer-events: none; } .infoList .info__wrapper { position: relative; width: 100%; height: 100%; display: flex; justify-content: flex-start; align-items: flex-end; perspective: 1000px; transform-style: preserve-3d; } .info { margin-bottom: calc(var(--card-height) / 8); margin-left: calc(var(--card-width) / 1.5); transform: translateZ(2rem); transition: transform var(--card-transition-duration) var(--card-transition-easing); } .info .text { position: relative; font-family: "Montserrat"; font-size: calc(var(--card-width) * var(--text-size-offset, 0.2)); white-space: nowrap; color: #fff; width: fit-content; } .info .name, .info .location { text-transform: uppercase; } .info .location { font-weight: 800; } .info .location { --mg-left: 40px; --text-size-offset: 0.12; font-weight: 600; margin-left: var(--mg-left); margin-bottom: calc(var(--mg-left) / 2); padding-bottom: 0.8rem; } .info .location::before, .info .location::after { content: ""; position: absolute; background: #fff; left: 0%; transform: translate(calc(-1 * var(--mg-left)), -50%); } .info .location::before { top: 50%; width: 20px; height: 5px; } .info .location::after { bottom: 0; width: 60px; height: 2px; } .info .description { --text-size-offset: 0.065; font-weight: 500; } .info.current--info { opacity: 1; display: block; } .info.previous--info, .info.next--info { opacity: 0; display: none; } .loading__wrapper { position: fixed; left: 0; top: 0; width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center; background: #000; z-index: 200; } .loading__wrapper .loader--text { color: #fff; font-family: "Montserrat"; font-weight: 500; margin-bottom: 1.4rem; } .loading__wrapper .loader { position: relative; width: 200px; height: 2px; background: rgba(255, 255, 255, 0.25); } .loading__wrapper .loader span { position: absolute; left: 0; top: 0; width: 100%; height: 100%; background: red; transform: scaleX(0); transform-origin: left; } @media only screen and (min-width: 800px) { :root { --card-width: 250px; --card-height: 400px; } } .support { position: absolute; right: 10px; bottom: 10px; padding: 10px; display: flex; } .support a { margin: 0 10px; color: #fff; font-size: 1.8rem; backface-visibility: hidden; transition: all 150ms ease; } .support a:hover { transform: scale(1.1); }
JS
Copy
console.clear(); const { gsap, imagesLoaded } = window; const buttons = { prev: document.querySelector(".btn--left"), next: document.querySelector(".btn--right"), }; const cardsContainerEl = document.querySelector(".cards__wrapper"); const appBgContainerEl = document.querySelector(".app__bg"); const cardInfosContainerEl = document.querySelector(".info__wrapper"); buttons.next.addEventListener("click", () => swapCards("right")); buttons.prev.addEventListener("click", () => swapCards("left")); function swapCards(direction) { const currentCardEl = cardsContainerEl.querySelector(".current--card"); const previousCardEl = cardsContainerEl.querySelector(".previous--card"); const nextCardEl = cardsContainerEl.querySelector(".next--card"); const currentBgImageEl = appBgContainerEl.querySelector(".current--image"); const previousBgImageEl = appBgContainerEl.querySelector(".previous--image"); const nextBgImageEl = appBgContainerEl.querySelector(".next--image"); changeInfo(direction); swapCardsClass(); removeCardEvents(currentCardEl); function swapCardsClass() { currentCardEl.classList.remove("current--card"); previousCardEl.classList.remove("previous--card"); nextCardEl.classList.remove("next--card"); currentBgImageEl.classList.remove("current--image"); previousBgImageEl.classList.remove("previous--image"); nextBgImageEl.classList.remove("next--image"); currentCardEl.style.zIndex = "50"; currentBgImageEl.style.zIndex = "-2"; if (direction === "right") { previousCardEl.style.zIndex = "20"; nextCardEl.style.zIndex = "30"; nextBgImageEl.style.zIndex = "-1"; currentCardEl.classList.add("previous--card"); previousCardEl.classList.add("next--card"); nextCardEl.classList.add("current--card"); currentBgImageEl.classList.add("previous--image"); previousBgImageEl.classList.add("next--image"); nextBgImageEl.classList.add("current--image"); } else if (direction === "left") { previousCardEl.style.zIndex = "30"; nextCardEl.style.zIndex = "20"; previousBgImageEl.style.zIndex = "-1"; currentCardEl.classList.add("next--card"); previousCardEl.classList.add("current--card"); nextCardEl.classList.add("previous--card"); currentBgImageEl.classList.add("next--image"); previousBgImageEl.classList.add("current--image"); nextBgImageEl.classList.add("previous--image"); } } } function changeInfo(direction) { let currentInfoEl = cardInfosContainerEl.querySelector(".current--info"); let previousInfoEl = cardInfosContainerEl.querySelector(".previous--info"); let nextInfoEl = cardInfosContainerEl.querySelector(".next--info"); gsap.timeline() .to([buttons.prev, buttons.next], { duration: 0.2, opacity: 0.5, pointerEvents: "none", }) .to( currentInfoEl.querySelectorAll(".text"), { duration: 0.4, stagger: 0.1, translateY: "-120px", opacity: 0, }, "-=" ) .call(() => { swapInfosClass(direction); }) .call(() => initCardEvents()) .fromTo( direction === "right" ? nextInfoEl.querySelectorAll(".text") : previousInfoEl.querySelectorAll(".text"), { opacity: 0, translateY: "40px", }, { duration: 0.4, stagger: 0.1, translateY: "0px", opacity: 1, } ) .to([buttons.prev, buttons.next], { duration: 0.2, opacity: 1, pointerEvents: "all", }); function swapInfosClass() { currentInfoEl.classList.remove("current--info"); previousInfoEl.classList.remove("previous--info"); nextInfoEl.classList.remove("next--info"); if (direction === "right") { currentInfoEl.classList.add("previous--info"); nextInfoEl.classList.add("current--info"); previousInfoEl.classList.add("next--info"); } else if (direction === "left") { currentInfoEl.classList.add("next--info"); nextInfoEl.classList.add("previous--info"); previousInfoEl.classList.add("current--info"); } } } function updateCard(e) { const card = e.currentTarget; const box = card.getBoundingClientRect(); const centerPosition = { x: box.left + box.width / 2, y: box.top + box.height / 2, }; let angle = Math.atan2(e.pageX - centerPosition.x, 0) * (35 / Math.PI); gsap.set(card, { "--current-card-rotation-offset": `${angle}deg`, }); const currentInfoEl = cardInfosContainerEl.querySelector(".current--info"); gsap.set(currentInfoEl, { rotateY: `${angle}deg`, }); } function resetCardTransforms(e) { const card = e.currentTarget; const currentInfoEl = cardInfosContainerEl.querySelector(".current--info"); gsap.set(card, { "--current-card-rotation-offset": 0, }); gsap.set(currentInfoEl, { rotateY: 0, }); } function initCardEvents() { const currentCardEl = cardsContainerEl.querySelector(".current--card"); currentCardEl.addEventListener("pointermove", updateCard); currentCardEl.addEventListener("pointerout", (e) => { resetCardTransforms(e); }); } initCardEvents(); function removeCardEvents(card) { card.removeEventListener("pointermove", updateCard); } function init() { let tl = gsap.timeline(); tl.to(cardsContainerEl.children, { delay: 0.15, duration: 0.5, stagger: { ease: "power4.inOut", from: "right", amount: 0.1, }, "--card-translateY-offset": "0%", }) .to(cardInfosContainerEl.querySelector(".current--info").querySelectorAll(".text"), { delay: 0.5, duration: 0.4, stagger: 0.1, opacity: 1, translateY: 0, }) .to( [buttons.prev, buttons.next], { duration: 0.4, opacity: 1, pointerEvents: "all", }, "-=0.4" ); } const waitForImages = () => { const images = [...document.querySelectorAll("img")]; const totalImages = images.length; let loadedImages = 0; const loaderEl = document.querySelector(".loader span"); gsap.set(cardsContainerEl.children, { "--card-translateY-offset": "100vh", }); gsap.set(cardInfosContainerEl.querySelector(".current--info").querySelectorAll(".text"), { translateY: "40px", opacity: 0, }); gsap.set([buttons.prev, buttons.next], { pointerEvents: "none", opacity: "0", }); images.forEach((image) => { imagesLoaded(image, (instance) => { if (instance.isComplete) { loadedImages++; let loadProgress = loadedImages / totalImages; gsap.to(loaderEl, { duration: 1, scaleX: loadProgress, backgroundColor: `hsl(${loadProgress * 120}, 100%, 50%`, }); if (totalImages == loadedImages) { gsap.timeline() .to(".loading__wrapper", { duration: 0.8, opacity: 0, pointerEvents: "none", }) .call(() => init()); } } }); }); }; waitForImages();