
Weather animation
An animated weather card
Prompt
Create a single HTML file containing CSS and JavaScript to generate an animated weather card. The card should visually represent the following weather conditions with distinct animations: Wind: (e.g., moving clouds, swaying trees, or wind lines) Rain: (e.g., falling raindrops, puddles forming) Sun: (e.g., shining rays, bright background) Snow: (e.g., falling snowflakes, snow accumulating) Show all the weather card side by side The card should have a dark background. Provide all the HTML, CSS, and JavaScript code within this single file. The JavaScript should include a way to switch between the different weather conditions (e.g., a function or a set of buttons polished) to demonstrate refined the animations for each. UI meets Apple's premium-quality standard for stunning visual design.
A system prompt was added to support web rendering
```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Premium Weather Cards</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } body { background: #000; display: flex; flex-direction: column; align-items: center; min-height: 100vh; padding: 40px 20px; } .header { color: white; text-align: center; margin-bottom: 40px; } .header h1 { font-size: 2.5rem; font-weight: 600; margin-bottom: 10px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } .header p { color: #a0a0a0; font-size: 1.1rem; max-width: 600px; line-height: 1.6; } .controls { display: flex; gap: 15px; margin-bottom: 40px; flex-wrap: wrap; justify-content: center; } .control-btn { background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.2); color: white; padding: 12px 24px; border-radius: 16px; cursor: pointer; font-size: 1rem; font-weight: 500; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); backdrop-filter: blur(10px); } .control-btn:hover { background: rgba(255, 255, 255, 0.2); transform: translateY(-2px); box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3); } .control-btn.active { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-color: transparent; box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3); } .weather-cards { display: flex; gap: 30px; flex-wrap: wrap; justify-content: center; } .weather-card { width: 320px; height: 450px; border-radius: 24px; position: relative; overflow: hidden; background: linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 100%); box-shadow: 0 25px 50px rgba(0, 0, 0, 0.5); border: 1px solid rgba(255, 255, 255, 0.1); transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1); } .weather-card:hover { transform: translateY(-10px); box-shadow: 0 35px 60px rgba(0, 0, 0, 0.6); } .card-header { padding: 25px; text-align: center; } .weather-icon { font-size: 3.5rem; margin-bottom: 15px; } .weather-title { color: white; font-size: 1.8rem; font-weight: 600; margin-bottom: 5px; } .weather-desc { color: #a0a0a0; font-size: 1rem; font-weight: 400; } .card-content { padding: 0 25px 25px; } .temp { color: white; font-size: 3.5rem; font-weight: 300; text-align: center; margin-bottom: 20px; } .weather-details { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; } .detail-item { background: rgba(255, 255, 255, 0.05); border-radius: 16px; padding: 15px; text-align: center; backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.05); } .detail-label { color: #a0a0a0; font-size: 0.9rem; margin-bottom: 5px; } .detail-value { color: white; font-size: 1.2rem; font-weight: 500; } /* Wind Animation */ .wind-animation { position: absolute; top: 0; left: 0; width: 100%; height: 60%; overflow: hidden; } .wind-line { position: absolute; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); height: 2px; animation: windMove 3s linear infinite; } .cloud { position: absolute; background: rgba(255, 255, 255, 0.8); border-radius: 50%; animation: cloudFloat 8s linear infinite; } .tree { position: absolute; bottom: 0; width: 8px; background: #8B4513; transform-origin: bottom; } .tree-top { position: absolute; bottom: 20px; left: -12px; width: 32px; height: 32px; background: #228B22; border-radius: 50%; clip-path: polygon(50% 0%, 0% 100%, 100% 100%); } /* Rain Animation */ .rain-animation { position: absolute; top: 0; left: 0; width: 100%; height: 60%; overflow: hidden; } .raindrop { position: absolute; background: linear-gradient(to bottom, rgba(173, 216, 230, 0.8), rgba(135, 206, 250, 0.9)); width: 2px; height: 15px; border-radius: 0 0 2px 2px; animation: rainFall 1s linear infinite; } .puddle { position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); width: 80px; height: 8px; background: rgba(173, 216, 230, 0.3); border-radius: 50%; animation: puddleRipple 2s ease-in-out infinite; } /* Sun Animation */ .sun-animation { position: absolute; top: 20%; left: 50%; transform: translateX(-50%); width: 100px; height: 100px; } .sun-core { width: 60px; height: 60px; background: radial-gradient(circle, #FFD700, #FFA500); border-radius: 50%; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); box-shadow: 0 0 30px #FFA500, 0 0 60px rgba(255, 165, 0, 0.5); animation: sunPulse 3s ease-in-out infinite; } .sun-ray { position: absolute; background: linear-gradient(to right, transparent, #FFD700, transparent); height: 3px; border-radius: 2px; transform-origin: left center; } /* Snow Animation */ .snow-animation { position: absolute; top: 0; left: 0; width: 100%; height: 60%; overflow: hidden; } .snowflake { position: absolute; color: #fff; font-size: 1.2rem; animation: snowFall 4s linear infinite; text-shadow: 0 0 5px rgba(255, 255, 255, 0.8); } .snow-ground { position: absolute; bottom: 0; width: 100%; height: 20px; background: linear-gradient(to top, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.4)); border-radius: 10px 10px 0 0; animation: snowAccumulate 10s ease-in-out infinite; } /* Animations */ @keyframes windMove { 0% { transform: translateX(-100%); opacity: 0; } 10% { opacity: 1; } 90% { opacity: 1; } 100% { transform: translateX(100%); opacity: 0; } } @keyframes cloudFloat { 0% { transform: translateX(-50px); } 100% { transform: translateX(370px); } } @keyframes rainFall { 0% { transform: translateY(-20px); opacity: 0; } 10% { opacity: 1; } 90% { opacity: 1; } 100% { transform: translateY(300px); opacity: 0; } } @keyframes puddleRipple { 0%, 100% { transform: translateX(-50%) scale(1); opacity: 0.3; } 50% { transform: translateX(-50%) scale(1.1); opacity: 0.5; } } @keyframes sunPulse { 0%, 100% { transform: translate(-50%, -50%) scale(1); } 50% { transform: translate(-50%, -50%) scale(1.1); } } @keyframes snowFall { 0% { transform: translateY(-20px) rotate(0deg); opacity: 0; } 10% { opacity: 1; } 90% { opacity: 1; } 100% { transform: translateY(300px) rotate(360deg); opacity: 0; } } @keyframes snowAccumulate { 0%, 100% { height: 15px; } 50% { height: 25px; } } /* Responsive Design */ @media (max-width: 768px) { .weather-cards { flex-direction: column; align-items: center; } .weather-card { width: 100%; max-width: 350px; } } </style> </head> <body> <div class="header"> <h1>Premium Weather Experience</h1> <p>Experience stunning weather animations with Apple-quality design and smooth transitions</p> </div> <div class="controls"> <button class="control-btn active" data-weather="wind">Wind</button> <button class="control-btn" data-weather="rain">Rain</button> <button class="control-btn" data-weather="sun">Sun</button> <button class="control-btn" data-weather="snow">Snow</button> </div> <div class="weather-cards"> <div class="weather-card" id="wind-card"> <div class="wind-animation" id="wind-animation"></div> <div class="card-header"> <div class="weather-icon">💨</div> <h2 class="weather-title">Windy</h2> <p class="weather-desc">Strong gusts and moving clouds</p> </div> <div class="card-content"> <div class="temp">22°</div> <div class="weather-details"> <div class="detail-item"> <div class="detail-label">Wind Speed</div> <div class="detail-value">24 mph</div> </div> <div class="detail-item"> <div class="detail-label">Humidity</div> <div class="detail-value">65%</div> </div> <div class="detail-item"> <div class="detail-label">Pressure</div> <div class="detail-value">1013 hPa</div> </div> <div class="detail-item"> <div class="detail-label">Visibility</div> <div class="detail-value">10 km</div> </div> </div> </div> </div> <div class="weather-card" id="rain-card"> <div class="rain-animation" id="rain-animation"></div> <div class="card-header"> <div class="weather-icon">🌧️</div> <h2 class="weather-title">Rainy</h2> <p class="weather-desc">Steady rainfall and forming puddles</p> </div> <div class="card-content"> <div class="temp">18°</div> <div class="weather-details"> <div class="detail-item"> <div class="detail-label">Rainfall</div> <div class="detail-value">5mm</div> </div> <div class="detail-item"> <div class="detail-label">Humidity</div> <div class="detail-value">85%</div> </div> <div class="detail-item"> <div class="detail-label">Pressure</div> <div class="detail-value">1008 hPa</div> </div> <div class="detail-item"> <div class="detail-label">Visibility</div> <div class="detail-value">2 km</div> </div> </div> </div> </div> <div class="weather-card" id="sun-card"> <div class="sun-animation" id="sun-animation"></div> <div class="card-header"> <div class="weather-icon">☀️</div> <h2 class="weather-title">Sunny</h2> <p class="weather-desc">Bright sunshine and clear skies</p> </div> <div class="card-content"> <div class="temp">28°</div> <div class="weather-details"> <div class="detail-item"> <div class="detail-label">UV Index</div> <div class="detail-value">8</div> </div> <div class="detail-item"> <div class="detail-label">Humidity</div> <div class="detail-value">45%</div> </div> <div class="detail-item"> <div class="detail-label">Pressure</div> <div class="detail-value">1020 hPa</div> </div> <div class="detail-item"> <div class="detail-label">Visibility</div> <div class="detail-value">15 km</div> </div> </div> </div> </div> <div class="weather-card" id="snow-card"> <div class="snow-animation" id="snow-animation"></div> <div class="card-header"> <div class="weather-icon">❄️</div> <h2 class="weather-title">Snowy</h2> <p class="weather-desc">Falling snow and accumulation</p> </div> <div class="card-content"> <div class="temp">-2°</div> <div class="weather-details"> <div class="detail-item"> <div class="detail-label">Snowfall</div> <div class="detail-value">8cm</div> </div> <div class="detail-item"> <div class="detail-label">Humidity</div> <div class="detail-value">90%</div> </div> <div class="detail-item"> <div class="detail-label">Pressure</div> <div class="detail-value">1005 hPa</div> </div> <div class="detail-item"> <div class="detail-label">Visibility</div> <div class="detail-value">1 km</div> </div> </div> </div> </div> </div> <script> // Wind Animation function createWindAnimation() { const container = document.getElementById('wind-animation'); container.innerHTML = ''; // Create wind lines for (let i = 0; i < 15; i++) { const line = document.createElement('div'); line.className = 'wind-line'; line.style.top = Math.random() * 100 + '%'; line.style.width = (20 + Math.random() * 30) + '%'; line.style.animationDelay = Math.random() * 3 + 's'; container.appendChild(line); } // Create clouds for (let i = 0; i < 5; i++) { const cloud = document.createElement('div'); cloud.className = 'cloud'; cloud.style.width = (30 + Math.random() * 40) + 'px'; cloud.style.height = (15 + Math.random() * 20) + 'px'; cloud.style.top = (20 + Math.random() * 40) + '%'; cloud.style.animationDuration = (6 + Math.random() * 6) + 's'; cloud.style.animationDelay = Math.random() * 4 + 's'; container.appendChild(cloud); } // Create trees for (let i = 0; i < 3; i++) { const tree = document.createElement('div'); tree.className = 'tree'; tree.style.left = (20 + i * 30) + '%'; tree.style.height = (40 + Math.random() * 20) + 'px'; const treeTop = document.createElement('div'); treeTop.className = 'tree-top'; tree.appendChild(treeTop); container.appendChild(tree); // Animate tree sway animateTree(tree); } } function animateTree(tree) { const sway = () => { const angle = (Math.random() - 0.5) * 15; tree.style.transform = `rotate(${angle}deg)`; setTimeout(sway, 1000 + Math.random() * 2000); }; sway(); } // Rain Animation function createRainAnimation() { const container = document.getElementById('rain-animation'); container.innerHTML = ''; // Create raindrops for (let i = 0; i < 100; i++) { const drop = document.createElement('div'); drop.className = 'raindrop'; drop.style.left = Math.random() * 100 + '%'; drop.style.animationDelay = Math.random() * 2 + 's'; drop.style.animationDuration = (0.5 + Math.random() * 0.5) + 's'; container.appendChild(drop); } // Create puddle const puddle = document.createElement('div'); puddle.className = 'puddle'; container.appendChild(puddle); } // Sun Animation function createSunAnimation() { const container = document.getElementById('sun-animation'); container.innerHTML = ''; // Create sun core const core = document.createElement('div'); core.className = 'sun-core'; container.appendChild(core); // Create sun rays for (let i = 0; i < 16; i++) { const ray = document.createElement('div'); ray.className = 'sun-ray'; const angle = (i * 22.5) * Math.PI / 180; const length = 40; ray.style.width = length + 'px'; ray.style.left = '50%'; ray.style.top = '50%'; ray.style.transform = `rotate(${i * 22.5}deg) translateY(-30px)`; container.appendChild(ray); } } // Snow Animation function createSnowAnimation() { const container = document.getElementById('snow-animation'); container.innerHTML = ''; // Create snowflakes for (let i = 0; i < 50; i++) { const flake = document.createElement('div'); flake.className = 'snowflake'; flake.innerHTML = '❄'; flake.style.left = Math.random() * 100 + '%'; flake.style.animationDelay = Math.random() * 4 + 's'; flake.style.animationDuration = (3 + Math.random() * 3) + 's'; flake.style.fontSize = (0.5 + Math.random() * 1) + 'rem'; container.appendChild(flake); } // Create snow ground const ground = document.createElement('div'); ground.className = 'snow-ground'; container.appendChild(ground); } // Initialize all animations function initAnimations() { createWindAnimation(); createRainAnimation(); createSunAnimation(); createSnowAnimation(); } // Weather switching function setupWeatherSwitching() { const buttons = document.querySelectorAll('.control-btn'); const cards = document.querySelectorAll('.weather-card'); buttons.forEach(button => { button.addEventListener('click', () => { // Update active button buttons.forEach(btn => btn.classList.remove('active')); button.classList.add('active'); // Get weather type const weatherType = button.dataset.weather; // Show/hide cards based on weather type cards.forEach(card => { if (card.id.includes(weatherType)) { card.style.display = 'block'; card.style.opacity = '1'; card.style.transform = 'scale(1)'; } else { card.style.opacity = '0'; card.style.transform = 'scale(0.9)'; setTimeout(() => { card.style.display = 'none'; }, 300); } }); }); }); } // Initialize when DOM is loaded document.addEventListener('DOMContentLoaded', () => { initAnimations(); setupWeatherSwitching(); // Show all cards initially const cards = document.querySelectorAll('.weather-card'); cards.forEach(card => { card.style.display = 'block'; card.style.opacity = '1'; card.style.transform = 'scale(1)'; }); }); // Handle window resize window.addEventListener('resize', () => { setTimeout(initAnimations, 100); }); </script> </body> </html> ```
```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Animated Weather Cards</title> <!-- Everything lives in ONE file: HTML + CSS + JS --> <style> /* ---------- Design tokens ---------- */ @import url("https://fonts.googleapis.com/css2?family=SF+Pro+Display:wght@400;600&display=swap"); :root{ --w:220px; /* card width */ --h:300px; /* card height */ --round:22px; /* card radius */ --bg:#0d0d0d; /* global background */ --card:#1a1a1a; /* card background */ --accent:#0a84ff; /* iOS blue */ } *{margin:0;padding:0;box-sizing:border-box} body{ min-height:100vh; background:var(--bg); color:#fff; font-family:"SF Pro Display",system-ui,-apple-system,sans-serif; display:flex; flex-direction:column; align-items:center; gap:32px; overflow-x:hidden; } /* ---------- Heading ---------- */ h1{font-size:28px;font-weight:600;margin-top:28px;letter-spacing:-.3px} /* ---------- Controls ---------- */ .controls{ display:flex; gap:12px; flex-wrap:wrap; justify-content:center; } .controls button{ padding:9px 22px; border-radius:32px; background:#000; border:1px solid #333; color:#fff; font-size:15px; cursor:pointer; transition:.25s ease; } .controls button:hover, .controls button.active{ background:var(--accent); border-color:var(--accent); } /* ---------- Card grid ---------- */ .cards{ display:flex; flex-wrap:wrap; gap:34px; justify-content:center; padding:0 20px 70px; } .card{ position:relative; width:var(--w); height:var(--h); background:var(--card); border-radius:var(--round); overflow:hidden; box-shadow:0 14px 28px rgba(0,0,0,.4); display:flex; align-items:flex-end; justify-content:center; padding-bottom:26px; } .card h2{ pointer-events:none; font-size:20px; font-weight:600; } /* generic “hide” utility when a filter is chosen */ .hide{display:none!important} /* ---------- SUN ---------- */ .sun{ background:radial-gradient(circle at 50% 130%,#222 0%,#000 70%); } .sun-core{ position:absolute; top:54px;left:50%; width:88px;height:88px; margin-left:-44px; background:#ffd93b; border-radius:50%; box-shadow:0 0 18px 6px rgba(255,217,59,.7); } .sun-rays{ position:absolute; width:160px;height:160px; top:5px;left:50%; margin-left:-80px; animation:rotate 18s linear infinite; } .sun-rays span{ position:absolute; left:50%;top:0; width:8px;height:32px; margin-left:-4px; background:#ffd93b; border-radius:4px; box-shadow:0 0 12px rgba(255,217,59,.55); } .sun-rays span:nth-child(2){transform:rotate(45deg) translateY(-80px)} .sun-rays span:nth-child(3){transform:rotate(90deg) translateY(-80px)} .sun-rays span:nth-child(4){transform:rotate(135deg) translateY(-80px)} .sun-rays span:nth-child(5){transform:rotate(180deg) translateY(-80px)} .sun-rays span:nth-child(6){transform:rotate(225deg) translateY(-80px)} .sun-rays span:nth-child(7){transform:rotate(270deg) translateY(-80px)} .sun-rays span:nth-child(8){transform:rotate(315deg) translateY(-80px)} @keyframes rotate{from{transform:rotate(0deg)}to{transform:rotate(360deg)}} /* ---------- RAIN ---------- */ .rain{overflow:hidden} .raindrop{ position:absolute; top:-50px; width:2px;height:14px; background:var(--accent); border-radius:1px; animation:raindrop linear infinite; } @keyframes raindrop{ 0%{transform:translateY(0);opacity:1} 90%{opacity:1} 100%{transform:translateY(calc(var(--h) + 60px));opacity:0} } .puddle{ position:absolute; bottom:22px;left:50%; width:130px;height:9px; background:rgba(10,132,255,.35); border-radius:50%; transform:translateX(-50%); filter:blur(2px); animation:puddle 3s ease-in-out infinite; } @keyframes puddle{0%,100%{transform:translateX(-50%)scaleX(.9)}50%{transform:translateX(-50%)scaleX(1)}} /* ---------- SNOW ---------- */ .snow{overflow:hidden} .flake{ position:absolute;top:-40px; width:6px;height:6px; background:#fff;border-radius:50%; opacity:.9;animation:snow linear infinite; } .flake::before,.flake::after{ content:'';position:absolute; background:#fff;border-radius:50%; } .flake::before{width:6px;height:2px;top:2px;left:-2px} .flake::after {width:2px;height:6px;top:-2px;left:2px} @keyframes snow{ 0%{transform:translateY(0) rotate(0);opacity:1} 90%{opacity:.85} 100%{transform:translateY(calc(var(--h) + 70px)) rotate(180deg);opacity:0} } .snow-ground{ position:absolute;left:0;bottom:0; width:100%;height:42px; background:linear-gradient(to top,#fff 0%,rgba(255,255,255,0) 80%); } /* ---------- WIND ---------- */ .wind{overflow:hidden} .cloud{ position:absolute;top:60px;left:-160px; width:128px;height:62px; background:#fff;border-radius:62px; filter:drop-shadow(0 4px 14px rgba(255,255,255,.25)); animation:cloud 12s linear infinite; } .cloud::before,.cloud::after{ content:'';position:absolute;background:#fff;border-radius:50%; } .cloud::before{width:74px;height:74px;top:-37px;left:8px} .cloud::after {width:54px;height:54px;top:-18px;right:18px} @keyframes cloud{ 0%{transform:translateX(0)} 100%{transform:translateX(calc(var(--w) + 340px))} } .wind-line{ position:absolute;top:140px;left:-80px; width:70px;height:4px; background:rgba(255,255,255,.55); border-radius:4px; animation:wind 4s cubic-bezier(.4,.04,.46,.99) infinite; } .wind-line::after{ content:'';position:absolute; width:36px;height:4px; background:rgba(255,255,255,.55); border-radius:4px; top:-10px;left:48px; } @keyframes wind{ 0%{transform:translateX(0)scaleX(.6);opacity:0} 10%{opacity:1} 60%{transform:translateX(calc(var(--w) + 160px))scaleX(1)} 100%{transform:translateX(calc(var(--w) + 180px));opacity:0} } /* ---------- Responsive tweak ---------- */ @media(max-width:950px){ .cards{flex-direction:column;align-items:center} } </style> </head> <body> <h1>Animated Weather Cards</h1> <!-- filter buttons --> <div class="controls"> <button class="active" data-filter="all">All</button> <button data-filter="sun">Sun</button> <button data-filter="rain">Rain</button> <button data-filter="snow">Snow</button> <button data-filter="wind">Wind</button> </div> <!-- cards --> <div class="cards"> <!-- SUN --> <div class="card sun" data-kind="sun"> <div class="sun-core"></div> <div class="sun-rays"> <span></span><span></span><span></span><span></span> <span></span><span></span><span></span><span></span> </div> <h2>Sunny</h2> </div> <!-- RAIN --> <div class="card rain" data-kind="rain"> <div class="puddle"></div> <h2>Rainy</h2> </div> <!-- SNOW --> <div class="card snow" data-kind="snow"> <div class="snow-ground"></div> <h2>Snowy</h2> </div> <!-- WIND --> <div class="card wind" data-kind="wind"> <h2>Windy</h2> </div> </div> <script> /* ------------------------------------------------- Particle generators --------------------------------------------------*/ const $ = s=>document.querySelector(s); /* RAIN */ const rainCard = $('.rain'); for(let i=0;i<60;i++) addDrop(); setInterval(()=>addDrop(),300); function addDrop(){ const d=document.createElement('div'); d.className='raindrop'; d.style.left=Math.random()*220+'px'; d.style.animationDuration=.45+Math.random()*.5+'s'; rainCard.appendChild(d); // remove once finished to keep DOM small setTimeout(()=>d.remove(),2000); } /* SNOW */ const snowCard=$('.snow'); for(let i=0;i<40;i++) addFlake(); setInterval(()=>addFlake(),700); function addFlake(){ const f=document.createElement('div'); f.className='flake'; const size=3+Math.random()*5; f.style.width=f.style.height=size+'px'; f.style.left=Math.random()*220+'px'; f.style.animationDuration=2+Math.random()*3+'s'; snowCard.appendChild(f); setTimeout(()=>f.remove(),6000); } /* WIND */ const windCard=$('.wind'); for(let i=0;i<7;i++) addWindLine(); for(let i=0;i<2;i++) addCloud(); setInterval(()=>addWindLine(),1900); setInterval(()=>addCloud(),6000); function addWindLine(){ const l=document.createElement('div'); l.className='wind-line'; l.style.top=130+Math.random()*60+'px'; l.style.animationDelay=Math.random()*1+'s'; windCard.appendChild(l); setTimeout(()=>l.remove(),4500); } function addCloud(){ const c=document.createElement('div'); c.className='cloud'; windCard.appendChild(c); setTimeout(()=>c.remove(),13000); } /* ------------------------------------------------- Filter buttons --------------------------------------------------*/ document.querySelectorAll('.controls button').forEach(btn=>{ btn.addEventListener('click',()=>{ document.querySelector('.controls .active')?.classList.remove('active'); btn.classList.add('active'); const filter=btn.dataset.filter; document.querySelectorAll('.card').forEach(card=>{ if(filter==='all'||card.dataset.kind===filter) card.classList.remove('hide'); else card.classList.add('hide'); }); }); }); </script> </body> </html> ```
Of course! Here is a single HTML file that creates four distinct, animated weather cards displayed side-by-side, designed with a premium, clean aesthetic. The animations for wind, rain, sun, and snow are created using only CSS and a little JavaScript to dynamically generate the raindrops and snowflakes for a more random, natural effect. ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Animated Weather Cards</title> <style> /* --- Global Styles & Setup --- */ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;700&display=swap'); :root { --bg-color: #121212; --card-color: #1E1E1E; --text-primary: #E0E0E0; --text-secondary: #A0A0A0; --shadow-color: rgba(0, 0, 0, 0.2); --border-color: rgba(255, 255, 255, 0.1); --sun-color: #FFD700; --rain-color: #87CEEB; --snow-color: #FFFFFF; --cloud-color: #F5F5F5; } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; background-color: var(--bg-color); color: var(--text-primary); display: flex; justify-content: center; align-items: center; min-height: 100vh; padding: 2rem; } /* --- Main Container --- */ .weather-container { display: flex; flex-wrap: wrap; justify-content: center; gap: 2rem; } /* --- Base Card Style --- */ .weather-card { width: 280px; height: 400px; background: var(--card-color); border-radius: 24px; padding: 2rem; display: flex; flex-direction: column; justify-content: space-between; position: relative; overflow: hidden; border: 1px solid var(--border-color); box-shadow: 0 10px 30px var(--shadow-color); transition: transform 0.3s ease, box-shadow 0.3s ease; } .weather-card:hover { transform: translateY(-10px); box-shadow: 0 20px 40px var(--shadow-color); } .card-header { z-index: 10; } .card-header .condition { font-size: 1.5rem; font-weight: 500; } .card-header .location { font-size: 1rem; font-weight: 300; color: var(--text-secondary); } .card-footer { font-size: 3rem; font-weight: 700; z-index: 10; } .animation-container { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } /* --- Sunny Card --- */ .sunny { background: linear-gradient(135deg, #4A4A6A, #28315A); } .sun { position: absolute; top: 35%; left: 50%; transform: translate(-50%, -50%); width: 80px; height: 80px; background: radial-gradient(circle, var(--sun-color) 60%, rgba(255,215,0,0) 62%); border-radius: 50%; animation: pulse 4s infinite ease-in-out; } .sun-ray { position: absolute; top: 50%; left: 50%; width: 2px; height: 160px; /* Long rays */ background: linear-gradient(to bottom, rgba(255,215,0,0.5), rgba(255,215,0,0)); transform-origin: top; } .sun-ray.one { transform: rotate(0deg); animation: sunrise 8s infinite linear; } .sun-ray.two { transform: rotate(45deg); animation: sunrise 8s infinite linear -2s; } .sun-ray.three { transform: rotate(90deg); animation: sunrise 8s infinite linear -4s; } .sun-ray.four { transform: rotate(135deg); animation: sunrise 8s infinite linear -6s; } @keyframes pulse { 0%, 100% { box-shadow: 0 0 30px 10px rgba(255,215,0,0.2); } 50% { box-shadow: 0 0 50px 20px rgba(255,215,0,0.4); } } @keyframes sunrise { 0% { opacity: 0; transform: scaleY(0) rotate(var(--angle)); } 50% { opacity: 0.5; transform: scaleY(1) rotate(var(--angle)); } 100% { opacity: 0; transform: scaleY(0) rotate(var(--angle)); } } .sun-ray.one { --angle: 0deg; } .sun-ray.two { --angle: 45deg; } .sun-ray.three { --angle: 90deg; } .sun-ray.four { --angle: 135deg; } .sun-ray.five { --angle: 180deg; animation-delay: -4s;} .sun-ray.six { --angle: 225deg; animation-delay: -6s;} .sun-ray.seven { --angle: 270deg; animation-delay: -8s;} .sun-ray.eight { --angle: 315deg; animation-delay: -10s;} /* --- Rainy Card --- */ .rainy { background: linear-gradient(135deg, #5D6C7E, #364554); } .cloud { position: absolute; background: var(--cloud-color); border-radius: 50%; filter: opacity(0.9); top: 60px; } .cloud.base { width: 120px; height: 40px; left: 50%; transform: translateX(-50%); border-radius: 20px; } .cloud::before, .cloud::after { content: ''; position: absolute; background: var(--cloud-color); border-radius: 50%; } .cloud.base::before { width: 60px; height: 60px; top: -30px; left: 20px; } .cloud.base::after { width: 80px; height: 80px; top: -45px; right: 10px; } .raindrop { position: absolute; bottom: 0px; width: 2px; height: 15px; background: var(--rain-color); border-radius: 50%; animation: fall linear infinite; } @keyframes fall { from { transform: translateY(-300px); opacity: 0.8; } to { transform: translateY(0px); opacity: 0; } } /* --- Windy Card --- */ .windy { background: linear-gradient(135deg, #6E6D8F, #4A4A6A); } .wind-cloud { position: absolute; animation: drift 15s infinite linear; } .wind-cloud.one { top: 80px; left: -150px; transform: scale(0.8); animation-duration: 20s; } .wind-cloud.two { top: 150px; left: -200px; transform: scale(1.1); animation-duration: 25s; animation-delay: -8s; } .wind-line { position: absolute; background-color: rgba(255,255,255,0.2); width: 80px; height: 2px; border-radius: 2px; animation: wind-gust 2s infinite ease-out; } .wind-line.one { top: 40%; left: -100px; animation-delay: 0s; } .wind-line.two { top: 50%; left: -100px; animation-delay: -1s; } .wind-line.three { top: 60%; left: -100px; animation-delay: -0.5s; } @keyframes drift { from { transform: translateX(0); } to { transform: translateX(450px); } } @keyframes wind-gust { 0% { transform: translateX(0); opacity: 0; } 20% { opacity: 1; } 100% { transform: translateX(380px); opacity: 0; } } /* --- Snowy Card --- */ .snowy { background: linear-gradient(135deg, #3E5C76, #1D2D44); } .snowflake { position: absolute; color: var(--snow-color); font-size: 1.5rem; animation: snowfall linear infinite; } @keyframes snowfall { 0% { transform: translateY(-50px) translateX(0); opacity: 0; } 10% { opacity: 1; } 90% { opacity: 1; } 100% { transform: translateY(350px) translateX(20px); opacity: 0; } } </style> </head> <body> <div class="weather-container"> <!-- Sunny Card --> <div class="weather-card sunny"> <div class="animation-container"> <div class="sun"></div> <div class="sun-ray one"></div> <div class="sun-ray two"></div> <div class="sun-ray three"></div> <div class="sun-ray four"></div> <div class="sun-ray five"></div> <div class="sun-ray six"></div> <div class="sun-ray seven"></div> <div class="sun-ray eight"></div> </div> <div class="card-header"> <div class="condition">Sunny</div> <div class="location">San Francisco</div> </div> <div class="card-footer">25°C</div> </div> <!-- Rainy Card --> <div class="weather-card rainy"> <div class="animation-container" id="rain-container"> <div class="cloud base"></div> </div> <div class="card-header"> <div class="condition">Heavy Rain</div> <div class="location">London</div> </div> <div class="card-footer">9°C</div> </div> <!-- Windy Card --> <div class="weather-card windy"> <div class="animation-container"> <div class="wind-cloud one"> <div class="cloud base"></div> </div> <div class="wind-cloud two"> <div class="cloud base"></div> </div> <div class="wind-line one"></div> <div class="wind-line two"></div> <div class="wind-line three"></div> </div> <div class="card-header"> <div class="condition">Windy</div> <div class="location">Chicago</div> </div> <div class="card-footer">12°C</div> </div> <!-- Snowy Card --> <div class="weather-card snowy"> <div class="animation-container" id="snow-container"> <div class="cloud base" style="filter: opacity(0.6)"></div> </div> <div class="card-header"> <div class="condition">Light Snow</div> <div class="location">Stockholm</div> </div> <div class="card-footer">-2°C</div> </div> </div> <script> document.addEventListener('DOMContentLoaded', () => { const rainContainer = document.getElementById('rain-container'); const snowContainer = document.getElementById('snow-container'); function createParticles(container, particleClass, count, content) { for (let i = 0; i < count; i++) { const particle = document.createElement('span'); particle.className = particleClass; const x = Math.random() * 100; // a percentage const duration = Math.random() * 1.5 + 0.5; // 0.5 to 2 seconds const delay = Math.random() * 2; // 0 to 2 seconds particle.style.left = `${x}%`; particle.style.animationDuration = `${duration}s`; particle.style.animationDelay = `${delay}s`; if (particleClass === 'snowflake') { const size = Math.random() * 10 + 8; // 8px to 18px particle.style.fontSize = `${size}px`; // A slight horizontal variation for snowfall const initialX = (Math.random() - 0.5) * 40; // -20px to +20px const finalX = initialX + (Math.random() - 0.5) * 40; const snowfallKeyframes = ` @keyframes snowfall-${i} { 0% { transform: translateY(-50px) translateX(${initialX}px); opacity: 0; } 10% { opacity: 1; } 90% { opacity: 1; } 100% { transform: translateY(350px) translateX(${finalX}px); opacity: 0; } } `; const styleSheet = document.styleSheets[0]; styleSheet.insertRule(snowfallKeyframes, styleSheet.cssRules.length); particle.style.animationName = `snowfall-${i}`; particle.textContent = '•'; } container.appendChild(particle); } } createParticles(rainContainer, 'raindrop', 50); createParticles(snowContainer, 'snowflake', 70); }); </script> </body> </html> ```
# Animated Weather Cards - Apple Premium Design Here's a complete solution with four weather cards (Wind, Rain, Sun, Snow) that animate when you switch between conditions. The design follows Apple's premium aesthetic with smooth animations and a dark theme. ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Premium Weather Cards</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } body { background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); min-height: 100vh; display: flex; flex-direction: column; align-items: center; padding: 40px 20px; color: #f0f0f0; } .header { text-align: center; margin-bottom: 40px; max-width: 800px; } h1 { font-size: 2.8rem; font-weight: 700; background: linear-gradient(to right, #4facfe 0%, #00f2fe 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 12px; letter-spacing: -0.5px; } .subtitle { font-size: 1.2rem; font-weight: 300; color: #a0aec0; max-width: 600px; margin: 0 auto; line-height: 1.6; } .controls { display: flex; gap: 16px; margin-bottom: 40px; flex-wrap: wrap; justify-content: center; } .weather-btn { background: rgba(255, 255, 255, 0.1); border: 2px solid rgba(255, 255, 255, 0.1); color: #fff; padding: 14px 28px; border-radius: 60px; font-size: 1.1rem; font-weight: 500; cursor: pointer; transition: all 0.3s ease; backdrop-filter: blur(10px); box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2); } .weather-btn:hover { background: rgba(255, 255, 255, 0.15); transform: translateY(-3px); box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3); } .weather-btn.active { background: rgba(255, 255, 255, 0.2); border-color: rgba(255, 255, 255, 0.3); font-weight: 600; transform: translateY(-2px); } .cards-container { display: flex; gap: 30px; max-width: 1200px; width: 100%; justify-content: center; flex-wrap: wrap; } .weather-card { width: 280px; height: 360px; background: linear-gradient(145deg, rgba(30, 30, 46, 0.8), rgba(22, 22, 40, 0.8)); border-radius: 24px; padding: 25px; display: flex; flex-direction: column; box-shadow: 0 20px 50px rgba(0, 0, 0, 0.3); border: 1px solid rgba(255, 255, 255, 0.05); transition: transform 0.4s ease, box-shadow 0.4s ease; overflow: hidden; position: relative; } .weather-card:hover { transform: translateY(-10px); box-shadow: 0 25px 60px rgba(0, 0, 0, 0.4); } .card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 30px; z-index: 2; } .weather-icon { font-size: 2.8rem; opacity: 0.9; } .temperature { font-size: 3.2rem; font-weight: 700; letter-spacing: -1px; } .weather-condition { font-size: 1.4rem; font-weight: 600; text-transform: uppercase; letter-spacing: 1px; margin-top: 5px; opacity: 0.9; } .location { display: flex; align-items: center; font-size: 1.1rem; color: #a0aec0; margin-top: 5px; } .divider { height: 1px; background: rgba(255, 255, 255, 0.05); margin: 25px 0; width: 100%; } .details { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; z-index: 2; } .detail-item { display: flex; flex-direction: column; } .detail-label { font-size: 0.9rem; color: #a0aec0; margin-bottom: 5px; } .detail-value { font-size: 1.2rem; font-weight: 600; } /* Wind specific styles */ .wind-animation { position: absolute; bottom: 0; left: 0; width: 100%; height: 80px; overflow: hidden; } .wind-line { position: absolute; background: rgba(64, 224, 208, 0.6); height: 2px; border-radius: 1px; animation: windFlow 12s linear infinite; } @keyframes windFlow { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } } /* Rain specific styles */ .rain-animation { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } .raindrop { position: absolute; background: rgba(173, 216, 230, 0.8); border-radius: 50%; animation: rainFall 1.5s linear infinite; } @keyframes rainFall { 0% { transform: translateY(-50px); opacity: 0; } 10% { opacity: 1; } 90% { opacity: 0.8; } 100% { transform: translateY(400px); opacity: 0; } } /* Sun specific styles */ .sun-animation { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } .ray { position: absolute; background: rgba(255, 255, 200, 0.6); border-radius: 50%; animation: sunPulse 4s ease-in-out infinite; } @keyframes sunPulse { 0%, 100% { transform: scale(1); opacity: 0.6; } 50% { transform: scale(1.1); opacity: 0.8; } } /* Snow specific styles */ .snow-animation { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } .snowflake { position: absolute; background: rgba(255, 255, 255, 0.9); border-radius: 50%; animation: snowFall 10s linear infinite; } @keyframes snowFall { 0% { transform: translateY(-50px) translateX(0); opacity: 0; } 10% { opacity: 1; } 90% { opacity: 0.9; } 100% { transform: translateY(400px) translateX(20px); opacity: 0; } } .card-footer { margin-top: auto; font-size: 0.85rem; color: #718096; z-index: 2; } @media (max-width: 1100px) { .cards-container { gap: 20px; } .weather-card { width: 260px; height: 340px; } } @media (max-width: 900px) { .cards-container { flex-direction: column; align-items: center; } .weather-card { width: 100%; max-width: 400px; } } </style> </head> <body> <div class="header"> <h1>Animated Weather Cards</h1> <p class="subtitle">Premium Apple-inspired weather visualization with smooth animations. Select a weather condition to see its unique animation in all cards.</p> </div> <div class="controls"> <button class="weather-btn active" data-weather="wind">Wind</button> <button class="weather-btn" data-weather="rain">Rain</button> <button class="weather-btn" data-weather="sun">Sun</button> <button class="weather-btn" data-weather="snow">Snow</button> </div> <div class="cards-container"> <!-- Wind Card --> <div class="weather-card" id="wind-card"> <div class="card-header"> <div> <div class="temperature">18°</div> <div class="weather-condition">Windy</div> </div> <div class="weather-icon">💨</div> </div> <div class="location"> <span>📍</span> San Francisco, CA </div> <div class="divider"></div> <div class="details"> <div class="detail-item"> <span class="detail-label">Humidity</span> <span class="detail-value">65%</span> </div> <div class="detail-item"> <span class="detail-label">Pressure</span> <span class="detail-value">1013 hPa</span> </div> <div class="detail-item"> <span class="detail-label">Wind Speed</span> <span class="detail-value">22 km/h</span> </div> <div class="detail-item"> <span class="detail-label">Feels Like</span> <span class="detail-value">16°</span> </div> </div> <div class="wind-animation" id="wind-animation"></div> <div class="card-footer">Updated just now</div> </div> <!-- Rain Card --> <div class="weather-card" id="rain-card"> <div class="card-header"> <div> <div class="temperature">12°</div> <div class="weather-condition">Rainy</div> </div> <div class="weather-icon">🌧️</div> </div> <div class="location"> <span>📍</span> London, UK </div> <div class="divider"></div> <div class="details"> <div class="detail-item"> <span class="detail-label">Humidity</span> <span class="detail-value">85%</span> </div> <div class="detail-item"> <span class="detail-label">Pressure</span> <span class="detail-value">1008 hPa</span> </div> <div class="detail-item"> <span class="detail-label">Wind Speed</span> <span class="detail-value">14 km/h</span> </div> <div class="detail-item"> <span class="detail-label">Feels Like</span> <span class="detail-value">10°</span> </div> </div> <div class="rain-animation" id="rain-animation"></div> <div class="card-footer">Updated just now</div> </div> <!-- Sun Card --> <div class="weather-card" id="sun-card"> <div class="card-header"> <div> <div class="temperature">28°</div> <div class="weather-condition">Sunny</div> </div> <div class="weather-icon">☀️</div> </div> <div class="location"> <span>📍</span> Sydney, AU </div> <div class="divider"></div> <div class="details"> <div class="detail-item"> <span class="detail-label">Humidity</span> <span class="detail-value">45%</span> </div> <div class="detail-item"> <span class="detail-label">Pressure</span> <span class="detail-value">1016 hPa</span> </div> <div class="detail-item"> <span class="detail-label">Wind Speed</span> <span class="detail-value">8 km/h</span> </div> <div class="detail-item"> <span class="detail-label">UV Index</span> <span class="detail-value">7</span> </div> </div> <div class="sun-animation" id="sun-animation"></div> <div class="card-footer">Updated just now</div> </div> <!-- Snow Card --> <div class="weather-card" id="snow-card"> <div class="card-header"> <div> <div class="temperature">-5°</div> <div class="weather-condition">Snowy</div> </div> <div class="weather-icon">❄️</div> </div> <div class="location"> <span>📍</span> Oslo, Norway </div> <div class="divider"></div> <div class="details"> <div class="detail-item"> <span class="detail-label">Humidity</span> <span class="detail-value">92%</span> </div> <div class="detail-item"> <span class="detail-label">Pressure</span> <span class="detail-value">1022 hPa</span> </div> <div class="detail-item"> <span class="detail-label">Wind Speed</span> <span class="detail-value">12 km/h</span> </div> <div class="detail-item"> <span class="detail-label">Feels Like</span> <span class="detail-value">-9°</span> </div> </div> <div class="snow-animation" id="snow-animation"></div> <div class="card-footer">Updated just now</div> </div> </div> <script> // Weather animation controller document.addEventListener('DOMContentLoaded', function() { const weatherButtons = document.querySelectorAll('.weather-btn'); const windAnimation = document.getElementById('wind-animation'); const rainAnimation = document.getElementById('rain-animation'); const sunAnimation = document.getElementById('sun-animation'); const snowAnimation = document.getElementById('snow-animation'); // Initialize wind animation function initWindAnimation() { windAnimation.innerHTML = ''; for (let i = 0; i < 15; i++) { const line = document.createElement('div'); line.classList.add('wind-line'); line.style.top = `${Math.random() * 40 + 20}px`; line.style.width = `${Math.random() * 100 + 50}px`; line.style.animationDelay = `${Math.random() * 5}s`; windAnimation.appendChild(line); } } // Initialize rain animation function initRainAnimation() { rainAnimation.innerHTML = ''; for (let i = 0; i < 80; i++) { const drop = document.createElement('div'); drop.classList.add('raindrop'); drop.style.left = `${Math.random() * 100}%`; drop.style.width = `${Math.random() * 3 + 2}px`; drop.style.height = drop.style.width; drop.style.animationDelay = `${Math.random() * 2}s`; rainAnimation.appendChild(drop); } } // Initialize sun animation function initSunAnimation() { sunAnimation.innerHTML = ''; for (let i = 0; i < 12; i++) { const ray = document.createElement('div'); ray.classList.add('ray'); ray.style.width = `${Math.random() * 60 + 40}%`; ray.style.height = `${Math.random() * 60 + 40}%`; ray.style.top = `${50 - ray.style.height / 2}%`; ray.style.left = `${50 - ray.style.width / 2}%`; ray.style.animationDelay = `${Math.random() * 2}s`; sunAnimation.appendChild(ray); } } // Initialize snow animation function initSnowAnimation() { snowAnimation.innerHTML = ''; for (let i = 0; i < 60; i++) { const flake = document.createElement('div'); flake.classList.add('snowflake'); flake.style.left = `${Math.random() * 100}%`; flake.style.width = `${Math.random() * 5 + 2}px`; flake.style.height = flake.style.width; flake.style.animationDelay = `${Math.random() * 5}s`; flake.style.animationDuration = `${Math.random() * 5 + 8}s`; snowAnimation.appendChild(flake); } } // Set all animations to a specific weather type function setWeather(weatherType) { // Hide all animations windAnimation.style.display = 'none'; rainAnimation.style.display = 'none'; sunAnimation.style.display = 'none'; snowAnimation.style.display = 'none'; // Update button states weatherButtons.forEach(btn => { btn.classList.remove('active'); if (btn.dataset.weather === weatherType) { btn.classList.add('active'); } }); // Show and initialize the selected animation if (weatherType === 'wind') { windAnimation.style.display = 'block'; initWindAnimation(); } else if (weatherType === 'rain') { rainAnimation.style.display = 'block'; initRainAnimation(); } else if (weatherType === 'sun') { sunAnimation.style.display = 'block'; initSunAnimation(); } else if (weatherType === 'snow') { snowAnimation.style.display = 'block'; initSnowAnimation(); } } // Add event listeners to buttons weatherButtons.forEach(btn => { btn.addEventListener('click', () => { setWeather(btn.dataset.weather); }); }); // Initialize with wind animation initWindAnimation(); setWeather('wind'); }); </script> </body> </html> ``` ## Features 1. **Premium Apple-inspired Design**: - Sleek dark theme with gradient accents - Subtle animations and hover effects - Clean typography and spacing - Glassmorphism effect for cards 2. **Four Weather Conditions**: - **Wind**: Animated flowing lines - **Rain**: Falling raindrops with varying sizes - **Sun**: Pulsing rays with glow effect - **Snow**: Gentle falling snowflakes 3. **Interactive Controls**: - Buttons to switch between weather conditions - Active state indication - Smooth transitions between animations 4. **Responsive Layout**: - Cards adjust for different screen sizes - Mobile-friendly design - Flexible container system 5. **Detailed Weather Information**: - Temperature, location, and weather condition - Humidity, pressure, wind speed, and feels-like values - Timely update indicator To use the weather cards, simply click on the weather condition buttons at the top to see the corresponding animation in all four cards. Each card maintains its own unique animation that responds to the selected weather condition.
```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Animated Weather Cards</title> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link href="https://fonts.googleapis.com/css2?family=SF+Pro+Display:wght@400;600&display=swap" rel="stylesheet"> <style> :root { --card-radius: 30px; --card-width: 270px; --card-height: 390px; --accent-blue: #4d79ff; --accent-yellow: #ffe066; --accent-gray: #acb6c5; --bg-dark: #161925; --fg-light: #fafaff; --text-shadow: 0 2px 12px rgba(0,0,0,0.18); } html, body { height: 100%; } body { min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; background: linear-gradient(120deg, #161925 80%, #232740 100%); font-family: 'SF Pro Display', 'San Francisco', 'Segoe UI', Arial, sans-serif; letter-spacing: 0.02em; margin: 0; padding: 0; } header { margin-top: 46px; margin-bottom: 20px; text-align: center; color: var(--fg-light); font-size: 2rem; font-weight: 600; text-shadow: var(--text-shadow); } .weather-control { margin-bottom: 30px; display: flex; gap: 24px; justify-content: center; flex-wrap: wrap; } .weather-btn { padding: 10px 28px; border-radius: 22px; border: none; background: var(--bg-dark); color: var(--fg-light); font-size: 1.08rem; font-weight: 600; box-shadow: 0 2px 12px rgba(0,0,0,0.11); cursor: pointer; outline: none; transition: background .22s, color .15s, box-shadow .15s; letter-spacing: 0.01em; } .weather-btn.active, .weather-btn:focus, .weather-btn:hover { background: var(--accent-blue); color: #fff; box-shadow: 0 4px 32px -2px #4d79ff33; } .card-strip { display: flex; gap: 28px; justify-content: center; flex-wrap: wrap; margin-bottom: 54px; } .weather-card { position: relative; width: var(--card-width); height: var(--card-height); background: linear-gradient(135deg, #23253b 72%, #1e2036 100%); border-radius: var(--card-radius); overflow: hidden; box-shadow: 0 8px 42px -6px rgba(56,74,130,0.22), 0 2px 10px rgba(12,18,44,0.13); display: flex; flex-direction: column; align-items: center; justify-content: flex-end; padding: 0; transition: box-shadow .23s; } .weather-card:hover { box-shadow: 0 14px 64px -2px #4668e822, 0 2px 10px rgba(12,18,44,0.13); } .weather-content { z-index: 3; position: absolute; bottom: 26px; left: 0; right: 0; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; } .weather-title { font-size: 1.32rem; font-weight: 600; margin-bottom: 8px; color: var(--fg-light); letter-spacing: 0.01em; text-shadow: var(--text-shadow); opacity: 0.98; } .weather-temp { font-size: 2.5rem; font-weight: 600; color: var(--accent-blue); text-shadow: var(--text-shadow); margin-bottom: 2px; letter-spacing: 0.01em; } .weather-desc { font-size: 1.08rem; color: var(--fg-light); opacity: 0.77; text-shadow: var(--text-shadow); font-weight: 400; margin-bottom: 0; } /* Card-specific overlay light/façade and animated backgrounds */ .card-bg { position: absolute; inset: 0; z-index: 1; pointer-events: none; } /* Apple-like frosted shine */ .shine { position: absolute; left: -30%; top: -25%; right: -30%; height: 76px; background: linear-gradient(112deg,rgba(255,255,255,0.15)0%,rgba(255,255,255,0.04)65%); border-radius: 55px; filter: blur(6px); opacity: 0.92; z-index: 4; } /* Animations specific to weather below */ /* General keyframes */ @keyframes sun-rays-rotate { 0% {transform:rotate(0deg);} 100% {transform:rotate(360deg);} } /* Used for gentle sway and wind lines */ @keyframes sway { 0%, 100% { transform: translateY(0) rotate(-2deg);} 50% { transform: translateY(4px) rotate(5deg);} } @keyframes windline-move { 0% {transform: translateX(-70px);} 100% {transform: translateX(300px);} } /* Rain */ @keyframes raindrop-fall { 0% { opacity: 1; transform:translateY(-75px); } 80% { opacity: 1; transform:translateY(255px); } 100% { opacity: 0; transform: translateY(340px) scaleY(0.8); } } @keyframes puddle-expand { 0% { transform: scaleX(0.45);} 80% { transform: scaleX(1.05);} 100% { transform: scaleX(1);} } /* Snow */ @keyframes snow-fall { 0% { opacity: 1; transform:translateY(-45px) scale(1) rotate(0deg); } 60%{opacity:1;} 90% { opacity: 1; transform: translateY(320px) scale(1) rotate(360deg); } 100% { opacity: 0; transform:translateY(370px) scale(1.15) rotate(400deg); } } @keyframes snow-accum { 0% { width:10%;} 100%{width:90%;} } /* Hide native scrollbar on body for premium look */ ::-webkit-scrollbar { display: none;} body { -ms-overflow-style: none; scrollbar-width: none;} /* Responsive */ @media (max-width: 1200px) { .card-strip {gap: 20px;} } @media (max-width: 900px) { .card-strip {gap: 10px;} .weather-card {width:220px; height:330px;} } @media (max-width: 600px) { .card-strip {flex-direction:column; align-items:center;} } </style> </head> <body> <header> Animated Weather Cards </header> <div class="weather-control"> <button class="weather-btn active" data-weather="all">All</button> <button class="weather-btn" data-weather="sun">Sun</button> <button class="weather-btn" data-weather="rain">Rain</button> <button class="weather-btn" data-weather="wind">Wind</button> <button class="weather-btn" data-weather="snow">Snow</button> </div> <div class="card-strip" id="cardStrip"> <!-- Weather Cards inserted here by JS --> </div> <script> /* Weather card data */ const weatherCards = [ { key: 'sun', name: 'Sunny', temp: '27°', desc: 'Clear Sky', card: ` <div class="card-bg"> <svg width="284" height="394" style="position:absolute; top:0; left:0; z-index:2"> <!-- Sun --> <g> <circle cx="135" cy="120" r="48" fill="url(#sun-gradient)"></circle> <g style="transform-origin:135px 123px; animation:sun-rays-rotate 6s linear infinite;"> <!-- Sun rays, 8 lines --> <g stroke="#ffe066" stroke-width="7" stroke-linecap="round" opacity=".94"> <line x1="135" y1="47" x2="135" y2="20"></line> <line x1="205" y1="120" x2="235" y2="120"></line> <line x1="65" y1="120" x2="35" y2="120"></line> <line x1="135" y1="193" x2="135" y2="220"></line> <line x1="186" y1="66" x2="207" y2="43"></line> <line x1="82" y1="66" x2="61" y2="43"></line> <line x1="82" y1="174" x2="61" y2="197"></line> <line x1="186" y1="174" x2="207" y2="197"></line> </g> </g> <!-- Subtle sun glow --> <circle cx="135" cy="120" r="67" fill="url(#sunglow-grad)" fill-opacity="0.46"></circle> <!-- background shine --> </g> <defs> <radialGradient id="sun-gradient" cx="50%" cy="50%" r="60%"> <stop offset="0%" stop-color="#fffbe6"/> <stop offset="60%" stop-color="#ffe066"/> <stop offset="100%" stop-color="#fdc535"/> </radialGradient> <radialGradient id="sunglow-grad" cx="50%" cy="50%" r="85%"> <stop offset="50%" stop-color="#ffe066" stop-opacity="0.36"/> <stop offset="100%" stop-color="#ffe066" stop-opacity="0"/> </radialGradient> </defs> </svg> <div class="shine"></div> <div style="position:absolute;left:0;top:0;width:100%;height:60%;background:linear-gradient(180deg,rgba(255,236,128,0.09) 20%,transparent 85%);z-index:3;"></div> </div> ` }, { key:'rain', name: 'Rainy', temp: '16°', desc: 'Moderate Rain', card: ` <div class="card-bg"> <svg width="284" height="395" style="position:absolute;top:0;left:0;z-index:2; pointer-events:none;"> <!-- Blue-gray background cloud --> <ellipse cx="132" cy="120" rx="62" ry="36" fill="url(#cloud-bg-grad-rain)"/> <ellipse cx="185" cy="134" rx="32" ry="22" fill="url(#cloud-inner-grad-rain)"/> <ellipse cx="86" cy="137" rx="17" ry="12" fill="url(#cloud-bg-grad-rain)"/> <!-- Foreground cloud --> <ellipse cx="107" cy="109" rx="23" ry="17" fill="url(#cloud-main-grad-rain)"/> <ellipse cx="155" cy="108" rx="24" ry="17" fill="url(#cloud-main-grad-rain)"/> <!-- subtle overlay --> <ellipse cx="135" cy="129" rx="68" ry="47" fill="rgba(210,220,245,0.06)"/> <defs> <linearGradient id="cloud-bg-grad-rain" x1="0" y1="0" x2="1" y2="1"> <stop offset="25%" stop-color="#b9ccda"/> <stop offset="100%" stop-color="#838fb2"/> </linearGradient> <linearGradient id="cloud-main-grad-rain" x1="0" y1="0" x2="1" y2="1"> <stop offset="0%" stop-color="#e6f4ff"/> <stop offset="100%" stop-color="#cbd4e2"/> </linearGradient> <linearGradient id="cloud-inner-grad-rain" x1="0" y1="0" x2="1" y2="1"> <stop offset="0%" stop-color="#e7f2ff"/> <stop offset="100%" stop-color="#b9ccda"/> </linearGradient> </defs> </svg> <!-- Puddle animates in --> <div id="puddle" style="position:absolute; left:61px; top:278px; width:72px; height:24px; background:radial-gradient(ellipse at 65% 55%, #aee1f6 52%, #699acc 100%); border-radius:100px/32px; opacity:0.38; transform:scaleX(0.48); z-index:3; animation:puddle-expand 2.6s .34s cubic-bezier(.7,0,0.34,1.2) forwards;"></div> <!-- shine --> <div class="shine"></div> </div> ` }, { key: 'wind', name: 'Windy', temp: '19°', desc: 'Breezy', card: ` <div class="card-bg"> <svg width="284" height="390" style="position:absolute;top:0;left:0;z-index:2;"> <!-- Clouds --> <ellipse cx="136" cy="130" rx="53" ry="22" fill="url(#cloud-wind-bg)" style="filter:blur(2px)"/> <ellipse cx="177" cy="144" rx="26" ry="13" fill="url(#cloud-wind-main)"/> <ellipse cx="97" cy="146" rx="14" ry="9" fill="url(#cloud-wind-main)"/> <!-- Foreground trees (swaying) --> <g id="swaytree1" style="animation:sway 2.7s ease-in-out infinite; transform-origin:68px 263px"> <rect x="67" y="225" width="4" height="38" rx="2" fill="#3a524b"/> <ellipse cx="69" cy="226" rx="10" ry="21" fill="#7cd9a9"/> <ellipse cx="72" cy="243" rx="6" ry="13" fill="#4dfcbb" opacity="0.81"/> </g> <g id="swaytree2" style="animation:sway 3.3s .7s ease-in-out infinite; transform-origin:208px 275px;"> <rect x="207" y="235" width="4" height="40" rx="2" fill="#415651"/> <ellipse cx="209" cy="236" rx="9" ry="19" fill="#43e07b"/> <ellipse cx="207" cy="259" rx="6" ry="15" fill="#37b072" opacity="0.88"/> </g> <defs> <linearGradient id="cloud-wind-bg" x1="0" y1="0" x2="1" y2="1"> <stop offset="0%" stop-color="#e6f3fd"/> <stop offset="80%" stop-color="#b7cce1"/> </linearGradient> <linearGradient id="cloud-wind-main" x1="0" y1="0" x2="1" y2="1"> <stop offset="0%" stop-color="#d5f2fc"/> <stop offset="100%" stop-color="#b0c7db"/> </linearGradient> </defs> </svg> <!-- Wind lines created via JS --> <div class="shine"></div> </div> ` }, { key: 'snow', name: 'Snowy', temp: '-3°', desc: 'Light Snow', card: ` <div class="card-bg"> <!-- Main snow cloud --> <svg width="284" height="394" style="position:absolute;top:0;left:0;z-index:2;"> <ellipse cx="132" cy="116" rx="60" ry="27" fill="url(#snow-cloud-bg)"/> <ellipse cx="103" cy="140" rx="33" ry="14" fill="url(#snow-cloud-main)" opacity="0.93"/> <ellipse cx="169" cy="142" rx="24" ry="11" fill="url(#snow-cloud-main)" opacity="0.89"/> <ellipse cx="135" cy="129" rx="68" ry="38" fill="url(#snow-cloud-inner)" opacity="0.17"/> <defs> <linearGradient id="snow-cloud-bg" x1="0" y1="0" x2="1" y2="1"> <stop offset="0%" stop-color="#e4eef9"/> <stop offset="100%" stop-color="#c6d6ee"/> </linearGradient> <linearGradient id="snow-cloud-main" x1="0" y1="0" x2="1" y2="1"> <stop offset="0%" stop-color="#eefdff"/> <stop offset="100%" stop-color="#c9e3f7"/> </linearGradient> <linearGradient id="snow-cloud-inner" x1="0" y1="0" x2="1" y2="1"> <stop offset="0%" stop-color="#fcfcff"/> <stop offset="100%" stop-color="#e2e8f0"/> </linearGradient> </defs> </svg> <!-- Snow accumulation over time (on bottom) --> <div id="snow-accum" style="position:absolute; bottom:19px; left:12px; height:19px; width:10%; border-radius:25px; background:linear-gradient(90deg,#fcfeff 25%,#e6f2fb 70%,#dcf0fe); box-shadow:0 2px 22px #b3c9e385; z-index:5; animation:snow-accum 6s cubic-bezier(.6,-0.1,0.4,1.4) forwards;"></div> <div class="shine"></div> <!-- overlay snow fog --> <div style="position:absolute;left:0;top:0;width:100%;height:70%;background:linear-gradient(180deg,rgba(244,253,254,.1) 20%,transparent 90%);z-index:3;"></div> </div> ` } ]; // Function to make SVG wind lines for the wind card function renderWindLines(cardElem) { const windLineContainer = document.createElement("div"); windLineContainer.style.position = "absolute"; windLineContainer.style.left = "0"; windLineContainer.style.top = "0"; windLineContainer.style.width = "100%"; windLineContainer.style.height = "60%"; windLineContainer.style.zIndex = "20"; windLineContainer.style.overflow = "hidden"; for(let i=0;i<3;++i) { const windLine = document.createElement("div"); windLine.style.position = "absolute"; windLine.style.left = (i==1? "-60px":"-44px"); windLine.style.top = (120+i*28)+"px"; windLine.style.width = (i==2? "90px":"110px"); windLine.style.height = "8px"; windLine.style.borderRadius = "18px"; windLine.style.opacity = 0.37 + Math.random()*0.15; windLine.style.background = "linear-gradient(90deg,#57e7fa 45%,#e6f3fe 100%)"; windLine.style.filter = "blur(0.5px)"; windLine.style.animation = `windline-move ${1.95+Math.random()*1.2}s linear infinite`; windLine.style.animationDelay = `${-Math.random()*2}s`; // Small wiggle: windLine.animate([ { transform: "translateY(0)" }, { transform: "translateY(3px)" }, { transform: "translateY(0)" } ], { duration:800+Math.random()*800, direction:'alternate', iterations:Infinity }); windLineContainer.appendChild(windLine); } cardElem.querySelector('.card-bg').appendChild(windLineContainer); } // Function to create rain drops for the Rainy card function renderRaining(cardElem) { const dropsContainer = document.createElement("div"); dropsContainer.style.position = "absolute"; dropsContainer.style.left = "0"; dropsContainer.style.top = "0"; dropsContainer.style.width = "100%"; dropsContainer.style.height = "100%"; dropsContainer.style.zIndex = "22"; for(let i=0;i<12;++i) { const drop = document.createElement("div"); drop.style.position = "absolute"; drop.style.width = "5px"; drop.style.height = `${12+Math.random()*7}px`; drop.style.left = (55+Math.random()*110)+'px'; drop.style.top = "153px"; drop.style.borderRadius = "46% 58% 44% 56%/48% 70% 37% 52%"; drop.style.background = "radial-gradient(circle at 80% 20%,#b9f6ff 33%,#53a3ef 70%)"; drop.style.opacity = Math.random()*0.22+0.66; const animDur = 1.22+Math.random()*0.9; drop.style.animation = `raindrop-fall ${animDur}s cubic-bezier(.59,.9,.4,1) infinite`; drop.style.animationDelay = `${-Math.random()*animDur}s`; // Tiny puddle splash for large drops (occasionally) if(Math.random()>0.67) { const splash = document.createElement("div"); splash.style.position = "absolute"; splash.style.top = "99%"; splash.style.left = "42%"; splash.style.width = "15px"; splash.style.height = "4px"; splash.style.transform = "scaleY(0.8)"; splash.style.background = "radial-gradient(ellipse at 15% 55%,#aee1f6 58%,#699acc 100%)"; splash.style.opacity = "0.6"; splash.style.borderRadius = "8px"; drop.appendChild(splash); } dropsContainer.appendChild(drop); } cardElem.querySelector('.card-bg').appendChild(dropsContainer); } // Function to create snow flakes for the Snowy card function renderSnowing(cardElem) { const snowContainer = document.createElement("div"); snowContainer.style.position = "absolute"; snowContainer.style.left = "0"; snowContainer.style.top = "0"; snowContainer.style.width = "100%"; snowContainer.style.height = "100%"; snowContainer.style.zIndex = "23"; for(let i=0;i<15;++i) { const flake = document.createElement("div"); flake.style.position = "absolute"; flake.style.width = flake.style.height = (7+Math.random()*7)+'px'; flake.style.left = (29+Math.random()*166)+'px'; flake.style.top = "142px"; flake.style.opacity = (0.65+Math.random()*0.33).toFixed(2); // Use SVG shape for premium snow flake flake.innerHTML = ` <svg width="100%" height="100%" viewBox="0 0 15 15" fill="none"> <g opacity="0.97"> <circle cx="7.5" cy="7.5" r="2.8" fill="#fff" fill-opacity="0.95"/> <path d="M7.5 1 V14" stroke="#aee2fd" stroke-width="2" stroke-linecap="round" opacity="0.88"/> <path d="M1 7.5 H14" stroke="#beeefd" stroke-width="2" stroke-linecap="round" opacity="0.82"/> <path d="M2.3 2.3 L13 13" stroke="#d8f4ff" stroke-width="1.2" stroke-linecap="round" opacity="0.92"/> <path d="M2.3 12.7 L13 2.1" stroke="#d8f4ff" stroke-width="1.2" stroke-linecap="round" opacity="0.92"/> </g> </svg> `; const dur = 2.7+Math.random()*2.6; flake.style.animation = `snow-fall ${dur}s cubic-bezier(.32,0.89,0.22,1) infinite`; flake.style.animationDelay = `${-dur*Math.random()}s`; snowContainer.appendChild(flake); } cardElem.querySelector('.card-bg').appendChild(snowContainer); } // Dynamically render all cards (or a single card type) function renderWeatherCards(show='all') { const cardStrip = document.getElementById('cardStrip'); cardStrip.innerHTML = ''; let cardsToDisplay = (show==='all'? weatherCards: weatherCards.filter(w=>w.key===show)); for(const w of cardsToDisplay) { const cardElem = document.createElement('div'); cardElem.className = 'weather-card'; cardElem.innerHTML = w.card + `<div class="weather-content"> <div class="weather-title">${w.name}</div> <div class="weather-temp">${w.temp}</div> <div class="weather-desc">${w.desc}</div> </div>`; // Weather-specific animation overlays if(w.key==='wind') renderWindLines(cardElem); else if(w.key==='rain') renderRaining(cardElem); else if(w.key==='snow') renderSnowing(cardElem); cardStrip.appendChild(cardElem); } } // Button switches document.querySelectorAll('.weather-btn').forEach(btn=>{ btn.addEventListener('click',()=>{ document.querySelectorAll('.weather-btn').forEach(b=>b.classList.remove('active')); btn.classList.add('active'); renderWeatherCards(btn.dataset.weather); }); }); // On load: show all renderWeatherCards('all'); </script> </body> </html> ```
Below is a single HTML file that includes CSS and JavaScript to create an animated weather card. The card visually represents four weather conditions (Wind, Rain, Sun, Snow) with distinct animations. The UI is designed to meet premium-quality standards with a dark background and polished transitions. ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Animated Weather Card</title> <style> body { display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background-color: #1a1a1a; font-family: 'Arial', sans-serif; } .weather-container { display: flex; gap: 20px; } .weather-card { position: relative; width: 200px; height: 300px; background-color: #2a2a2a; border-radius: 16px; box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3); overflow: hidden; display: flex; justify-content: center; align-items: center; color: white; cursor: pointer; transition: transform 0.3s ease; } .weather-card:hover { transform: translateY(-5px); } .weather-card .condition { font-size: 24px; font-weight: bold; z-index: 2; } /* Wind Animation */ .wind .clouds { position: absolute; top: 20%; left: -20px; animation: moveClouds 5s linear infinite; } .wind .cloud { width: 50px; height: 50px; background: #fff; border-radius: 50%; position: absolute; } .wind .cloud::before, .wind .cloud::after { content: ''; position: absolute; background: #fff; border-radius: 50%; } .wind .cloud::before { width: 70px; height: 70px; top: -20px; left: 10px; } .wind .cloud::after { width: 60px; height: 60px; top: -10px; left: 30px; } @keyframes moveClouds { 0% { transform: translateX(0); } 100% { transform: translateX(200px); } } /* Rain Animation */ .rain .drop { position: absolute; width: 2px; height: 10px; background: #64b5f6; animation: fallRain 1s linear infinite; } @keyframes fallRain { 0% { transform: translateY(-300px); } 100% { transform: translateY(300px); } } /* Sun Animation */ .sun .sun-circle { width: 100px; height: 100px; background: #ffd700; border-radius: 50%; box-shadow: 0 0 50px #ffd700; animation: shineSun 2s ease-in-out infinite; } @keyframes shineSun { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.1); } } /* Snow Animation */ .snow .flake { position: absolute; width: 8px; height: 8px; background: white; border-radius: 50%; animation: fallSnow 5s linear infinite; } @keyframes fallSnow { 0% { transform: translateY(-300px); } 100% { transform: translateY(300px); } } /* Buttons */ .controls { position: absolute; top: 20px; left: 50%; transform: translateX(-50%); display: flex; gap: 10px; } .controls button { padding: 10px 20px; background-color: #333; color: white; border: none; border-radius: 8px; cursor: pointer; transition: background-color 0.3s ease; } .controls button:hover { background-color: #555; } </style> </head> <body> <div class="controls"> <button onclick="setWeather('wind')">Wind</button> <button onclick="setWeather('rain')">Rain</button> <button onclick="setWeather('sun')">Sun</button> <button onclick="setWeather('snow')">Snow</button> </div> <div class="weather-container"> <div class="weather-card" onclick="setWeather('wind')"> <div class="condition">Wind</div> <div class="clouds"> <div class="cloud"></div> </div> </div> <div class="weather-card" onclick="setWeather('rain')"> <div class="condition">Rain</div> </div> <div class="weather-card" onclick="setWeather('sun')"> <div class="condition">Sun</div> <div class="sun-circle"></div> </div> <div class="weather-card" onclick="setWeather('snow')"> <div class="condition">Snow</div> </div> </div> <script> const weatherCards = document.querySelectorAll('.weather-card'); const conditions = ['wind', 'rain', 'sun', 'snow']; function setWeather(condition) { weatherCards.forEach(card => { card.classList.remove(...conditions); if (card.querySelector('.condition').innerText.toLowerCase() === condition) { card.classList.add(condition); addAnimationElements(card, condition); } }); } function addAnimationElements(card, condition) { // Clear existing animations card.innerHTML = `<div class="condition">${condition.charAt(0).toUpperCase() + condition.slice(1)}</div>`; switch (condition) { case 'rain': for (let i = 0; i < 20; i++) { const drop = document.createElement('div'); drop.classList.add('drop'); drop.style.left = `${Math.random() * 100}%`; drop.style.animationDuration = `${Math.random() * 0.5 + 0.5}s`; card.appendChild(drop); } break; case 'snow': for (let i = 0; i < 30; i++) { const flake = document.createElement('div'); flake.classList.add('flake'); flake.style.left = `${Math.random() * 100}%`; flake.style.animationDuration = `${Math.random() * 3 + 2}s`; card.appendChild(flake); } break; case 'sun': const sunCircle = document.createElement('div'); sunCircle.classList.add('sun-circle'); card.appendChild(sunCircle); break; case 'wind': const clouds = document.createElement('div'); clouds.classList.add('clouds'); clouds.innerHTML = `<div class="cloud"></div>`; card.appendChild(clouds); break; } } // Initialize with default weather conditions conditions.forEach((condition, index) => { weatherCards[index].classList.add(condition); addAnimationElements(weatherCards[index], condition); }); </script> </body> </html> ``` ### Features: 1. **Four Weather Cards**: Wind, Rain, Sun, and Snow displayed side by side. 2. **Animations**: - **Wind**: Moving clouds. - **Rain**: Falling raindrops. - **Sun**: Shining sun with pulsating effect. - **Snow**: Falling snowflakes. 3. **Interactive Controls**: Buttons to switch between weather conditions. 4. **Premium Design**: Dark background, smooth transitions, and polished animations. ### How It Works: - The `setWeather` function updates the active weather condition and adds corresponding animation elements. - Each card is clickable and can be switched using the buttons at the top. - The animations are created using CSS keyframes and dynamically added via JavaScript. This code provides a visually stunning and interactive weather card experience.
```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Animated Weather Cards</title> <style> :root { --bg-color: #1a1a1a; --card-color: #2d2d2d; --button-color: #3a3a3a; --text-color: #ffffff; --sun-yellow: #FFD666; --snow-white: #f0f8ff; --rain-blue: #66ccff; } * { box-sizing: border-box; margin: 0; padding: 0; } body { background: var(--bg-color); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; display: flex; flex-direction: column; align-items: center; padding: 40px 20px; min-height: 100vh; color: var(--text-color); } .card-container { display: flex; gap: 20px; flex-wrap: wrap; justify-content: center; margin-bottom: 30px; } .weather-card { background: var(--card-color); border-radius: 25px; width: 280px; height: 400px; position: relative; overflow: hidden; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); display: flex; justify-content: center; align-items: center; transition: 0.3s ease; } .weather-card:hover { transform: translateY(-5px); box-shadow: 0 15px 40px rgba(0, 0, 0, 0.4); } .scene { width: 100%; height: 100%; position: absolute; top: 0; left: 0; opacity: 0; z-index: 1; transition: opacity 0.5s ease-in-out; } .scene.active { opacity: 1; z-index: 2; } /* Wind */ .cloud { position: absolute; width: 100px; height: 50px; background: #fff; border-radius: 50%; animation: cloudMove 8s linear infinite; } .cloud.big { top: 80px; left: -50px; height: 60px; width: 120px; opacity: 0.6; } .cloud.small { top: 140px; left: -30px; height: 30px; width: 60px; opacity: 0.8; } @keyframes cloudMove { 0% { transform: translateX(0); } 100% { transform: translateX(110%); } } .wind-line { position: absolute; height: 1px; background: rgba(255, 255, 255, 0.4); opacity: 0.3; } .wind-line:nth-child(1) { width: 40px; top: 30px; animation: windLine 3s linear infinite; } .wind-line:nth-child(2) { width: 55px; top: 45px; animation: windLine 4s linear infinite; } .wind-line:nth-child(3) { width: 30px; top: 60px; animation: windLine 5s linear infinite; } @keyframes windLine { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } } /* Rain */ .rain-drop { position: absolute; width: 2px; height: 10px; background: var(--rain-blue); animation: rainAnimation 1s linear infinite; } @keyframes rainAnimation { 0% { transform: translateY(-10px); opacity: 0; } 20% { opacity: 1; } 100% { transform: translateY(380px); opacity: 0; } } .puddle { position: absolute; bottom: 10px; width: 100%; height: 20px; background: radial-gradient(circle at 50% 50%, rgba(0, 70, 150, 0.3) 0%, transparent 70%); opacity: 0; animation: puddleAppear 5s ease-in-out infinite; } @keyframes puddleAppear { 0%, 80% { opacity: 0; } 100% { opacity: 0.6; } } /* Sun */ .sun { position: absolute; top: 40%; left: 50%; transform: translate(-50%, -50%); width: 120px; height: 120px; background: radial-gradient(circle closest-side, var(--sun-yellow), #ff9900); border-radius: 50%; box-shadow: 0 0 40px 10px var(--sun-yellow); } .sun-ray { position: absolute; background: linear-gradient(transparent, var(--sun-yellow), transparent); transform-origin: center; } .sun-ray:nth-child(1) { width: 100%; height: 5px; top: 20px; left: 0; animation: sunRotate 8s linear infinite; } .sun-ray:nth-child(2) { width: 100%; height: 5px; top: 150px; left: 0; animation: sunRotate 10s linear infinite; } @keyframes sunRotate { from { transform: rotate(0deg) translateY(-30px); } to { transform: rotate(360deg) translateY(-30px); } } /* Snow */ .snowflake { position: absolute; width: 6px; height: 6px; background: white; border-radius: 50%; opacity: 0.8; animation: snowFall 6s linear infinite; } @keyframes snowFall { 0% { transform: translateY(-10%) translateX(0) rotate(0deg); } 100% { transform: translateY(120%) translateX(20px) rotate(360deg); } } .snow-pile { position: absolute; bottom: -5px; width: 100%; height: 20px; background: linear-gradient(to bottom, rgba(255,255,255,0.4), transparent 60%); } .button-group { display: flex; gap: 15px; margin-bottom: 30px; justify-content: center; } .nav-button { background: var(--button-color); border: none; padding: 12px 20px; border-radius: 20px; color: var(--text-color); font-weight: 500; cursor: pointer; transition: all 0.2s ease; font-size: 16px; } .nav-button:hover { background: #444; } </style> </head> <body> <div class="button-group"> <button class="nav-button" onclick="showWeather('wind')">Wind</button> <button class="nav-button" onclick="showWeather('rain')">Rain</button> <button class="nav-button" onclick="showWeather('sun')">Sun</button> <button class="nav-button" onclick="showWeather('snow')">Snow</button> </div> <div class="card-container"> <div class="weather-card"> <div class="scene active" id="wind"> <div class="cloud big"></div> <div class="cloud small"></div> <div class="wind-line"></div> <div class="wind-line"></div> <div class="wind-line"></div> </div> </div> <div class="weather-card"> <div class="scene" id="rain"> <!-- Dynamic drops will be injected by JS --> <div class="puddle"></div> </div> </div> <div class="weather-card"> <div class="scene" id="sun"> <div class="sun"></div> <div class="sun-ray"></div> <div class="sun-ray"></div> </div> </div> <div class="weather-card"> <div class="scene" id="snow"> <!-- Dynamic snowflakes will be injected by JS --> <div class="snow-pile"></div> </div> </div> </div> <script> function showWeather(condition) { document.querySelectorAll('.scene').forEach(scene => { scene.classList.remove('active'); }); document.getElementById(condition).classList.add('active'); } // Raindrops const rainContainer = document.querySelector('#rain'); for(let i = 0; i < 150; i++) { const drop = document.createElement('div'); drop.className = 'rain-drop'; drop.style.left = Math.random() * 100 + '%'; drop.style.animationDelay = Math.random() * 2 + 's'; drop.style.animationDuration = (Math.random() * 0.5 + 0.5) + 's'; rainContainer.appendChild(drop); } // Snowflakes const snowContainer = document.querySelector('#snow'); for(let i = 0; i < 100; i++) { const flake = document.createElement('div'); flake.className = 'snowflake'; flake.style.left = Math.random() * 100 + '%'; flake.style.top = -Math.random() * 10 + '%'; flake.style.opacity = Math.random() * 0.5 + 0.5; flake.style.fontSize = Math.random() * 4 + 2 + 'px'; flake.style.animationDelay = Math.random() * 3 + 's'; flake.style.animationDuration = (Math.random() * 4 + 3) + 's'; snowContainer.appendChild(flake); } </script> </body> </html> ```
Here's a single HTML file containing CSS and JavaScript to generate an animated weather card with the specified conditions. The file includes all necessary code within a single block. ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Animated Weather Cards</title> <style> body { font-family: 'Arial', sans-serif; background-color: #121212; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; overflow: hidden; } .weather-container { display: flex; gap: 20px; } .weather-card { background-color: #1e1e1e; border-radius: 20px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); width: 300px; height: 400px; position: relative; overflow: hidden; display: flex; flex-direction: column; align-items: center; justify-content: center; color: white; padding: 20px; box-sizing: border-box; } .weather-card h2 { margin: 0; font-size: 24px; text-align: center; margin-bottom: 20px; } .weather-card p { margin: 0; font-size: 16px; text-align: center; } .weather-card .temp { font-size: 48px; font-weight: bold; margin: 20px 0; } .weather-card .condition { font-size: 20px; margin-bottom: 20px; } .weather-card .wind { position: absolute; top: 50px; left: 20px; width: 260px; height: 260px; border: 2px solid rgba(255, 255, 255, 0.2); border-radius: 50%; display: flex; justify-content: center; align-items: center; } .weather-card .wind::before { content: ""; position: absolute; width: 100px; height: 2px; background-color: rgba(255, 255, 255, 0.5); transform-origin: center; animation: wind 3s linear infinite; } .weather-card .wind::after { content: ""; position: absolute; width: 100px; height: 2px; background-color: rgba(255, 255, 255, 0.5); transform-origin: center; animation: wind 3s linear infinite reverse; } .weather-card .rain { position: absolute; top: 0; left: 0; width: 100%; height: 100%; overflow: hidden; } .weather-card .rain-drop { position: absolute; width: 2px; height: 10px; background-color: rgba(255, 255, 255, 0.7); border-radius: 50%; top: -10px; left: 50%; transform: translateX(-50%); animation: rain 2s linear infinite; } .weather-card .sun { position: absolute; top: 50px; left: 50%; transform: translateX(-50%); width: 100px; height: 100px; border-radius: 50%; background: radial-gradient(circle, #ffcc00, #ff9900); box-shadow: 0 0 30px #ffcc00; } .weather-card .sun-ray { position: absolute; width: 2px; height: 50px; background-color: #ffcc00; top: 50px; left: 50%; transform-origin: top center; animation: sun-ray 2s linear infinite; } .weather-card .snow { position: absolute; top: 0; left: 0; width: 100%; height: 100%; overflow: hidden; } .weather-card .snowflake { position: absolute; width: 4px; height: 4px; background-color: rgba(255, 255, 255, 0.8); border-radius: 50%; top: -4px; left: 50%; transform: translateX(-50%); animation: snow 3s linear infinite; } .controls { position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); display: flex; gap: 10px; } .controls button { background-color: #333; color: white; border: none; border-radius: 10px; padding: 8px 16px; cursor: pointer; font-size: 14px; transition: background-color 0.3s; } .controls button:hover { background-color: #555; } @keyframes wind { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @keyframes rain { 0% { top: -10px; transform: translateX(-50%); } 100% { top: 100%; transform: translateX(calc(-50% + 50px)); } } @keyframes sun-ray { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @keyframes snow { 0% { top: -4px; transform: translateX(-50%); } 100% { top: 100%; transform: translateX(calc(-50% + 20px)); } } </style> </head> <body> <div class="weather-container"> <div class="weather-card" id="wind-card"> <h2>Wind</h2> <div class="temp">15°</div> <div class="condition">Windy</div> <div class="wind"></div> <div class="controls"> <button onclick="changeWeather('wind')">Wind</button> <button onclick="changeWeather('rain')">Rain</button> <button onclick="changeWeather('sun')">Sun</button> <button onclick="changeWeather('snow')">Snow</button> </div> </div> <div class="weather-card" id="rain-card"> <h2>Rain</h2> <div class="temp">12°</div> <div class="condition">Rainy</div> <div class="rain" id="rain"></div> <div class="controls"> <button onclick="changeWeather('wind')">Wind</button> <button onclick="changeWeather('rain')">Rain</button> <button onclick="changeWeather('sun')">Sun</button> <button onclick="changeWeather('snow')">Snow</button> </div> </div> <div class="weather-card" id="sun-card"> <h2>Sun</h2> <div class="temp">25°</div> <div class="condition">Sunny</div> <div class="sun" id="sun"> <div class="sun-ray"></div> <div class="sun-ray" style="transform: rotate(45deg) translateX(-50%);"></div> <div class="sun-ray" style="transform: rotate(90deg) translateX(-50%);"></div> <div class="sun-ray" style="transform: rotate(135deg) translateX(-50%);"></div> <div class="sun-ray" style="transform: rotate(180deg) translateX(-50%);"></div> <div class="sun-ray" style="transform: rotate(225deg) translateX(-50%);"></div> <div class="sun-ray" style="transform: rotate(270deg) translateX(-50%);"></div> <div class="sun-ray" style="transform: rotate(315deg) translateX(-50%);"></div> </div> <div class="controls"> <button onclick="changeWeather('wind')">Wind</button> <button onclick="changeWeather('rain')">Rain</button> <button onclick="changeWeather('sun')">Sun</button> <button onclick="changeWeather('snow')">Snow</button> </div> </div> <div class="weather-card" id="snow-card"> <h2>Snow</h2> <div class="temp">5°</div> <div class="condition">Snowy</div> <div class="snow" id="snow"></div> <div class="controls"> <button onclick="changeWeather('wind')">Wind</button> <button onclick="changeWeather('rain')">Rain</button> <button onclick="changeWeather('sun')">Sun</button> <button onclick="changeWeather('snow')">Snow</button> </div> </div> </div> <script> function changeWeather(weatherType) { const cards = document.querySelectorAll('.weather-card'); cards.forEach(card => { card.querySelector('.wind').style.display = 'none'; card.querySelector('.rain').style.display = 'none'; card.querySelector('.sun').style.display = 'none'; card.querySelector('.snow').style.display = 'none'; }); if (weatherType === 'wind') { document.getElementById('wind-card').querySelector('.wind').style.display = 'flex'; } else if (weatherType === 'rain') { document.getElementById('rain-card').querySelector('.rain').style.display = 'block'; createRainDrops(); } else if (weatherType === 'sun') { document.getElementById('sun-card').querySelector('.sun').style.display = 'block'; } else if (weatherType === 'snow') { document.getElementById('snow-card').querySelector('.snow').style.display = 'block'; createSnowflakes(); } } function createRainDrops() { const rain = document.getElementById('rain'); rain.innerHTML = ''; for (let i = 0; i < 50; i++) { const drop = document.createElement('div'); drop.className = 'rain-drop'; drop.style.left = `${Math.random() * 100}%`; drop.style.animationDelay = `${Math.random() * 2}s`; rain.appendChild(drop); } } function createSnowflakes() { const snow = document.getElementById('snow'); snow.innerHTML = ''; for (let i = 0; i < 50; i++) { const flake = document.createElement('div'); flake.className = 'snowflake'; flake.style.left = `${Math.random() * 100}%`; flake.style.animationDelay = `${Math.random() * 3}s`; snow.appendChild(flake); } } // Initialize the weather cards createRainDrops(); createSnowflakes(); </script> </body> </html> ```
```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Premium Weather Cards</title> <style> @import url('https://fonts.googleapis.com/css2?family=SF+Pro+Display:wght@300;400;600;700&display=swap'); * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif; background: linear-gradient(135deg, #0a0a0a 0%, #1a1a2e 100%); min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; color: white; overflow-x: auto; padding: 40px 20px; } .container { display: flex; gap: 40px; flex-wrap: wrap; justify-content: center; max-width: 1400px; } .weather-card { width: 320px; height: 420px; background: linear-gradient(135deg, #1e1e2e 0%, #2a2a3a 100%); border-radius: 32px; padding: 30px; position: relative; overflow: hidden; backdrop-filter: blur(20px); border: 1px solid rgba(255, 255, 255, 0.1); box-shadow: 0 25px 50px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.05), inset 0 1px 0 rgba(255, 255, 255, 0.1); transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); cursor: pointer; } .weather-card:hover { transform: translateY(-10px) scale(1.02); box-shadow: 0 35px 70px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15); } .weather-content { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; z-index: 10; width: 100%; padding: 0 20px; } .temperature { font-size: 72px; font-weight: 200; margin-bottom: 5px; letter-spacing: -2px; opacity: 0; animation: fadeIn 1s ease-out 0.2s forwards; } .location { font-size: 24px; font-weight: 400; margin-bottom: 8px; opacity: 0.9; letter-spacing: -0.5px; opacity: 0; animation: fadeIn 1s ease-out 0.3s forwards; } .condition { font-size: 18px; font-weight: 300; color: rgba(255, 255, 255, 0.7); letter-spacing: -0.3px; opacity: 0; animation: fadeIn 1s ease-out 0.4s forwards; } .weather-icon { font-size: 48px; margin-bottom: 15px; opacity: 0; animation: fadeIn 1s ease-out 0.1s forwards; } @keyframes fadeIn { to { opacity: 1; } } .animation-container { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 1; } /* Wind Animation */ .wind-particle { position: absolute; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); height: 2px; border-radius: 1px; animation: windMove 3s ease-in-out infinite; } @keyframes windMove { 0% { transform: translateX(-100%) translateY(0) scaleX(0); opacity: 0; } 20% { opacity: 1; } 80% { transform: translateX(100%) translateY(-20px) scaleX(1); opacity: 1; } 100% { transform: translateX(100%) translateY(-20px) scaleX(0); opacity: 0; } } .cloud { position: absolute; background: rgba(255, 255, 255, 0.1); border-radius: 50px; animation: cloudFloat 20s ease-in-out infinite; } .cloud:before { content: ''; position: absolute; background: rgba(255, 255, 255, 0.1); border-radius: 50px; width: 60%; height: 80%; top: -30%; left: 10%; } .cloud:after { content: ''; position: absolute; background: rgba(255, 255, 255, 0.1); border-radius: 50px; width: 60%; height: 60%; top: -20%; right: 10%; } @keyframes cloudFloat { 0%, 100% { transform: translateX(-100px) scale(0.8); } 50% { transform: translateX(400px) scale(1.2); } } /* Rain Animation */ .raindrop { position: absolute; width: 2px; background: linear-gradient(180deg, transparent, rgba(173, 216, 230, 0.8)); border-radius: 50px; animation: rainFall linear infinite; } @keyframes rainFall { to { transform: translateY(420px); } } .puddle { position: absolute; bottom: 20px; width: 100%; height: 3px; background: linear-gradient(90deg, transparent, rgba(173, 216, 230, 0.3), transparent); border-radius: 50%; animation: puddleExpand 3s ease-in-out infinite; } @keyframes puddleExpand { 0%, 100% { transform: scaleX(0.9) scaleY(1); opacity: 0.2; } 50% { transform: scaleX(1.1) scaleY(1.2); opacity: 0.4; } } /* Sun Animation */ .sun { position: absolute; width: 100px; height: 100px; background: radial-gradient(circle, #ffd700, #ffa500); border-radius: 50%; top: 50%; left: 50%; transform: translate(-50%, -50%); animation: sunPulse 4s ease-in-out infinite; } @keyframes sunPulse { 0%, 100% { transform: translate(-50%, -50%) scale(1); box-shadow: 0 0 40px rgba(255, 215, 0, 0.6); } 50% { transform: translate(-50%, -50%) scale(1.1); box-shadow: 0 0 80px rgba(255, 215, 0, 0.8); } } .sun-ray { position: absolute; width: 2px; height: 30px; background: linear-gradient(180deg, #ffd700, transparent); top: 50%; left: 50%; transform-origin: center 50px; border-radius: 1px; animation: rotateRay 10s linear infinite; } @keyframes rotateRay { from { transform: translate(-50%, -50%) rotate(0deg); } to { transform: translate(-50%, -50%) rotate(360deg); } } /* Snow Animation */ .snowflake { position: absolute; color: white; font-size: 12px; animation: snowFall linear infinite; text-shadow: 0 0 10px rgba(255, 255, 255, 0.8); } @keyframes snowFall { 0% { transform: translateY(-50px) translateX(0) rotate(0deg); } 100% { transform: translateY(420px) translateX(40px) rotate(360deg); } } .snow-ground { position: absolute; bottom: 0; width: 100%; height: 40px; background: linear-gradient(180deg, transparent, rgba(255, 255, 255, 0.3)); transform-origin: bottom; animation: snowBuildup 6s ease-in-out infinite; } @keyframes snowBuildup { 0%, 100% { transform: scaleY(0.8); height: 30px; } 50% { transform: scaleY(1.2); height: 50px; } } .glow { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 200%; height: 200%; background: radial-gradient(circle, rgba(255, 255, 255, 0.05) 0%, transparent 70%); pointer-events: none; opacity: 0; transition: opacity 0.3s ease; } .weather-card:hover .glow { opacity: 1; } .title { font-size: 42px; font-weight: 700; letter-spacing: -1px; margin-bottom: 50px; background: linear-gradient(135deg, #fff 0%, rgba(255, 255, 255, 0.7) 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } </style> </head> <body> <h1 class="title">Weather Conditions</h1> <div class="container"> <div class="weather-card" id="wind-card"> <div class="glow"></div> <div class="weather-content"> <div class="weather-icon">💨</div> <div class="temperature">18°</div> <div class="location">Seattle</div> <div class="condition">Windy</div> </div> <div class="animation-container" id="wind-animation"></div> </div> <div class="weather-card" id="rain-card"> <div class="glow"></div> <div class="weather-content"> <div class="weather-icon">🌧️</div> <div class="temperature">14°</div> <div class="location">London</div> <div class="condition">Light Rain</div> </div> <div class="animation-container" id="rain-animation"></div> </div> <div class="weather-card" id="sun-card"> <div class="glow"></div> <div class="weather-content"> <div class="weather-icon">☀️</div> <div class="temperature">28°</div> <div class="location">Miami</div> <div class="condition">Sunny</div> </div> <div class="animation-container" id="sun-animation"></div> </div> <div class="weather-card" id="snow-card"> <div class="glow"></div> <div class="weather-content"> <div class="weather-icon">❄️</div> <div class="temperature">-5°</div> <div class="location">Helsinki</div> <div class="condition">Snowfall</div> </div> <div class="animation-container" id="snow-animation"></div> </div> </div> <script> // Wind animation function createWind() { const container = document.getElementById('wind-animation'); container.innerHTML = ''; // Create clouds for (let i = 0; i < 3; i++) { const cloud = document.createElement('div'); cloud.className = 'cloud'; cloud.style.width = `${70 + Math.random() * 50}px`; cloud.style.height = `${40 + Math.random() * 30}px`; cloud.style.top = `${10 + Math.random() * 150}px`; cloud.style.animationDelay = `${i * 7}s`; cloud.style.animationDuration = `${15 + Math.random() * 10}s`; container.appendChild(cloud); } // Create wind particles for (let i = 0; i < 20; i++) { const particle = document.createElement('div'); particle.className = 'wind-particle'; particle.style.width = `${50 + Math.random() * 100}px`; particle.style.top = `${Math.random() * 100}%`; particle.style.left = `${-50}px`; particle.style.animationDelay = `${Math.random() * 3}s`; particle.style.animationDuration = `${2 + Math.random() * 3}s`; container.appendChild(particle); } } // Rain animation function createRain() { const container = document.getElementById('rain-animation'); container.innerHTML = ''; // Create puddle const puddle = document.createElement('div'); puddle.className = 'puddle'; puddle.style.bottom = '30px'; container.appendChild(puddle); // Create raindrops for (let i = 0; i < 50; i++) { const drop = document.createElement('div'); drop.className = 'raindrop'; drop.style.left = `${Math.random() * 100}%`; drop.style.top = `-50px`; drop.style.height = `${10 + Math.random() * 20}px`; drop.style.animationDuration = `${0.4 + Math.random() * 0.8}s`; drop.style.animationDelay = `${Math.random() * 1.5}s`; container.appendChild(drop); } } // Sun animation function createSun() { const container = document.getElementById('sun-animation'); container.innerHTML = ''; // Create sun const sun = document.createElement('div'); sun.className = 'sun'; container.appendChild(sun); // Create sun rays for (let i = 0; i < 12; i++) { const ray = document.createElement('div'); ray.className = 'sun-ray'; ray.style.transform = `translate(-50%, -50%) rotate(${i * 30}deg)`; container.appendChild(ray); } // Create floating particles for sunny look for (let i = 0; i < 5; i++) { const particle = document.createElement('div'); particle.style.position = 'absolute'; particle.style.width = '2px'; particle.style.height = '2px'; particle.style.backgroundColor = 'rgba(255, 215, 0, 0.6)'; particle.style.borderRadius = '50%'; particle.style.top = `${20 + Math.random() * 60}%`; particle.style.left = `${20 + Math.random() * 60}%`; particle.style.animation = 'float 4s ease-in-out infinite'; particle.style.animationDelay = `${i * 0.8}s`; container.appendChild(particle); } } // Snow animation function createSnow() { const container = document.getElementById('snow-animation'); container.innerHTML = ''; // Create snow ground const ground = document.createElement('div'); ground.className = 'snow-ground'; container.appendChild(ground); // Create snowflakes const snowflakes = ['❄', '❅', '❆']; for (let i = 0; i < 30; i++) { const flake = document.createElement('div'); flake.className = 'snowflake'; flake.innerHTML = snowflakes[Math.floor(Math.random() * snowflakes.length)]; flake.style.left = `${Math.random() * 100}%`; flake.style.top = `-50px`; flake.style.fontSize = `${8 + Math.random() * 8}px`; flake.style.animationDuration = `${3 + Math.random() * 5}s`; flake.style.animationDelay = `${Math.random() * 2}s`; container.appendChild(flake); } } // Initialize all animations function init() { createWind(); createRain(); createSun(); createSnow(); } // Start animations on page load window.addEventListener('load', init); // Add floating animation for sun particles const floatStyle = document.createElement('style'); floatStyle.innerHTML = ` @keyframes float { 0%, 100% { transform: translateY(0px) translateX(0px); opacity: 0.3; } 25% { transform: translateY(-10px) translateX(5px); opacity: 0.7; } 50% { transform: translateY(-5px) translateX(10px); opacity: 0.4; } 75% { transform: translateY(-15px) translateX(3px); opacity: 0.8; } } `; document.head.appendChild(floatStyle); // Add interactivity to cards document.querySelectorAll('.weather-card').forEach(card => { card.addEventListener('mouseenter', function() { this.style.transform = 'translateY(-10px) scale(1.02)'; }); card.addEventListener('mouseleave', function() { this.style.transform = 'translateY(0) scale(1)'; }); }); </script> </body> </html> ```
Here's a single HTML file containing CSS and JavaScript to generate an animated weather card with a dark background and polished UI. The code includes animations for wind, rain, sun, and snow, with buttons to switch between different weather conditions. ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Animated Weather Cards</title> <style> body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; background-color: #121212; color: white; display: flex; flex-direction: column; align-items: center; padding: 20px; } h1 { margin-bottom: 30px; font-size: 28px; font-weight: 600; } .weather-container { display: flex; justify-content: center; flex-wrap: wrap; gap: 20px; margin-bottom: 30px; } .weather-card { width: 250px; height: 350px; background: linear-gradient(135deg, #1e1e1e, #2d2d2d); border-radius: 20px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); overflow: hidden; position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 20px; transition: transform 0.3s ease, box-shadow 0.3s ease; } .weather-card:hover { transform: translateY(-5px); box-shadow: 0 15px 35px rgba(0, 0, 0, 0.4); } .weather-icon { font-size: 80px; margin-bottom: 20px; opacity: 0.9; } .weather-info { text-align: center; } .weather-info h2 { font-size: 24px; margin-bottom: 10px; font-weight: 500; } .weather-info p { font-size: 16px; opacity: 0.8; margin-bottom: 5px; } .weather-details { display: flex; justify-content: space-around; width: 100%; margin-top: 20px; } .weather-detail { text-align: center; } .weather-detail p { font-size: 14px; opacity: 0.7; margin-bottom: 5px; } .weather-detail span { font-size: 18px; font-weight: 500; } .controls { display: flex; gap: 10px; margin-bottom: 20px; } button { background: linear-gradient(135deg, #3a3a3a, #4a4a4a); color: white; border: none; border-radius: 10px; padding: 10px 20px; font-size: 16px; cursor: pointer; transition: background 0.3s ease, transform 0.2s ease; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } button:hover { background: linear-gradient(135deg, #4a4a4a, #5a5a5a); transform: translateY(-2px); } button:active { transform: translateY(0); } button.selected { background: linear-gradient(135deg, #007AFF, #0055CC); box-shadow: 0 4px 10px rgba(0, 122, 255, 0.3); } /* Animations */ .sun { position: relative; width: 100px; height: 100px; background: radial-gradient(circle at center, #FFD700, #FF4500); border-radius: 50%; box-shadow: 0 0 30px #FFD700; animation: pulse 2s infinite alternate; } .sun-ray { position: absolute; background: linear-gradient(to right, transparent, #FFD700); height: 3px; width: 120px; top: 50%; left: 50%; transform-origin: left center; } .sun-ray:nth-child(1) { transform: rotate(0deg); } .sun-ray:nth-child(2) { transform: rotate(45deg); } .sun-ray:nth-child(3) { transform: rotate(90deg); } .sun-ray:nth-child(4) { transform: rotate(135deg); } .sun-ray:nth-child(5) { transform: rotate(180deg); } .sun-ray:nth-child(6) { transform: rotate(225deg); } .sun-ray:nth-child(7) { transform: rotate(270deg); } .sun-ray:nth-child(8) { transform: rotate(315deg); } @keyframes pulse { 0% { box-shadow: 0 0 30px #FFD700; } 100% { box-shadow: 0 0 50px #FFD700, 0 0 70px #FF4500; } } .rain { position: relative; width: 100%; height: 100px; } .raindrop { position: absolute; width: 2px; height: 15px; background: linear-gradient(to bottom, transparent, #aad4ff); border-radius: 0 0 5px 5px; animation: fall linear infinite; } @keyframes fall { to { transform: translateY(100px); } } .cloud { position: relative; width: 100px; height: 60px; background: #4a4a4a; border-radius: 50px; margin: 0 auto; } .cloud:before, .cloud:after { content: ''; position: absolute; background: #4a4a4a; border-radius: 50px; } .cloud:before { width: 70px; height: 50px; left: -30px; top: -15px; } .cloud:after { width: 60px; height: 40px; left: 15px; top: -20px; } .wind { position: relative; width: 100%; height: 100px; overflow: hidden; } .wind-line { position: absolute; height: 2px; background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.5)); animation: wind linear infinite; } @keyframes wind { 0% { transform: translateX(-100px); opacity: 0; } 50% { opacity: 0.8; } 100% { transform: translateX(100px); opacity: 0; } } .snowflake { position: absolute; color: #aad4ff; user-select: none; pointer-events: none; animation: fall-snow linear infinite; } @keyframes fall-snow { to { transform: translateY(100px); } } .snow-ground { position: absolute; bottom: 0; left: 0; right: 0; height: 10px; background: linear-gradient(to bottom, transparent, rgba(255, 255, 255, 0.3)); } </style> </head> <body> <h1>Animated Weather Cards</h1> <div class="controls"> <button onclick="setWeather('sun')" class="selected">Sunny</button> <button onclick="setWeather('rain')">Rainy</button> <button onclick="setWeather('wind')">Windy</button> <button onclick="setWeather('snow')">Snowy</button> </div> <div class="weather-container"> <div class="weather-card" id="weather-card-1"> <div class="weather-icon" id="weather-icon-1"> <div class="sun" id="sun-1"> <div class="sun-ray"></div> <div class="sun-ray"></div> <div class="sun-ray"></div> <div class="sun-ray"></div> <div class="sun-ray"></div> <div class="sun-ray"></div> <div class="sun-ray"></div> <div class="sun-ray"></div> </div> </div> <div class="weather-info"> <h2 id="weather-title-1">Sunny</h2> <p id="weather-desc-1">Clear skies with bright sunshine</p> </div> <div class="weather-details"> <div class="weather-detail"> <p>Temperature</p> <span id="weather-temp-1">28°C</span> </div> <div class="weather-detail"> <p>Humidity</p> <span id="weather-humidity-1">45%</span> </div> </div> </div> <div class="weather-card" id="weather-card-2"> <div class="weather-icon" id="weather-icon-2"> <div class="cloud" id="cloud-2"></div> <div class="rain" id="rain-2"></div> </div> <div class="weather-info"> <h2 id="weather-title-2">Rainy</h2> <p id="weather-desc-2">Heavy rainfall expected</p> </div> <div class="weather-details"> <div class="weather-detail"> <p>Temperature</p> <span id="weather-temp-2">18°C</span> </div> <div class="weather-detail"> <p>Humidity</p> <span id="weather-humidity-2">85%</span> </div> </div> </div> <div class="weather-card" id="weather-card-3"> <div class="weather-icon" id="weather-icon-3"> <div class="wind" id="wind-3"></div> </div> <div class="weather-info"> <h2 id="weather-title-3">Windy</h2> <p id="weather-desc-3">Strong winds blowing</p> </div> <div class="weather-details"> <div class="weather-detail"> <p>Temperature</p> <span id="weather-temp-3">15°C</span> </div> <div class="weather-detail"> <p>Humidity</p> <span id="weather-humidity-3">55%</span> </div> </div> </div> <div class="weather-card" id="weather-card-4"> <div class="weather-icon" id="weather-icon-4"> <div class="snow" id="snow-4"></div> </div> <div class="weather-info"> <h2 id="weather-title-4">Snowy</h2> <p id="weather-desc-4">Heavy snowfall expected</p> </div> <div class="weather-details"> <div class="weather-detail"> <p>Temperature</p> <span id="weather-temp-4">-5°C</span> </div> <div class="weather-detail"> <p>Humidity</p> <span id="weather-humidity-4">70%</span> </div> </div> </div> </div> <script> // Set initial weather animations document.addEventListener('DOMContentLoaded', function() { createSunAnimation(); createRainAnimation(); createWindAnimation(); createSnowAnimation(); }); // Function to set weather type function setWeather(type) { // Update button states const buttons = document.querySelectorAll('button'); buttons.forEach(button => { button.classList.remove('selected'); if (button.textContent.toLowerCase() === type) { button.classList.add('selected'); } }); // Update weather cards based on type const cards = document.querySelectorAll('.weather-card'); cards.forEach((card, index) => { const icon = card.querySelector('.weather-icon'); const title = card.querySelector('h2'); const desc = card.querySelector('p'); const temp = card.querySelector('.weather-detail span:nth-child(2)'); const humidity = card.querySelector('.weather-detail span:nth-child(4)'); switch(type) { case 'sun': title.textContent = 'Sunny'; desc.textContent = 'Clear skies with bright sunshine'; temp.textContent = `${25 + index}°C`; humidity.textContent = `${40 + index * 5}%`; break; case 'rain': title.textContent = 'Rainy'; desc.textContent = 'Heavy rainfall expected'; temp.textContent = `${15 + index * 2}°C`; humidity.textContent = `${75 + index * 5}%`; break; case 'wind': title.textContent = 'Windy'; desc.textContent = 'Strong winds blowing'; temp.textContent = `${12 + index * 3}°C`; humidity.textContent = `${50 + index * 5}%`; break; case 'snow': title.textContent = 'Snowy'; desc.textContent = 'Heavy snowfall expected'; temp.textContent = `${-8 + index * 2}°C`; humidity.textContent = `${65 + index * 5}%`; break; } }); } // Sun animation function createSunAnimation() { const sunElements = document.querySelectorAll('.sun'); sunElements.forEach(sun => { // Sun is already styled with CSS animations }); } // Rain animation function createRainAnimation() { const rainContainers = document.querySelectorAll('.rain'); rainContainers.forEach(container => { container.innerHTML = ''; for (let i = 0; i < 30; i++) { const raindrop = document.createElement('div'); raindrop.className = 'raindrop'; raindrop.style.left = `${Math.random() * 100}%`; raindrop.style.top = `${-Math.random() * 100}px`; raindrop.style.animationDuration = `${0.5 + Math.random()}s`; raindrop.style.animationDelay = `${Math.random()}s`; container.appendChild(raindrop); } }); } // Wind animation function createWindAnimation() { const windContainers = document.querySelectorAll('.wind'); windContainers.forEach(container => { container.innerHTML = ''; for (let i = 0; i < 5; i++) { const windLine = document.createElement('div'); windLine.className = 'wind-line'; windLine.style.top = `${20 + i * 20}px`; windLine.style.width = `${100 + Math.random() * 50}px`; windLine.style.animationDuration = `${2 + Math.random()}s`; windLine.style.animationDelay = `${Math.random()}s`; container.appendChild(windLine); } }); } // Snow animation function createSnowAnimation() { const snowContainers = document.querySelectorAll('.weather-icon'); snowContainers.forEach((container, index) => { if (index === 3) { // Only add snow to the fourth card initially container.innerHTML = '<div class="snow" id="snow-' + (index + 1) + '"></div>'; const snowContainer = container.querySelector('.snow'); snowContainer.innerHTML = '<div class="snow-ground"></div>'; for (let i = 0; i < 50; i++) { const snowflake = document.createElement('div'); snowflake.className = 'snowflake'; snowflake.innerHTML = '❄'; snowflake.style.left = `${Math.random() * 100}%`; snowflake.style.top = `${-Math.random() * 100}px`; snowflake.style.fontSize = `${8 + Math.random() * 10}px`; snowflake.style.opacity = Math.random(); snowflake.style.animationDuration = `${5 + Math.random() * 5}s`; snowflake.style.animationDelay = `${Math.random() * 5}s`; snowContainer.appendChild(snowflake); } } }); } </script> </body> </html> ``` This HTML file includes: 1. A dark-themed UI with polished weather cards 2. Four weather conditions (sun, rain, wind, snow) with distinct animations 3. CSS animations for each weather type: - Sun: Pulsing sun with rays - Rain: Falling raindrops with a cloud - Wind: Moving wind lines - Snow: Falling snowflakes with accumulation 4. JavaScript functions to: - Initialize animations when the page loads - Switch between different weather conditions when buttons are clicked - Update the weather information displayed on each card The design follows Apple's premium-quality standards with smooth animations, subtle shadows, and a clean, modern interface.
```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Animated Weather Cards</title> <style> body { background-color: #121212; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: #FFFFFF; margin: 0; padding: 40px; display: flex; justify-content: center; align-items: center; min-height: 100vh; } .container { display: flex; justify-content: space-around; flex-wrap: wrap; gap: 20px; max-width: 1400px; } .weather-card { position: relative; width: 300px; height: 400px; background-color: #1E1E1E; border-radius: 24px; overflow: hidden; box-shadow: 0 10px 20px rgba(0,0,0,0.2); padding: 20px; box-sizing: border-box; transition: transform 0.3s ease; } .weather-card:hover { transform: translateY(-5px); } .weather-card h2 { text-align: center; margin: 0 0 20px; font-size: 24px; font-weight: 600; } .animation-container { position: absolute; top: 0; left: 0; width: 100%; height: 100%; overflow: hidden; pointer-events: none; } .buttons { position: absolute; bottom: 20px; left: 20px; right: 20px; display: flex; justify-content: space-between; gap: 5px; } .buttons button { background-color: #007AFF; color: #FFFFFF; border: none; padding: 8px 12px; border-radius: 12px; font-size: 12px; cursor: pointer; transition: background-color 0.3s ease, transform 0.1s ease; flex: 1; } .buttons button:hover { background-color: #0062CC; } .buttons button:active { transform: scale(0.95); } /* Wind Animation */ @keyframes windAnim { 0% { left: -30%; } 100% { left: 110%; } } .wind-line { position: absolute; height: 2px; background: rgba(255, 255, 255, 0.5); transform: rotate(10deg); } /* Rain Animation */ @keyframes rainAnim { 0% { top: -10%; } 100% { top: 110%; } } .rain-drop { position: absolute; width: 2px; background: rgba(255, 255, 255, 0.7); } /* Sun Animation */ @keyframes shine { 0% { box-shadow: 0 0 10px yellow, 0 0 20px orange; } 100% { box-shadow: 0 0 30px yellow, 0 0 40px orange; } } @keyframes rayAnim { 0% { transform: rotate(var(--rotate)) scale(0.8); opacity: 0.5; } 100% { transform: rotate(var(--rotate)) scale(1.2); opacity: 1; } } .sun { position: absolute; top: 30%; left: 50%; transform: translate(-50%, -50%); width: 80px; height: 80px; background: radial-gradient(circle, yellow 0%, orange 100%); border-radius: 50%; animation: shine 2s ease-in-out infinite alternate; } .ray { position: absolute; top: 0; left: 50%; width: 2px; height: 100px; background: linear-gradient(to bottom, transparent, rgba(255, 255, 0, 0.6)); transform-origin: 50% 100%; animation: rayAnim 3s ease-in-out infinite alternate; } /* Snow Animation */ @keyframes fall { 0% { top: -10%; } 100% { top: 110%; } } @keyframes sway { 0% { transform: translateX(-15px); } 100% { transform: translateX(15px); } } .snowflake { position: absolute; background: white; border-radius: 50%; opacity: 0.8; } </style> </head> <body> <div class="container"> <div class="weather-card"> <h2></h2> <div class="animation-container"></div> <div class="buttons"> <button onclick="switchWeather(this.parentElement.parentElement, 'wind')">Wind</button> <button onclick="switchWeather(this.parentElement.parentElement, 'rain')">Rain</button> <button onclick="switchWeather(this.parentElement.parentElement, 'sun')">Sun</button> <button onclick="switchWeather(this.parentElement.parentElement, 'snow')">Snow</button> </div> </div> <div class="weather-card"> <h2></h2> <div class="animation-container"></div> <div class="buttons"> <button onclick="switchWeather(this.parentElement.parentElement, 'wind')">Wind</button> <button onclick="switchWeather(this.parentElement.parentElement, 'rain')">Rain</button> <button onclick="switchWeather(this.parentElement.parentElement, 'sun')">Sun</button> <button onclick="switchWeather(this.parentElement.parentElement, 'snow')">Snow</button> </div> </div> <div class="weather-card"> <h2></h2> <div class="animation-container"></div> <div class="buttons"> <button onclick="switchWeather(this.parentElement.parentElement, 'wind')">Wind</button> <button onclick="switchWeather(this.parentElement.parentElement, 'rain')">Rain</button> <button onclick="switchWeather(this.parentElement.parentElement, 'sun')">Sun</button> <button onclick="switchWeather(this.parentElement.parentElement, 'snow')">Snow</button> </div> </div> <div class="weather-card"> <h2></h2> <div class="animation-container"></div> <div class="buttons"> <button onclick="switchWeather(this.parentElement.parentElement, 'wind')">Wind</button> <button onclick="switchWeather(this.parentElement.parentElement, 'rain')">Rain</button> <button onclick="switchWeather(this.parentElement.parentElement, 'sun')">Sun</button> <button onclick="switchWeather(this.parentElement.parentElement, 'snow')">Snow</button> </div> </div> </div> <script> function switchWeather(card, condition) { card.className = `weather-card ${condition}`; const title = card.querySelector('h2'); title.textContent = condition.charAt(0).toUpperCase() + condition.slice(1); const animContainer = card.querySelector('.animation-container'); animContainer.innerHTML = ''; // Clear previous animations if (condition === 'wind') { for (let i = 0; i < 10; i++) { const line = document.createElement('div'); line.classList.add('wind-line'); const width = Math.random() * 20 + 10; const duration = Math.random() * 1 + 1.5; line.style.width = `${width}%`; line.style.top = `${Math.random() * 100}%`; line.style.left = '-30%'; line.style.animation = `windAnim ${duration}s linear infinite`; line.style.animationDelay = `-${Math.random() * duration}s`; line.style.transform = `rotate(${Math.random() * 20 - 10}deg)`; animContainer.appendChild(line); } } else if (condition === 'rain') { for (let i = 0; i < 30; i++) { const drop = document.createElement('div'); drop.classList.add('rain-drop'); const height = Math.random() * 20 + 10; const duration = Math.random() * 0.5 + 0.5; drop.style.height = `${height}px`; drop.style.left = `${Math.random() * 100}%`; drop.style.top = '-10%'; drop.style.animation = `rainAnim ${duration}s linear infinite`; drop.style.animationDelay = `-${Math.random() * 1}s`; animContainer.appendChild(drop); } } else if (condition === 'sun') { const sun = document.createElement('div'); sun.classList.add('sun'); animContainer.appendChild(sun); for (let i = 0; i < 8; i++) { const ray = document.createElement('div'); ray.classList.add('ray'); const rotate = i * 45; ray.style.setProperty('--rotate', `${rotate}deg`); ray.style.transform = `rotate(${rotate}deg)`; ray.style.animationDelay = `-${Math.random() * 3}s`; sun.appendChild(ray); } } else if (condition === 'snow') { for (let i = 0; i < 50; i++) { const flake = document.createElement('div'); flake.classList.add('snowflake'); const size = Math.random() * 5 + 3; const duration = Math.random() * 5 + 5; flake.style.width = `${size}px`; flake.style.height = `${size}px`; flake.style.left = `${Math.random() * 100}%`; flake.style.top = '-10%'; flake.style.opacity = Math.random() * 0.5 + 0.5; flake.style.animation = `fall ${duration}s linear infinite, sway ${duration / 2}s ease-in-out infinite alternate`; flake.style.animationDelay = `-${Math.random() * duration}s, -${Math.random() * (duration / 2)}s`; animContainer.appendChild(flake); } } } window.onload = function() { const cards = document.querySelectorAll('.weather-card'); const conditions = ['wind', 'rain', 'sun', 'snow']; cards.forEach((card, index) => { switchWeather(card, conditions[index]); }); }; </script> </body> </html> ```
Here's a complete HTML file with CSS and JavaScript for an animated weather card component that showcases four weather conditions with premium animations and a dark theme: ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Premium Weather Cards</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; } body { background-color: #121212; display: flex; justify-content: center; align-items: center; min-height: 100vh; padding: 20px; color: white; } .container { display: flex; gap: 24px; flex-wrap: wrap; justify-content: center; max-width: 1200px; } .weather-card { width: 260px; height: 360px; background: linear-gradient(135deg, #2c3e50, #1a1a2e); border-radius: 24px; padding: 24px; position: relative; overflow: hidden; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); transition: all 0.3s ease; } .weather-card:hover { transform: translateY(-8px); box-shadow: 0 15px 35px rgba(0, 0, 0, 0.4); } .weather-title { font-size: 24px; font-weight: 600; margin-bottom: 16px; z-index: 2; position: relative; } .weather-icon { font-size: 60px; margin-bottom: 20px; z-index: 2; position: relative; } .description { font-size: 16px; opacity: 0.8; margin-bottom: 20px; z-index: 2; position: relative; } /* Sunny Animation */ .sun { position: absolute; width: 80px; height: 80px; background: #ffde59; border-radius: 50%; top: 50px; right: 40px; box-shadow: 0 0 40px #ffde59; z-index: 1; } .sun-ray { position: absolute; width: 120px; height: 4px; background: rgba(255, 222, 89, 0.5); top: 50%; left: 50%; transform-origin: left center; border-radius: 4px; } /* Rain Animation */ .raindrop { position: absolute; width: 2px; height: 10px; background: rgba(174, 194, 224, 0.7); border-radius: 0 0 2px 2px; animation: falling linear infinite; } .puddle { position: absolute; bottom: 20px; width: 30px; height: 5px; background: rgba(174, 194, 224, 0.3); border-radius: 50%; opacity: 0; animation: puddle 3s linear infinite; } /* Wind Animation */ .cloud { position: absolute; background: rgba(255, 255, 255, 0.8); border-radius: 50px; animation: wind linear infinite; } .wind-line { position: absolute; height: 2px; background: rgba(255, 255, 255, 0.5); animation: wind linear infinite; } /* Snow Animation */ .snowflake { position: absolute; color: white; font-size: 10px; animation: snow linear infinite; opacity: 0.9; } /* Animations */ @keyframes falling { 0% { transform: translateY(-10px); opacity: 0; } 10% { opacity: 1; } 90% { opacity: 1; } 100% { transform: translateY(280px); opacity: 0; } } @keyframes puddle { 0% { transform: scale(0.2); opacity: 0; } 50% { opacity: 0.5; } 100% { transform: scale(1); opacity: 0; } } @keyframes wind { 0% { transform: translateX(-50px); opacity: 0; } 20% { opacity: 0.8; } 100% { transform: translateX(300px); opacity: 0; } } @keyframes snow { 0% { transform: translateY(-10px) rotate(0deg); opacity: 0; } 10% { opacity: 1; } 90% { opacity: 1; } 100% { transform: translateY(280px) rotate(360deg); opacity: 0; } } @keyframes shine { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* Control buttons */ .controls { position: fixed; bottom: 30px; display: flex; gap: 15px; } .weather-btn { background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.2); color: white; padding: 12px 24px; border-radius: 30px; font-size: 16px; cursor: pointer; transition: all 0.3s ease; backdrop-filter: blur(10px); } .weather-btn:hover { background: rgba(255, 255, 255, 0.2); transform: translateY(-2px); } .weather-btn.active { background: rgba(255, 255, 255, 0.3); font-weight: 600; } </style> </head> <body> <div class="container"> <!-- Sunny Card --> <div class="weather-card" id="sunny-card"> <div class="weather-title">Sunny Day</div> <div class="weather-icon">☀️</div> <div class="description">Bright and clear skies with warm sunshine</div> <div class="sun"></div> <div id="sun-rays"></div> </div> <!-- Rainy Card --> <div class="weather-card" id="rainy-card"> <div class="weather-title">Rainy Day</div> <div class="weather-icon">🌧️</div> <div class="description">Steady rainfall throughout the day</div> <div id="raindrops"></div> <div id="puddles"></div> </div> <!-- Windy Card --> <div class="weather-card" id="windy-card"> <div class="weather-title">Windy Day</div> <div class="weather-icon">🌬️</div> <div class="description">Strong winds with scattered clouds</div> <div id="clouds"></div> <div id="wind-lines"></div> </div> <!-- Snowy Card --> <div class="weather-card" id="snowy-card"> <div class="weather-title">Snowy Day</div> <div class="weather-icon">❄️</div> <div class="description">Gentle snowfall accumulating on surfaces</div> <div id="snowflakes"></div> </div> </div> <div class="controls"> <button class="weather-btn active" onclick="animateWeather('all')">All</button> <button class="weather-btn" onclick="animateWeather('sunny')">Sunny</button> <button class="weather-btn" onclick="animateWeather('rainy')">Rainy</button> <button class="weather-btn" onclick="animateWeather('windy')">Windy</button> <button class="weather-btn" onclick="animateWeather('snowy')">Snowy</button> </div> <script> // Initialize all weather animations function initWeatherAnimations() { createSunRays(); createRaindrops(); createPuddles(); createClouds(); createWindLines(); createSnowflakes(); } // Create sun rays for sunny card function createSunRays() { const container = document.getElementById('sun-rays'); for (let i = 0; i < 12; i++) { const ray = document.createElement('div'); ray.className = 'sun-ray'; ray.style.transform = `rotate(${i * 30}deg)`; container.appendChild(ray); } } // Create raindrops for rainy card function createRaindrops() { const container = document.getElementById('raindrops'); for (let i = 0; i < 30; i++) { const drop = document.createElement('div'); drop.className = 'raindrop'; drop.style.left = `${Math.random() * 240}px`; drop.style.animationDuration = `${0.5 + Math.random() * 1.5}s`; drop.style.animationDelay = `${Math.random() * 2}s`; container.appendChild(drop); } } // Create puddles for rainy card function createPuddles() { const container = document.getElementById('puddles'); for (let i = 0; i < 6; i++) { const puddle = document.createElement('div'); puddle.className = 'puddle'; puddle.style.left = `${30 + Math.random() * 180}px`; puddle.style.animationDelay = `${Math.random() * 3}s`; container.appendChild(puddle); } } // Create clouds for windy card function createClouds() { const container = document.getElementById('clouds'); for (let i = 0; i < 5; i++) { const cloud = document.createElement('div'); cloud.className = 'cloud'; cloud.style.width = `${30 + Math.random() * 50}px`; cloud.style.height = `${20 + Math.random() * 30}px`; cloud.style.top = `${50 + Math.random() * 180}px`; cloud.style.animationDuration = `${15 + Math.random() * 15}s`; cloud.style.animationDelay = `${Math.random() * 10}s`; container.appendChild(cloud); } } // Create wind lines for windy card function createWindLines() { const container = document.getElementById('wind-lines'); for (let i = 0; i < 10; i++) { const line = document.createElement('div'); line.className = 'wind-line'; line.style.width = `${10 + Math.random() * 30}px`; line.style.top = `${70 + Math.random() * 200}px`; line.style.animationDuration = `${5 + Math.random() * 10}s`; line.style.animationDelay = `${Math.random() * 5}s`; container.appendChild(line); } } // Create snowflakes for snowy card function createSnowflakes() { const container = document.getElementById('snowflakes'); for (let i = 0; i < 25; i++) { const flake = document.createElement('div'); flake.className = 'snowflake'; flake.innerHTML = '❄'; flake.style.left = `${Math.random() * 240}px`; flake.style.animationDuration = `${3 + Math.random() * 7}s`; flake.style.animationDelay = `${Math.random() * 5}s`; container.appendChild(flake); } } // Toggle weather animations function animateWeather(type) { const cards = document.querySelectorAll('.weather-card'); const buttons = document.querySelectorAll('.weather-btn'); buttons.forEach(btn => { btn.classList.remove('active'); if ((type === 'all' && btn.textContent === 'All') || (type === 'sunny' && btn.textContent === 'Sunny') || (type === 'rainy' && btn.textContent === 'Rainy') || (type === 'windy' && btn.textContent === 'Windy') || (type === 'snowy' && btn.textContent === 'Snowy')) { btn.classList.add('active'); } }); cards.forEach(card => { card.style.opacity = '0.3'; card.style.transform = 'scale(0.95)'; }); if (type === 'all') { cards.forEach(card => { card.style.opacity = '1'; card.style.transform = 'scale(1)'; }); } else { const activeCard = document.getElementById(`${type}-card`); if (activeCard) { activeCard.style.opacity = '1'; activeCard.style.transform = 'scale(1)'; } } } // Initialize on load window.onload = function() { initWeatherAnimations(); }; </script> </body> </html> ``` This code creates: 1. Four premium weather cards (Sunny, Rainy, Windy, Snowy) with: - Distinct animations for each weather condition - High-quality visual representation - Smooth animations with randomized timing for natural effects 2. Responsive design with: - Dark theme background - Card hover effects - Proper spacing and alignment 3. Interactive controls to: - Show all cards - Highlight individual weather types - Smooth transitions between states 4. Premium visual elements: - Sun with animated rays - Falling raindrops with puddle formation - Moving clouds and wind lines - Animated snowflakes with rotation The design follows Apple's premium standards with subtle animations, careful attention to detail, and a polished interface.
Here’s a single self-contained HTML file. It displays four weather cards side by side on a dark background and includes a polished control bar to switch all cards to any one weather. You can also click any card to cycle it through Wind → Rain → Sun → Snow. ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Animated Weather Cards</title> <style> /* Reset & body */ * { box-sizing: border-box; margin: 0; padding: 0; } body { background: #1e272e; color: #fff; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; display: flex; flex-direction: column; align-items: center; padding: 20px; } /* Controls */ .controls { margin-bottom: 20px; } .controls button { background: #34495e; border: none; color: #ecf0f1; padding: 10px 18px; margin: 0 6px; border-radius: 6px; font-size: 14px; cursor: pointer; transition: background 0.3s, transform 0.1s; } .controls button:hover { background: #3d5a73; } .controls button:active { transform: scale(0.96); } /* Card layout */ .cards { display: flex; gap: 20px; flex-wrap: wrap; justify-content: center; } .weather-card { position: relative; width: 180px; height: 240px; background: #2c3e50; border-radius: 16px; overflow: hidden; box-shadow: 0 6px 20px rgba(0,0,0,0.5); cursor: pointer; } /* Common animations */ @keyframes moveCloud { 0% { transform: translateX(-150px); } 100% { transform: translateX(350px); } } @keyframes swayLine { 0%,100% { transform: translateX(0); } 50% { transform: translateX(8px); } } @keyframes fallRain { 0% { transform: translateY(-20px); opacity: 1; } 100% { transform: translateY(260px); opacity: 0; } } @keyframes ripple { 0% { transform: scale(0.2); opacity: 0.7; } 100% { transform: scale(1); opacity: 0; } } @keyframes rotateRays { 0% { transform: rotate(0); } 100% { transform: rotate(360deg); } } @keyframes pulseRay { 0%,100% { opacity: 0.7; } 50% { opacity: 1; } } @keyframes fallSnow { 0% { transform: translateY(-10px); opacity: 0.9; } 100% { transform: translateY(260px); opacity: 0.3; } } @keyframes accumulate { 0% { height: 0; } 100% { height: 16px; } } /* Wind */ .cloud { position: absolute; background: #ecf0f1; width: 60px; height: 30px; border-radius: 50%; box-shadow: 30px 10px 0 0 #ecf0f1, -20px 15px 0 0 #ecf0f1; opacity: 0.85; animation-name: moveCloud; animation-timing-function: linear; animation-iteration-count: infinite; } .wind-line { position: absolute; width: 30px; height: 2px; background: rgba(236, 240, 241,0.7); border-radius: 1px; animation-name: swayLine; animation-duration: 1s; animation-iteration-count: infinite; animation-timing-function: ease-in-out; } /* Rain */ .drop { position: absolute; width: 2px; height: 12px; background: #74b9ff; border-radius: 1px; opacity: 0.8; animation-name: fallRain; animation-timing-function: linear; animation-iteration-count: infinite; } .puddle { position: absolute; bottom: 4px; width: 20px; height: 4px; background: rgba(116, 185, 255,0.6); border-radius: 50%; opacity: 0.6; animation-name: ripple; animation-duration: 1s; animation-iteration-count: infinite; animation-timing-function: ease-out; } /* Sun */ .sun { position: absolute; top: 40px; left: 50%; width: 80px; height: 80px; margin-left: -40px; background: radial-gradient(circle at center, #fff59d, #f9a825); border-radius: 50%; box-shadow: 0 0 20px rgba(249, 168, 37,0.5); } .rays { position: absolute; top: 0; left: 0; width:100%; height:100%; animation: rotateRays 8s linear infinite; } .ray { position: absolute; width: 4px; height: 20px; background: #ffe082; top: -10px; left: 50%; margin-left: -2px; border-radius: 2px; transform-origin: bottom center; animation-name: pulseRay; animation-duration: 1.5s; animation-iteration-count: infinite; animation-timing-function: ease-in-out; } /* Snow */ .snowflake { position: absolute; width: 6px; height: 6px; background: #ecf0f1; border-radius: 50%; opacity: 0.9; animation-name: fallSnow; animation-timing-function: linear; animation-iteration-count: infinite; } .snow-surface { position: absolute; bottom: 0; left: 0; width: 100%; background: #ecf0f1; animation: accumulate 10s forwards; } </style> </head> <body> <div class="controls"> <button data-weather="wind">Wind</button> <button data-weather="rain">Rain</button> <button data-weather="sun">Sun</button> <button data-weather="snow">Snow</button> </div> <div class="cards"> <div class="weather-card" data-weather="wind"></div> <div class="weather-card" data-weather="rain"></div> <div class="weather-card" data-weather="sun"></div> <div class="weather-card" data-weather="snow"></div> </div> <script> const types = ['wind','rain','sun','snow']; // Initialize all cards document.querySelectorAll('.weather-card').forEach(card => { render(card, card.dataset.weather); card.addEventListener('click', () => { // cycle to next weather on click let i = types.indexOf(card.dataset.weather); let next = types[(i+1)%types.length]; switchWeather(card, next); }); }); // Controls to switch all document.querySelectorAll('.controls button').forEach(btn => { btn.addEventListener('click', () => { const w = btn.dataset.weather; document.querySelectorAll('.weather-card').forEach(c => switchWeather(c, w)); }); }); function switchWeather(card, weather) { card.dataset.weather = weather; render(card, weather); } function render(card, w) { card.innerHTML = ''; if (w==='wind') createWind(card); if (w==='rain') createRain(card); if (w==='sun') createSun(card); if (w==='snow') createSnow(card); } function createWind(c) { // clouds for (let i=0;i<2;i++){ const cloud = document.createElement('div'); cloud.className = 'cloud'; cloud.style.top = `${30 + i*40}px`; cloud.style.animationDuration = `${12 + i*4}s`; cloud.style.left = `${-150 - i*100}px`; c.appendChild(cloud); } // wind lines for (let i=0;i<4;i++){ const ln = document.createElement('div'); ln.className = 'wind-line'; ln.style.bottom = `${50 + i*25}px`; ln.style.left = `${20 + i*35}px`; ln.style.animationDirection = i%2? 'alternate':'alternate-reverse'; c.appendChild(ln); } } function createRain(c) { // drops for (let i=0;i<30;i++){ const drop = document.createElement('div'); drop.className = 'drop'; drop.style.left = Math.random()*160 + 'px'; drop.style.animationDuration = 0.8 + Math.random()*0.7 + 's'; drop.style.animationDelay = Math.random()*1+'s'; c.appendChild(drop); } // puddles for (let i=0;i<6;i++){ const pud = document.createElement('div'); pud.className = 'puddle'; pud.style.left = 10 + i*25 + 'px'; pud.style.animationDelay = 0.3 + Math.random()*0.7 + 's'; c.appendChild(pud); } } function createSun(c) { const sun = document.createElement('div'); sun.className = 'sun'; c.appendChild(sun); const rays = document.createElement('div'); rays.className = 'rays'; sun.appendChild(rays); for (let i=0;i<8;i++){ const ray = document.createElement('div'); ray.className = 'ray'; ray.style.transform = `rotate(${i*45}deg) translateY(-10px)`; ray.style.animationDelay = (i*0.15)+'s'; rays.appendChild(ray); } } function createSnow(c) { // flakes for (let i=0;i<25;i++){ const flake = document.createElement('div'); flake.className = 'snowflake'; flake.style.left = Math.random()*170 + 'px'; flake.style.animationDuration = 4 + Math.random()*3 + 's'; flake.style.animationDelay = Math.random()*3 + 's'; c.appendChild(flake); } // accumulation const surface = document.createElement('div'); surface.className = 'snow-surface'; c.appendChild(surface); } </script> </body> </html> ```
```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Weather Cards</title> <style> body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; background-color: #121212; margin: 0; padding: 20px; display: flex; flex-direction: column; align-items: center; } .weather-cards { display: flex; gap: 20px; justify-content: center; } .weather-card { position: relative; width: 250px; height: 350px; background-color: #1a1a1a; border-radius: 20px; overflow: hidden; box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); } .weather-card .condition { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; font-size: 24px; color: #fff; } .weather-card.wind .cloud { position: absolute; top: 50px; left: 50px; width: 50px; height: 20px; background-color: #fff; border-radius: 20px; animation: wind-cloud 5s linear infinite; } .weather-card.wind .cloud::before { content: ""; position: absolute; top: -10px; left: 10px; width: 20px; height: 20px; background-color: #fff; border-radius: 50%; } @keyframes wind-cloud { 0% { transform: translateX(0); } 100% { transform: translateX(200px); } } .weather-card.rain .raindrop { position: absolute; top: 0; left: 50%; width: 5px; height: 10px; background-color: #fff; border-radius: 50%; animation: rain-drop 2s linear infinite; } .weather-card.rain .raindrop:nth-child(1) { left: 40%; animation-delay: 0.5s; } .weather-card.rain .raindrop:nth-child(2) { left: 60%; animation-delay: 1s; } @keyframes rain-drop { 0% { transform: translateY(0); } 100% { transform: translateY(350px); } } .weather-card.sun .sun-ray { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 100px; height: 100px; border-radius: 50%; background-color: #fff; box-shadow: 0 0 10px rgba(255, 255, 255, 0.5); animation: sun-ray 5s linear infinite; } @keyframes sun-ray { 0% { transform: translate(-50%, -50%) rotate(0); } 100% { transform: translate(-50%, -50%) rotate(360deg); } } .weather-card.snow .snowflake { position: absolute; top: 0; left: 50%; width: 10px; height: 10px; background-color: #fff; border-radius: 50%; animation: snow-flake 3s linear infinite; } .weather-card.snow .snowflake:nth-child(1) { left: 40%; animation-delay: 0.5s; } .weather-card.snow .snowflake:nth-child(2) { left: 60%; animation-delay: 1s; } @keyframes snow-flake { 0% { transform: translateY(0); } 100% { transform: translateY(350px); } } .buttons { margin-top: 20px; display: flex; gap: 10px; } button { background-color: #1a1a1a; color: #fff; border: none; padding: 10px 20px; border-radius: 10px; cursor: pointer; } button:hover { background-color: #2a2a2a; } button.active { background-color: #3a3a3a; } </style> </head> <body> <div class="weather-cards"> <div class="weather-card wind"> <div class="condition">Wind</div> <div class="cloud"></div> </div> <div class="weather-card rain"> <div class="condition">Rain</div> <div class="raindrop"></div> <div class="raindrop"></div> </div> <div class="weather-card sun"> <div class="condition">Sun</div> <div class="sun-ray"></div> </div> <div class="weather-card snow"> <div class="condition">Snow</div> <div class="snowflake"></div> <div class="snowflake"></div> </div> </div> <script> // No JavaScript needed for this example as the animations are CSS-based </script> </body> </html> ``` In this code: * We create a container `div` with the class `weather-cards` to hold four weather cards. * Each weather card is a `div` with a specific class (e.g., `wind`, `rain`, `sun`, `snow`) and contains a `div` with the class `condition` to display the weather condition. * We use CSS to style the weather cards, add animations, and create the visual effects for each weather condition. * We don't need any JavaScript code as the animations are CSS-based and run automatically. You can save this code as an HTML file and open it in a web browser to see the animated weather cards. **Example Use Cases:** * You can modify the CSS animations to create different visual effects for each weather condition. * You can add more weather cards or conditions by duplicating the existing HTML structure and updating the CSS accordingly. * You can use this code as a starting point to create a more complex weather application with dynamic data and user interactions.
```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Weather Cards</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { background: linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 100%); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; padding: 40px 20px; min-height: 100vh; overflow-x: auto; } .container { display: flex; gap: 30px; justify-content: center; align-items: center; flex-wrap: wrap; max-width: 1400px; margin: 0 auto; } .weather-card { width: 280px; height: 380px; border-radius: 24px; position: relative; overflow: hidden; backdrop-filter: blur(20px); border: 1px solid rgba(255, 255, 255, 0.1); box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3); transition: transform 0.3s ease, box-shadow 0.3s ease; cursor: pointer; } .weather-card:hover { transform: translateY(-10px); box-shadow: 0 30px 60px rgba(0, 0, 0, 0.4); } .card-content { position: absolute; bottom: 0; left: 0; right: 0; padding: 30px; background: linear-gradient(transparent, rgba(0, 0, 0, 0.6)); z-index: 10; } .temperature { font-size: 48px; font-weight: 300; color: white; margin-bottom: 5px; } .weather-type { font-size: 18px; color: rgba(255, 255, 255, 0.8); font-weight: 500; margin-bottom: 8px; } .location { font-size: 14px; color: rgba(255, 255, 255, 0.6); } /* Wind Card */ .wind-card { background: linear-gradient(135deg, #4a90a4 0%, #2d5a87 100%); } .wind-lines { position: absolute; width: 100%; height: 100%; opacity: 0.6; } .wind-line { position: absolute; height: 2px; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.7), transparent); animation: windMove 3s ease-in-out infinite; } .wind-line:nth-child(1) { top: 20%; width: 80px; animation-delay: 0s; } .wind-line:nth-child(2) { top: 35%; width: 60px; animation-delay: 0.5s; } .wind-line:nth-child(3) { top: 50%; width: 100px; animation-delay: 1s; } .wind-line:nth-child(4) { top: 65%; width: 70px; animation-delay: 1.5s; } @keyframes windMove { 0% { transform: translateX(-100px); opacity: 0; } 50% { opacity: 0.7; } 100% { transform: translateX(350px); opacity: 0; } } .clouds { position: absolute; width: 100%; height: 100%; } .cloud { position: absolute; background: rgba(255, 255, 255, 0.2); border-radius: 50px; animation: cloudFloat 8s ease-in-out infinite; } .cloud:before, .cloud:after { content: ''; position: absolute; background: rgba(255, 255, 255, 0.2); border-radius: 50px; } .cloud1 { width: 60px; height: 30px; top: 10%; left: -60px; animation-delay: 0s; } .cloud1:before { width: 50px; height: 25px; top: -15px; left: 10px; } .cloud1:after { width: 40px; height: 20px; top: -10px; right: 10px; } .cloud2 { width: 80px; height: 40px; top: 25%; left: -80px; animation-delay: 2s; } .cloud2:before { width: 60px; height: 35px; top: -20px; left: 15px; } .cloud2:after { width: 50px; height: 25px; top: -15px; right: 15px; } @keyframes cloudFloat { 0% { transform: translateX(0); } 100% { transform: translateX(400px); } } /* Rain Card */ .rain-card { background: linear-gradient(135deg, #4a6741 0%, #2d3561 100%); } .rain { position: absolute; width: 100%; height: 100%; } .raindrop { position: absolute; width: 2px; height: 20px; background: linear-gradient(rgba(173, 216, 230, 0.8), rgba(173, 216, 230, 0.3)); border-radius: 0 0 50% 50%; animation: rainFall 1s linear infinite; } @keyframes rainFall { 0% { transform: translateY(-20px); opacity: 0; } 10% { opacity: 1; } 100% { transform: translateY(400px); opacity: 0; } } .puddle { position: absolute; bottom: 0; width: 100%; height: 20px; background: rgba(173, 216, 230, 0.3); border-radius: 50% 50% 0 0; animation: puddleGrow 4s ease-in-out infinite alternate; } @keyframes puddleGrow { 0% { height: 10px; opacity: 0.2; } 100% { height: 25px; opacity: 0.4; } } /* Sun Card */ .sun-card { background: linear-gradient(135deg, #ffd89b 0%, #19547b 100%); } .sun { position: absolute; width: 120px; height: 120px; background: radial-gradient(circle, #ffd700 0%, #ffed4e 70%); border-radius: 50%; top: 20%; left: 50%; transform: translateX(-50%); box-shadow: 0 0 40px rgba(255, 215, 0, 0.6); animation: sunPulse 3s ease-in-out infinite alternate; } @keyframes sunPulse { 0% { box-shadow: 0 0 40px rgba(255, 215, 0, 0.6); } 100% { box-shadow: 0 0 60px rgba(255, 215, 0, 0.8); } } .sun-rays { position: absolute; width: 100%; height: 100%; animation: sunRotate 20s linear infinite; } .ray { position: absolute; width: 4px; height: 30px; background: linear-gradient(rgba(255, 215, 0, 0.8), transparent); border-radius: 2px; transform-origin: 2px 60px; } .ray:nth-child(1) { transform: rotate(0deg); } .ray:nth-child(2) { transform: rotate(45deg); } .ray:nth-child(3) { transform: rotate(90deg); } .ray:nth-child(4) { transform: rotate(135deg); } .ray:nth-child(5) { transform: rotate(180deg); } .ray:nth-child(6) { transform: rotate(225deg); } .ray:nth-child(7) { transform: rotate(270deg); } .ray:nth-child(8) { transform: rotate(315deg); } @keyframes sunRotate { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* Snow Card */ .snow-card { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); } .snow { position: absolute; width: 100%; height: 100%; } .snowflake { position: absolute; color: rgba(255, 255, 255, 0.8); font-size: 14px; animation: snowFall 8s linear infinite; user-select: none; } @keyframes snowFall { 0% { transform: translateY(-20px) translateX(0px); opacity: 0; } 10% { opacity: 1; } 100% { transform: translateY(400px) translateX(50px); opacity: 0; } } .snow-ground { position: absolute; bottom: 0; width: 100%; height: 30px; background: linear-gradient(rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0.2)); border-radius: 50% 50% 0 0; animation: snowAccumulate 6s ease-in-out infinite alternate; } @keyframes snowAccumulate { 0% { height: 20px; } 100% { height: 40px; } } .title { text-align: center; color: white; font-size: 36px; font-weight: 300; margin-bottom: 40px; opacity: 0.9; } @media (max-width: 768px) { .container { flex-direction: column; align-items: center; } .weather-card { width: 260px; height: 350px; } } </style> </head> <body> <div class="title">Weather Forecast</div> <div class="container"> <!-- Wind Card --> <div class="weather-card wind-card"> <div class="wind-lines"> <div class="wind-line"></div> <div class="wind-line"></div> <div class="wind-line"></div> <div class="wind-line"></div> </div> <div class="clouds"> <div class="cloud cloud1"></div> <div class="cloud cloud2"></div> </div> <div class="card-content"> <div class="temperature">18°</div> <div class="weather-type">Windy</div> <div class="location">San Francisco</div> </div> </div> <!-- Rain Card --> <div class="weather-card rain-card"> <div class="rain" id="rain"></div> <div class="puddle"></div> <div class="card-content"> <div class="temperature">12°</div> <div class="weather-type">Rainy</div> <div class="location">London</div> </div> </div> <!-- Sun Card --> <div class="weather-card sun-card"> <div class="sun"></div> <div class="sun-rays"> <div class="ray"></div> <div class="ray"></div> <div class="ray"></div> <div class="ray"></div> <div class="ray"></div> <div class="ray"></div> <div class="ray"></div> <div class="ray"></div> </div> <div class="card-content"> <div class="temperature">28°</div> <div class="weather-type">Sunny</div> <div class="location">Los Angeles</div> </div> </div> <!-- Snow Card --> <div class="weather-card snow-card"> <div class="snow" id="snow"></div> <div class="snow-ground"></div> <div class="card-content"> <div class="temperature">-3°</div> <div class="weather-type">Snowy</div> <div class="location">New York</div> </div> </div> </div> <script> // Create raindrops function createRaindrops() { const rainContainer = document.getElementById('rain'); const dropCount = 50; for (let i = 0; i < dropCount; i++) { const raindrop = document.createElement('div'); raindrop.className = 'raindrop'; raindrop.style.left = Math.random() * 100 + '%'; raindrop.style.animationDelay = Math.random() * 2 + 's'; raindrop.style.animationDuration = (Math.random() * 0.5 + 0.5) + 's'; rainContainer.appendChild(raindrop); } } // Create snowflakes function createSnowflakes() { const snowContainer = document.getElementById('snow'); const flakeCount = 30; const snowflakeSymbols = ['❄', '❅', '❆']; for (let i = 0; i < flakeCount; i++) { const snowflake = document.createElement('div'); snowflake.className = 'snowflake'; snowflake.innerHTML = snowflakeSymbols[Math.floor(Math.random() * snowflakeSymbols.length)]; snowflake.style.left = Math.random() * 100 + '%'; snowflake.style.animationDelay = Math.random() * 8 + 's'; snowflake.style.animationDuration = (Math.random() * 3 + 5) + 's'; snowflake.style.fontSize = (Math.random() * 10 + 10) + 'px'; snowContainer.appendChild(snowflake); } } // Initialize weather effects document.addEventListener('DOMContentLoaded', function() { createRaindrops(); createSnowflakes(); }); // Add hover effects for enhanced interactivity const weatherCards = document.querySelectorAll('.weather-card'); weatherCards.forEach(card => { card.addEventListener('mouseenter', function() { this.style.transform = 'translateY(-15px) scale(1.02)'; }); card.addEventListener('mouseleave', function() { this.style.transform = 'translateY(0) scale(1)'; }); }); </script> </body> </html> ```
```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Animated Weather Cards</title> <style> :root { --card-width: 240px; --card-height: 320px; --card-radius: 18px; --card-dark: #1a1a1a; --card-dark-lighter: #2a2a2a; --text-light: #ffffff; --text-secondary: rgba(255, 255, 255, 0.7); --blue-light: #64b5f6; --blue-dark: #1976d2; --yellow-light: #ffeb3b; --yellow-dark: #ffc107; --grey-light: #e0e0e0; --grey-dark: #9e9e9e; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } body { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; background: #0f0f14; padding: 40px 20px; overflow-x: hidden; } .weather-container { display: flex; flex-wrap: wrap; justify-content: center; gap: 30px; max-width: 1200px; margin-bottom: 30px; } .weather-card { position: relative; width: var(--card-width); height: var(--card-height); background: var(--card-dark); border-radius: var(--card-radius); overflow: hidden; box-shadow: 0 15px 35px rgba(0, 0, 0, 0.5); transition: transform 0.3s ease, box-shadow 0.3s ease; } .weather-card:hover { transform: translateY(-10px); box-shadow: 0 20px 40px rgba(0, 0, 0, 0.6); } .card-content { position: relative; z-index: 2; height: 100%; padding: 25px; display: flex; flex-direction: column; justify-content: space-between; } .weather-header { display: flex; justify-content: space-between; align-items: flex-start; } .weather-type { font-size: 24px; font-weight: 700; color: var(--text-light); margin-bottom: 6px; } .temperature { font-size: 54px; font-weight: 300; color: var(--text-light); margin-top: 10px; line-height: 1; } .location { font-size: 16px; color: var(--text-secondary); margin-top: 5px; } .weather-icon { width: 60px; height: 60px; display: flex; align-items: center; justify-content: center; border-radius: 50%; background: var(--card-dark-lighter); color: var(--text-light); } .weather-icon svg { width: 35px; height: 35px; } .weather-details { display: flex; margin-top: auto; gap: 15px; } .detail { flex: 1; display: flex; flex-direction: column; align-items: center; padding: 12px 0; border-radius: 12px; background: rgba(255, 255, 255, 0.07); } .detail-value { font-size: 16px; font-weight: 600; color: var(--text-light); margin-bottom: 4px; } .detail-label { font-size: 12px; color: var(--text-secondary); } /* WIND ANIMATION */ .wind-bg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 1; opacity: 0.6; background: linear-gradient(180deg, var(--card-dark) 0%, var(--card-dark-lighter) 100%); } .cloud { position: absolute; background: rgba(255, 255, 255, 0.7); border-radius: 50%; z-index: 1; opacity: 0.4; } .wind-line { position: absolute; height: 2px; background: rgba(255, 255, 255, 0.3); z-index: 1; transform-origin: left center; } /* RAIN ANIMATION */ .rain-bg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 1; background: linear-gradient(180deg, var(--blue-dark) 0%, var(--card-dark) 100%); opacity: 0.3; } .raindrop { position: absolute; width: 2px; background: var(--blue-light); z-index: 1; opacity: 0.7; border-radius: 50%; } .puddle { position: absolute; bottom: 0; background: radial-gradient(circle, rgba(100, 181, 246, 0.5) 0%, rgba(100, 181, 246, 0) 70%); border-radius: 50%; z-index: 1; } /* SUN ANIMATION */ .sun-bg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 1; background: linear-gradient(180deg, var(--yellow-light) 0%, var(--yellow-dark) 50%, var(--card-dark) 100%); opacity: 0.2; } .sun { position: absolute; width: 100px; height: 100px; top: 50px; left: 50%; transform: translateX(-50%); background: radial-gradient(circle, rgba(255, 235, 59, 0.8) 0%, rgba(255, 193, 7, 0) 70%); border-radius: 50%; z-index: 1; animation: sun-pulse 4s infinite alternate; } .sunray { position: absolute; background: linear-gradient(to right, rgba(255, 235, 59, 0.5), rgba(255, 235, 59, 0)); z-index: 1; transform-origin: left center; } @keyframes sun-pulse { 0% { box-shadow: 0 0 30px 10px rgba(255, 235, 59, 0.4); } 100% { box-shadow: 0 0 60px 20px rgba(255, 235, 59, 0.6); } } /* SNOW ANIMATION */ .snow-bg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 1; background: linear-gradient(180deg, var(--card-dark) 0%, var(--grey-dark) 100%); opacity: 0.2; } .snowflake { position: absolute; background: white; border-radius: 50%; z-index: 1; opacity: 0.8; } .snow-ground { position: absolute; bottom: 0; left: 0; width: 100%; height: 40px; background: linear-gradient(180deg, rgba(224, 224, 224, 0) 0%, rgba(224, 224, 224, 0.3) 100%); z-index: 1; } .controls { display: flex; gap: 15px; margin-top: 30px; } .control-btn { background: var(--card-dark-lighter); color: var(--text-light); border: none; border-radius: 12px; padding: 12px 20px; font-size: 14px; font-weight: 600; cursor: pointer; transition: all 0.3s ease; } .control-btn:hover { background: var(--card-dark); transform: translateY(-3px); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); } .active { background: linear-gradient(135deg, #3b82f6, #1d4ed8); box-shadow: 0 4px 12px rgba(59, 130, 246, 0.5); } .active:hover { background: linear-gradient(135deg, #3b82f6, #1d4ed8); } @media (max-width: 768px) { .weather-container { gap: 20px; } .weather-card { width: calc(var(--card-width) * 0.9); height: calc(var(--card-height) * 0.9); } .card-content { padding: 20px; } .temperature { font-size: 42px; } } </style> </head> <body> <div class="weather-container"> <div class="weather-card" id="windCard"> <div class="wind-bg"></div> <div class="card-content"> <div class="weather-header"> <div> <div class="weather-type">Windy</div> <div class="temperature">18°</div> <div class="location">Chicago, IL</div> </div> <div class="weather-icon"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 10h.01M15 15h.01M19 15h.01M19 10h.01M3 10h7m-7 5h7m-7 5h7M8 5a1 1 0 011-1h2a1 1 0 011 1v.01a1 1 0 01-1 1H9a1 1 0 01-1-1V5z"></path> </svg> </div> </div> <div class="weather-details"> <div class="detail"> <div class="detail-value">35 mph</div> <div class="detail-label">Wind</div> </div> <div class="detail"> <div class="detail-value">45%</div> <div class="detail-label">Humidity</div> </div> </div> </div> </div> <div class="weather-card" id="rainCard"> <div class="rain-bg"></div> <div class="card-content"> <div class="weather-header"> <div> <div class="weather-type">Rainy</div> <div class="temperature">12°</div> <div class="location">Seattle, WA</div> </div> <div class="weather-icon"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path> </svg> </div> </div> <div class="weather-details"> <div class="detail"> <div class="detail-value">5 mph</div> <div class="detail-label">Wind</div> </div> <div class="detail"> <div class="detail-value">85%</div> <div class="detail-label">Humidity</div> </div> </div> </div> </div> <div class="weather-card" id="sunCard"> <div class="sun-bg"></div> <div class="card-content"> <div class="weather-header"> <div> <div class="weather-type">Sunny</div> <div class="temperature">28°</div> <div class="location">Los Angeles, CA</div> </div> <div class="weather-icon"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"></path> </svg> </div> </div> <div class="weather-details"> <div class="detail"> <div class="detail-value">8 mph</div> <div class="detail-label">Wind</div> </div> <div class="detail"> <div class="detail-value">30%</div> <div class="detail-label">Humidity</div> </div> </div> </div> </div> <div class="weather-card" id="snowCard"> <div class="snow-bg"></div> <div class="card-content"> <div class="weather-header"> <div> <div class="weather-type">Snowy</div> <div class="temperature">-5°</div> <div class="location">Denver, CO</div> </div> <div class="weather-icon"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z"></path> </svg> </div> </div> <div class="weather-details"> <div class="detail"> <div class="detail-value">12 mph</div> <div class="detail-label">Wind</div> </div> <div class="detail"> <div class="detail-value">75%</div> <div class="detail-label">Humidity</div> </div> </div> </div> </div> </div> <div class="controls"> <button class="control-btn active" data-weather="all">All Weather</button> <button class="control-btn" data-weather="wind">Wind</button> <button class="control-btn" data-weather="rain">Rain</button> <button class="control-btn" data-weather="sun">Sun</button> <button class="control-btn" data-weather="snow">Snow</button> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Initialize all weather animations initWindAnimation(); initRainAnimation(); initSunAnimation(); initSnowAnimation(); // Controls const buttons = document.querySelectorAll('.control-btn'); const cards = document.querySelectorAll('.weather-card'); buttons.forEach(button => { button.addEventListener('click', function() { // Remove active class from all buttons buttons.forEach(btn => btn.classList.remove('active')); // Add active class to clicked button this.classList.add('active'); const weatherType = this.getAttribute('data-weather'); if (weatherType === 'all') { cards.forEach(card => { card.style.display = 'block'; }); } else { cards.forEach(card => { if (card.id === `${weatherType}Card`) { card.style.display = 'block'; } else { card.style.display = 'none'; } }); } }); }); }); function initWindAnimation() { const windCard = document.getElementById('windCard'); // Create clouds for (let i = 0; i < 5; i++) { createCloud(windCard); } // Create wind lines for (let i = 0; i < 15; i++) { createWindLine(windCard); } } function createCloud(parent) { const cloud = document.createElement('div'); cloud.className = 'cloud'; const size = Math.random() * 40 + 30; const left = Math.random() * 100; const top = Math.random() * 60 + 20; const duration = Math.random() * 20 + 30; const delay = Math.random() * 10; cloud.style.width = `${size}px`; cloud.style.height = `${size * 0.6}px`; cloud.style.left = `${left}%`; cloud.style.top = `${top}%`; cloud.style.animation = `cloud-move ${duration}s linear ${delay}s infinite`; parent.appendChild(cloud); // Define animation for each cloud const keyframes = ` @keyframes cloud-move { 0% { transform: translateX(${left > 50 ? '100%' : '-100%'}); } 100% { transform: translateX(${left > 50 ? '-100%' : '100%'}); } } `; const styleSheet = document.createElement('style'); styleSheet.type = 'text/css'; styleSheet.innerText = keyframes; document.head.appendChild(styleSheet); } function createWindLine(parent) { const windLine = document.createElement('div'); windLine.className = 'wind-line'; const length = Math.random() * 60 + 40; const top = Math.random() * 100; const left = Math.random() * 30; const angle = Math.random() * 10 - 5; const duration = Math.random() * 2 + 1; const delay = Math.random() * 3; windLine.style.width = `${length}px`; windLine.style.top = `${top}%`; windLine.style.left = `${left}%`; windLine.style.transform = `rotate(${angle}deg)`; windLine.style.animation = `wind-line-move ${duration}s linear ${delay}s infinite`; parent.appendChild(windLine); // Define animation for each line const keyframes = ` @keyframes wind-line-move { 0% { transform: rotate(${angle}deg) translateX(0) scaleX(0); opacity: 0; } 10% { opacity: 0.7; } 80% { opacity: 0.7; } 100% { transform: rotate(${angle}deg) translateX(${parent.offsetWidth}px) scaleX(1); opacity: 0; } } `; const styleSheet = document.createElement('style'); styleSheet.type = 'text/css'; styleSheet.innerText = keyframes; document.head.appendChild(styleSheet); } function initRainAnimation() { const rainCard = document.getElementById('rainCard'); // Create raindrops for (let i = 0; i < 60; i++) { createRaindrop(rainCard); } // Create puddles for (let i = 0; i < 8; i++) { createPuddle(rainCard); } } function createRaindrop(parent) { const raindrop = document.createElement('div'); raindrop.className = 'raindrop'; const left = Math.random() * 100; const delay = Math.random() * 5; const duration = Math.random() * 1 + 0.5; const height = Math.random() * 10 + 10; raindrop.style.height = `${height}px`; raindrop.style.left = `${left}%`; raindrop.style.top = `-${height}px`; raindrop.style.animation = `rain-fall ${duration}s linear ${delay}s infinite`; parent.appendChild(raindrop); // Define animation for each raindrop const keyframes = ` @keyframes rain-fall { 0% { transform: translateY(0) translateX(0); opacity: 0; } 10% { opacity: 0.7; } 95% { opacity: 0.7; } 100% { transform: translateY(${parent.offsetHeight + height}px) translateX(${Math.random() * 20 - 10}px); opacity: 0; } } `; const styleSheet = document.createElement('style'); styleSheet.type = 'text/css'; styleSheet.innerText = keyframes; document.head.appendChild(styleSheet); } function createPuddle(parent) { const puddle = document.createElement('div'); puddle.className = 'puddle'; const size = Math.random() * 30 + 20; const left = Math.random() * 80 + 10; const duration = Math.random() * 3 + 2; const delay = Math.random() * 5; puddle.style.width = `${size}px`; puddle.style.height = `${size * 0.3}px`; puddle.style.left = `${left}%`; puddle.style.animation = `puddle-pulse ${duration}s ease-in-out ${delay}s infinite alternate`; parent.appendChild(puddle); // Define animation for each puddle const keyframes = ` @keyframes puddle-pulse { 0% { transform: scale(0.8); opacity: 0.3; } 100% { transform: scale(1); opacity: 0.5; } } `; const styleSheet = document.createElement('style'); styleSheet.type = 'text/css'; styleSheet.innerText = keyframes; document.head.appendChild(styleSheet); } function initSunAnimation() { const sunCard = document.getElementById('sunCard'); // Create sun const sun = document.createElement('div'); sun.className = 'sun'; sunCard.appendChild(sun); // Create sun rays for (let i = 0; i < 12; i++) { createSunray(sunCard, i * 30); } } function createSunray(parent, angle) { const sunray = document.createElement('div'); sunray.className = 'sunray'; const length = Math.random() * 40 + 60; const width = Math.random() * 6 + 2; const duration = Math.random() * 3 + 3; const delay = Math.random() * 2; sunray.style.width = `${length}px`; sunray.style.height = `${width}px`; sunray.style.top = '100px'; sunray.style.left = '50%'; sunray.style.transform = `translateX(-5px) rotate(${angle}deg)`; sunray.style.animation = `sunray-pulse ${duration}s ease-in-out ${delay}s infinite alternate`; parent.appendChild(sunray); // Define animation for each sunray const keyframes = ` @keyframes sunray-pulse { 0% { opacity: 0.3; transform: translateX(-5px) rotate(${angle}deg) scaleX(0.8); } 100% { opacity: 0.6; transform: translateX(-5px) rotate(${angle}deg) scaleX(1.2); } } `; const styleSheet = document.createElement('style'); styleSheet.type = 'text/css'; styleSheet.innerText = keyframes; document.head.appendChild(styleSheet); } function initSnowAnimation() { const snowCard = document.getElementById('snowCard'); // Create snowflakes for (let i = 0; i < 50; i++) { createSnowflake(snowCard); } // Create snow ground const snowGround = document.createElement('div'); snowGround.className = 'snow-ground'; snowCard.appendChild(snowGround); } function createSnowflake(parent) { const snowflake = document.createElement('div'); snowflake.className = 'snowflake'; const size = Math.random() * 4 + 2; const left = Math.random() * 100; const delay = Math.random() * 10; const duration = Math.random() * 10 + 10; snowflake.style.width = `${size}px`; snowflake.style.height = `${size}px`; snowflake.style.left = `${left}%`; snowflake.style.top = `-${size}px`; snowflake.style.animation = `snowfall ${duration}s linear ${delay}s infinite`; parent.appendChild(snowflake); // Define animation for each snowflake const keyframes = ` @keyframes snowfall { 0% { transform: translateY(0) translateX(0) rotate(0deg); opacity: 0; } 10% { opacity: 0.8; } 90% { opacity: 0.8; } 100% { transform: translateY(${parent.offsetHeight + size}px) translateX(${Math.random() * 100 - 50}px) rotate(360deg); opacity: 0; } } `; const styleSheet = document.createElement('style'); styleSheet.type = 'text/css'; styleSheet.innerText = keyframes; document.head.appendChild(styleSheet); } </script> </body> </html> ```
Below is a single, self‑contained HTML file that includes all the CSS and JavaScript needed to render four animated weather cards (Wind, Rain, Sun, Snow) side‑by‑side on a dark background. The design uses smooth gradients, subtle shadows, and polished rounded corners to match a high‑end Apple‑style aesthetic. Buttons allow you to pause/resume each animation individually. ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Animated Weather Cards</title> <style> /* Global reset & dark theme */ * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, sans-serif; background: #111; color: #fff; display: flex; flex-direction: column; align-items: center; min-height: 100vh; overflow-x: hidden; padding: 20px; } h1 { margin-bottom: 20px; font-weight: 300; letter-spacing: 0.5px; } /* Container for cards */ .cards { display: flex; gap: 20px; flex-wrap: wrap; justify-content: center; } .card { width: 260px; height: 340px; background: linear-gradient(145deg, #1e1e1e, #272727); border-radius: 20px; box-shadow: 0 8px 30px rgba(0,0,0,0.7); position: relative; overflow: hidden; padding: 20px; text-align: center; } .card h2 { margin-top: 10px; font-weight: 400; font-size: 1.4rem; text-transform: uppercase; letter-spacing: 1px; color: #e0e0e0; } .card .btn-toggle { position: absolute; bottom: 12px; left: 50%; transform: translateX(-50%); background: rgba(255,255,255,0.1); border: none; color: #fff; padding: 6px 12px; border-radius: 12px; font-size: 0.9rem; cursor: pointer; transition: background 0.2s; } .card .btn-toggle:hover { background: rgba(255,255,255,0.2); } /* Wind animation */ .wind .cloud { background: #555; border-radius: 50%; width: 60px; height: 40px; position: absolute; top: 40%; left: -80px; animation: moveCloud 6s linear infinite; box-shadow: inset -10px -10px 20px rgba(0,0,0,0.2); } .wind .cloud::before, .wind .cloud::after { content: ""; position: absolute; background: #555; border-radius: 50%; } .wind .cloud::before { width: 50px; height: 30px; top: -15px; left: 5px; } .wind .cloud::after { width: 45px; height: 35px; top: 5px; left: -20px; } .wind .line { width: 2px; height: 100%; background: rgba(255,255,255,0.3); position: absolute; left: 50%; top: 0; animation: swayLine 1.5s ease-in-out infinite alternate; } @keyframes moveCloud { 0% { transform: translateX(0); } 100% { transform: translateX(340px); } } @keyframes swayLine { from { transform: translateX(-4px) rotate(0deg); } to { transform: translateX(4px) rotate(5deg); } } /* Rain animation */ .rain .drop { width: 2px; height: 12px; background: #6ab7ff; position: absolute; top: -20px; left: calc(20% + 50px * var(--i)); border-radius: 50% 50% 0 0; animation: fall 1s linear infinite; animation-delay: calc(0.2s * var(--i)); } @keyframes fall { 0% { transform: translateY(0); opacity: 0; } 10% { opacity: 1; } 80% { opacity: 1; } 100% { transform: translateY(260px); opacity: 0;} } .rain .puddle { position: absolute; bottom: 0; left: 50%; width: 80px; height: 30px; background: rgba(106,183,255,0.2); border-radius: 0 0 50% 50%; transform: translateX(-50%); animation: ripple 3s ease-out infinite; } @keyframes ripple { 0%, 100% { transform: translateX(-50%) scaleX(1); } 50% { transform: translateX(-50%) scaleX(1.2); } } /* Sun animation */ .sun .sun { position: absolute; top: 40px; left: calc(50% - 45px); width: 90px; height: 90px; background: radial-gradient(circle at 30% 30%, #ffd700, #ffbf00); border-radius: 50%; box-shadow: 0 0 30px 10px rgba(255,215,0,0.6); animation: pulse 3s ease-in-out infinite; } .sun .ray { position: absolute; width: 4px; height: 30px; background: #ffd700; top: -10px; left: 50%; transform-origin: bottom center; animation: rotateRay 8s linear infinite; } .sun .ray:nth-child(2) { transform: rotate(45deg); } .sun .ray:nth-child(3) { transform: rotate(90deg); } .sun .ray:nth-child(4) { transform: rotate(135deg); } .sun .ray:nth-child(5) { transform: rotate(180deg); } .sun .ray:nth-child(6) { transform: rotate(225deg); } .sun .ray:nth-child(7) { transform: rotate(270deg); } .sun .ray:nth-child(8) { transform: rotate(315deg); } @keyframes pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.08); } } @keyframes rotateRay { from { transform: rotate(var(--start)) translateY(-40px); } to { transform: rotate(calc(var(--start) + 360deg)) translateY(-40px); } } /* Snow animation */ .snow .flake { position: absolute; top: -20px; left: calc(10% + 20px * var(--i)); width: 8px; height: 8px; background: #fff; border-radius: 50%; opacity: 0.9; animation: snowFall 4s linear infinite; animation-delay: calc(0.4s * var(--i)); } @keyframes snowFall { 0% { transform: translateY(0) rotate(0deg); opacity: 0; } 10% { opacity: 0.9; } 90% { opacity: 0.9; } 100% { transform: translateY(300px) rotate(360deg); opacity: 0; } } </style> </head> <body> <h1>Animated Weather Cards</h1> <div class="cards"> <!-- Wind Card --> <div class="card wind" id="windCard"> <h2>Wind</h2> <div class="cloud"></div> <div class="line"></div> <button class="btn-toggle" onclick="toggleAnimation('wind')">Pause</button> </div> <!-- Rain Card --> <div class="card rain" id="rainCard"> <h2>Rain</h2> <div class="puddle"></div> <!-- generate raindrops via JS --> <button class="btn-toggle" onclick="toggleAnimation('rain')">Pause</button> </div> <!-- Sun Card --> <div class="card sun" id="sunCard"> <h2>Sun</h2> <div class="sun"></div> <div class="ray"></div> <div class="ray"></div> <div class="ray"></div> <div class="ray"></div> <div class="ray"></div> <div class="ray"></div> <div class="ray"></div> <div class="ray"></div> <button class="btn-toggle" onclick="toggleAnimation('sun')">Pause</button> </div> <!-- Snow Card --> <div class="card snow" id="snowCard"> <h2>Snow</h2> <button class="btn-toggle" onclick="toggleAnimation('snow')">Pause</button> </div> </div> <script> // Utility to pause/resume CSS animations const state = { wind: true, rain: true, sun: true, snow: true }; function toggleAnimation(type) { const card = document.getElementById(type + 'Card'); const btn = card.querySelector('.btn-toggle'); state[type] = !state[type]; if (state[type]) { card.style.animationPlayState = 'running'; card.querySelectorAll('*').forEach(el => el.style.animationPlayState = 'running'); btn.textContent = 'Pause'; } else { card.style.animationPlayState = 'paused'; card.querySelectorAll('*').forEach(el => el.style.animationPlayState = 'paused'); btn.textContent = 'Resume'; } } // Dynamically add raindrops function createRainDrops() { const rainCard = document.querySelector('.rain'); for (let i = 0; i < 12; i++) { const drop = document.createElement('div'); drop.className = 'drop'; drop.style.setProperty('--i', i); rainCard.appendChild(drop); } } // Dynamically add snowflakes function createSnowFlakes() { const snowCard = document.querySelector('.snow'); for (let i = 0; i < 20; i++) { const flake = document.createElement('div'); flake.className = 'flake'; flake.style.setProperty('--i', i); snowCard.appendChild(flake); } } // Initialize createRainDrops(); createSnowFlakes(); // For sun rays rotation start angle document.querySelectorAll('.sun .ray').forEach((ray, idx) => { ray.style.setProperty('--start', `${idx * 45}deg`); }); </script> </body> </html> ```