diff --git a/script.js b/script.js index 5f87a36..49b9f3a 100644 --- a/script.js +++ b/script.js @@ -523,26 +523,44 @@ var si = 0, c.el.classList.add('server-best'); } }); - /* Preload city image and animate reveal */ + /* Preload city image and carousel-slide */ var hero = document.querySelector('.hero'); var bestCard = cards.filter(function(c) { return c.server.host === best.host; })[0]; if (hero && bestCard && heroImages[best.host]) { var img = new Image(); img.onload = function() { - /* Reveal overlay — slides left-to-right via clip-path */ - var reveal = document.createElement('div'); - reveal.className = 'hero-city-reveal'; - reveal.style.backgroundImage = "url('" + heroImages[best.host] + "')"; - hero.appendChild(reveal); - /* Label — slides right-to-left simultaneously */ + /* Create background container on first swap */ + var bg = hero.querySelector('.hero-bg'); + if (!bg) { + bg = document.createElement('div'); + bg.className = 'hero-bg'; + hero.insertBefore(bg, hero.firstChild); + } + /* Old slide — starts at current position, slides out right */ + var oldEl = document.createElement('div'); + oldEl.className = 'hero-bg-slide old'; + oldEl.style.backgroundImage = "url('images/city-amsterdam.jpg')"; + bg.appendChild(oldEl); + /* New slide — starts off-screen right, slides in */ + var newEl = document.createElement('div'); + newEl.className = 'hero-bg-slide new'; + newEl.style.backgroundImage = "url('" + heroImages[best.host] + "')"; + bg.appendChild(newEl); + /* Fire both animations together */ + requestAnimationFrame(function() { + oldEl.classList.add('out'); + newEl.classList.add('in'); + }); + /* Label slides in from right */ var label = document.createElement('div'); label.className = 'hero-city-label'; label.innerHTML = 'Our ' + bestCard.server.city + ' server fits your location'; hero.appendChild(label); requestAnimationFrame(function() { - reveal.classList.add('open'); label.classList.add('visible'); }); + /* Clean up old slide after animation done */ + setTimeout(function() { oldEl.remove(); }, 1200); }; img.src = heroImages[best.host]; } diff --git a/style.css b/style.css index 2fc0eb5..5fc868f 100644 --- a/style.css +++ b/style.css @@ -112,10 +112,37 @@ img { max-width: 100%; height: auto; vertical-align: middle; } content: ''; position: absolute; inset: 0; - background: var(--hero-bg, url('images/city-amsterdam.jpg')) center/cover no-repeat; - opacity: 0.12; + background: var(--midnight); + opacity: 0.6; z-index: 0; - transition: background-image 0.8s cubic-bezier(0.16, 1, 0.3, 1); +} +.hero-bg { + position: absolute; + inset: 0; + z-index: 0; + overflow: hidden; +} +.hero-bg-slide { + position: absolute; + inset: 0; + background-size: cover; + background-position: center; + background-repeat: no-repeat; + opacity: 0.12; + transition: transform 1s cubic-bezier(0.16, 1, 0.3, 1); + will-change: transform; +} +.hero-bg-slide.old { + transform: translateX(0); +} +.hero-bg-slide.old.out { + transform: translateX(100%); +} +.hero-bg-slide.new { + transform: translateX(100%); +} +.hero-bg-slide.new.in { + transform: translateX(0); } .hero .container { position: relative; z-index: 1; flex: 1; display: flex; flex-direction: column; justify-content: center; } .hero-kicker { @@ -377,21 +404,6 @@ img { max-width: 100%; height: auto; vertical-align: middle; } } } -.hero-city-reveal { - position: absolute; - inset: 0; - background-size: cover; - background-position: center; - background-repeat: no-repeat; - opacity: 0.12; - z-index: 0; - clip-path: inset(0 100% 0 0); - will-change: clip-path; - pointer-events: none; -} -.hero-city-reveal.open { - clip-path: inset(0 0 0 0); -} .hero-city-label { position: absolute; bottom: 2rem;