Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Animated Weather Cards</title> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap" rel="stylesheet"> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| :root { | |
| --bg-color: #0f172a; | |
| --card-bg: rgba(255, 255, 255, 0.05); | |
| --card-border: rgba(255, 255, 255, 0.1); | |
| --text-primary: #ffffff; | |
| --text-secondary: #94a3b8; | |
| --accent-sun: #f59e0b; | |
| --accent-rain: #3b82f6; | |
| --accent-snow: #e2e8f0; | |
| --accent-wind: #10b981; | |
| } | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font-family: 'Poppins', sans-serif; | |
| background-color: var(--bg-color); | |
| background-image: radial-gradient(circle at 50% 0%, #1e293b 0%, #0f172a 100%); | |
| color: var(--text-primary); | |
| min-height: 100vh; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| overflow-x: hidden; | |
| } | |
| /* Header */ | |
| header { | |
| width: 100%; | |
| padding: 20px; | |
| text-align: center; | |
| background: rgba(15, 23, 42, 0.8); | |
| backdrop-filter: blur(10px); | |
| position: sticky; | |
| top: 0; | |
| z-index: 100; | |
| border-bottom: 1px solid var(--card-border); | |
| } | |
| .brand-link { | |
| color: var(--text-secondary); | |
| text-decoration: none; | |
| font-size: 0.9rem; | |
| font-weight: 500; | |
| transition: color 0.3s ease; | |
| } | |
| .brand-link:hover { | |
| color: var(--text-primary); | |
| text-decoration: underline; | |
| } | |
| .title { | |
| margin-top: 10px; | |
| font-size: 1.5rem; | |
| font-weight: 700; | |
| background: linear-gradient(to right, #fff, #94a3b8); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| } | |
| /* Controls */ | |
| .controls { | |
| margin: 30px 0; | |
| display: flex; | |
| gap: 10px; | |
| flex-wrap: wrap; | |
| justify-content: center; | |
| } | |
| .btn { | |
| padding: 10px 20px; | |
| border: none; | |
| border-radius: 30px; | |
| background: var(--card-bg); | |
| color: var(--text-primary); | |
| border: 1px solid var(--card-border); | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| font-family: inherit; | |
| font-weight: 500; | |
| } | |
| .btn:hover, .btn.active { | |
| background: rgba(255, 255, 255, 0.2); | |
| transform: translateY(-2px); | |
| box-shadow: 0 5px 15px rgba(0,0,0,0.3); | |
| } | |
| /* Grid Layout */ | |
| .weather-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); | |
| gap: 30px; | |
| width: 90%; | |
| max-width: 1200px; | |
| padding-bottom: 50px; | |
| } | |
| /* Card Styles */ | |
| .card { | |
| background: var(--card-bg); | |
| border: 1px solid var(--card-border); | |
| border-radius: 24px; | |
| padding: 30px; | |
| position: relative; | |
| overflow: hidden; | |
| backdrop-filter: blur(12px); | |
| transition: transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.27), opacity 0.3s ease; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| box-shadow: 0 10px 30px -10px rgba(0,0,0,0.5); | |
| } | |
| .card.hidden { | |
| display: none; | |
| } | |
| .card:hover { | |
| transform: translateY(-10px); | |
| border-color: rgba(255,255,255,0.2); | |
| } | |
| /* Weather Visual Area */ | |
| .visual { | |
| width: 100%; | |
| height: 150px; | |
| position: relative; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| margin-bottom: 20px; | |
| } | |
| /* Info Area */ | |
| .info { | |
| text-align: center; | |
| width: 100%; | |
| z-index: 2; | |
| } | |
| .temp { | |
| font-size: 3.5rem; | |
| font-weight: 700; | |
| line-height: 1; | |
| margin-bottom: 5px; | |
| } | |
| .condition { | |
| font-size: 1.2rem; | |
| color: var(--text-secondary); | |
| margin-bottom: 20px; | |
| text-transform: uppercase; | |
| letter-spacing: 1px; | |
| } | |
| .details { | |
| display: flex; | |
| justify-content: space-around; | |
| width: 100%; | |
| padding-top: 20px; | |
| border-top: 1px solid rgba(255,255,255,0.1); | |
| } | |
| .detail-item { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| font-size: 0.9rem; | |
| color: var(--text-secondary); | |
| } | |
| .detail-item i { | |
| margin-bottom: 5px; | |
| font-size: 1.1rem; | |
| } | |
| /* --- ANIMATIONS & ART --- */ | |
| /* Common Cloud */ | |
| .cloud { | |
| width: 100px; | |
| height: 40px; | |
| background: #fff; | |
| border-radius: 50px; | |
| position: absolute; | |
| z-index: 2; | |
| } | |
| .cloud::after { | |
| content: ''; | |
| position: absolute; | |
| top: -25px; | |
| left: 15px; | |
| width: 45px; | |
| height: 45px; | |
| background: #fff; | |
| border-radius: 50%; | |
| } | |
| .cloud::before { | |
| content: ''; | |
| position: absolute; | |
| top: -15px; | |
| left: 45px; | |
| width: 35px; | |
| height: 35px; | |
| background: #fff; | |
| border-radius: 50%; | |
| } | |
| /* 1. SUN CARD */ | |
| .card.sun .visual .sun-circle { | |
| width: 80px; | |
| height: 80px; | |
| background: linear-gradient(45deg, #f59e0b, #fbbf24); | |
| border-radius: 50%; | |
| box-shadow: 0 0 40px rgba(245, 158, 11, 0.6); | |
| position: absolute; | |
| animation: sun-pulse 3s infinite alternate; | |
| } | |
| .card.sun .visual .sun-rays { | |
| position: absolute; | |
| width: 120px; | |
| height: 120px; | |
| animation: spin 10s linear infinite; | |
| } | |
| .card.sun .visual .sun-rays span { | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| width: 100%; | |
| height: 2px; | |
| background: rgba(245, 158, 11, 0.5); | |
| } | |
| .card.sun .visual .cloud { | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-20%, 10%); | |
| opacity: 0.9; | |
| animation: float 4s ease-in-out infinite; | |
| } | |
| /* 2. RAIN CARD */ | |
| .card.rain .visual .cloud { | |
| background: #94a3b8; | |
| box-shadow: 0 10px 15px rgba(0,0,0,0.2); | |
| top: 40%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| } | |
| .card.rain .visual .cloud::after, | |
| .card.rain .visual .cloud::before { | |
| background: #94a3b8; | |
| } | |
| .rain-drop { | |
| position: absolute; | |
| background: #60a5fa; | |
| width: 2px; | |
| height: 10px; | |
| top: 60%; | |
| opacity: 0; | |
| animation: rain-fall 1s linear infinite; | |
| border-radius: 2px; | |
| } | |
| /* 3. SNOW CARD */ | |
| .card.snow .visual .cloud { | |
| background: #e2e8f0; | |
| top: 40%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| filter: drop-shadow(0 0 10px rgba(255,255,255,0.3)); | |
| } | |
| .snow-flake { | |
| position: absolute; | |
| color: white; | |
| font-size: 10px; | |
| top: 60%; | |
| opacity: 0; | |
| animation: snow-fall 2.5s linear infinite; | |
| } | |
| /* 4. WIND CARD */ | |
| .card.wind .visual .cloud { | |
| background: #cbd5e1; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| animation: wind-shake 2s ease-in-out infinite; | |
| } | |
| .wind-line { | |
| position: absolute; | |
| height: 2px; | |
| background: rgba(255,255,255,0.5); | |
| border-radius: 2px; | |
| animation: wind-blow 1.5s linear infinite; | |
| } | |
| /* Keyframes */ | |
| @keyframes spin { 100% { transform: rotate(360deg); } } | |
| @keyframes sun-pulse { | |
| 0% { box-shadow: 0 0 30px rgba(245, 158, 11, 0.4); transform: scale(1); } | |
| 100% { box-shadow: 0 0 60px rgba(245, 158, 11, 0.8); transform: scale(1.1); } | |
| } | |
| @keyframes float { | |
| 0%, 100% { transform: translate(-20%, 10%); } | |
| 50% { transform: translate(-20%, 5%); } | |
| } | |
| @keyframes rain-fall { | |
| 0% { transform: translateY(0); opacity: 1; } | |
| 100% { transform: translateY(60px); opacity: 0; } | |
| } | |
| @keyframes snow-fall { | |
| 0% { transform: translateY(0) translateX(0) rotate(0deg); opacity: 1; } | |
| 25% { transform: translateY(20px) translateX(5px) rotate(45deg); } | |
| 50% { transform: translateY(40px) translateX(-5px) rotate(90deg); } | |
| 75% { transform: translateY(60px) translateX(5px) rotate(135deg); } | |
| 100% { transform: translateY(80px) translateX(0) rotate(180deg); opacity: 0; } | |
| } | |
| @keyframes wind-shake { | |
| 0%, 100% { transform: translate(-50%, -50%); } | |
| 50% { transform: translate(-45%, -50%); } | |
| } | |
| @keyframes wind-blow { | |
| 0% { left: -50px; opacity: 0; width: 20px; } | |
| 50% { opacity: 1; width: 60px; } | |
| 100% { left: 110%; opacity: 0; width: 20px; } | |
| } | |
| /* Responsive Tweaks */ | |
| @media (max-width: 600px) { | |
| .temp { font-size: 2.5rem; } | |
| .weather-grid { grid-template-columns: 1fr; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <header> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" class="brand-link" target="_blank">Built with anycoder</a> | |
| <h1 class="title">Weather Animations</h1> | |
| </header> | |
| <!-- Controls to switch views --> | |
| <div class="controls"> | |
| <button class="btn active" onclick="filterWeather('all')">Show All</button> | |
| <button class="btn" onclick="filterWeather('sun')">Sunny</button> | |
| <button class="btn" onclick="filterWeather('rain')">Rainy</button> | |
| <button class="btn" onclick="filterWeather('snow')">Snowy</button> | |
| <button class="btn" onclick="filterWeather('wind')">Windy</button> | |
| </div> | |
| <div class="weather-grid"> | |
| <!-- SUNNY CARD --> | |
| <div class="card sun" data-type="sun"> | |
| <div class="visual"> | |
| <div class="sun-rays"> | |
| <!-- Rays generated via CSS or JS, let's keep it simple with spans in HTML for control --> | |
| <span style="transform: translate(-50%, -50%) rotate(0deg)"></span> | |
| <span style="transform: translate(-50%, -50%) rotate(45deg)"></span> | |
| <span style="transform: translate(-50%, -50%) rotate(90deg)"></span> | |
| <span style="transform: translate(-50%, -50%) rotate(135deg)"></span> | |
| </div> | |
| <div class="sun-circle"></div> | |
| <div class="cloud"></div> | |
| </div> | |
| <div class="info"> | |
| <div class="temp">28°C</div> | |
| <div class="condition">Sunny</div> | |
| <div class="details"> | |
| <div class="detail-item"> | |
| <i class="fas fa-wind"></i> | |
| <span>12 km/h</span> | |
| </div> | |
| <div class="detail-item"> | |
| <i class="fas fa-tint"></i> | |
| <span>45%</span> | |
| </div> | |
| <div class="detail-item"> | |
| <i class="fas fa-sun"></i> | |
| <span>UV 8</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- RAINY CARD --> | |
| <div class="card rain" data-type="rain"> | |
| <div class="visual" id="rain-visual"> | |
| <div class="cloud"></div> | |
| <!-- Raindrops injected via JS --> | |
| </div> | |
| <div class="info"> | |
| <div class="temp">15°C</div> | |
| <div class="condition">Heavy Rain</div> | |
| <div class="details"> | |
| <div class="detail-item"> | |
| <i class="fas fa-wind"></i> | |
| <span>25 km/h</span> | |
| </div> | |
| <div class="detail-item"> | |
| <i class="fas fa-tint"></i> | |
| <span>92%</span> | |
| </div> | |
| <div class="detail-item"> | |
| <i class="fas fa-umbrella"></i> | |
| <span>100%</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- SNOWY CARD --> | |
| <div class="card snow" data-type="snow"> | |
| <div class="visual" id="snow-visual"> | |
| <div class="cloud"></div> | |
| <!-- Snowflakes injected via JS --> | |
| </div> | |
| <div class="info"> | |
| <div class="temp">-4°C</div> | |
| <div class="condition">Snowing</div> | |
| <div class="details"> | |
| <div class="detail-item"> | |
| <i class="fas fa-wind"></i> | |
| <span>18 km/h</span> | |
| </div> | |
| <div class="detail-item"> | |
| <i class="fas fa-snowflake"></i> | |
| <span>80%</span> | |
| </div> | |
| <div class="detail-item"> | |
| <i class="fas fa-thermometer-empty"></i> | |
| <span>Cold</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- WINDY CARD --> | |
| <div class="card wind" data-type="wind"> | |
| <div class="visual" id="wind-visual"> | |
| <div class="cloud"></div> | |
| <!-- Wind lines injected via JS --> | |
| </div> | |
| <div class="info"> | |
| <div class="temp">19°C</div> | |
| <div class="condition">Windy</div> | |
| <div class="details"> | |
| <div class="detail-item"> | |
| <i class="fas fa-wind"></i> | |
| <span>45 km/h</span> | |
| </div> | |
| <div class="detail-item"> | |
| <i class="fas fa-tint"></i> | |
| <span>55%</span> | |
| </div> | |
| <div class="detail-item"> | |
| <i class="fas fa-leaf"></i> | |
| <span>High</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // Initialization for particles | |
| document.addEventListener('DOMContentLoaded', () => { | |
| createRain(); | |
| createSnow(); | |
| createWind(); | |
| }); | |
| // Logic to switch/filter cards | |
| function filterWeather(type) { | |
| const cards = document.querySelectorAll('.card'); | |
| const buttons = document.querySelectorAll('.btn'); | |
| // Update buttons state | |
| buttons.forEach(btn => btn.classList.remove('active')); | |
| event.target.classList.add('active'); | |
| // Filter cards | |
| cards.forEach(card => { | |
| if (type === 'all') { | |
| card.classList.remove('hidden'); | |
| } else { | |
| if (card.getAttribute('data-type') === type) { | |
| card.classList.remove('hidden'); | |
| } else { | |
| card.classList.add('hidden'); | |
| } | |
| } | |
| }); | |
| } | |
| // Animation Generators | |
| function createRain() { | |
| const container = document.getElementById('rain-visual'); | |
| const dropCount = 15; | |
| for(let i = 0; i < dropCount; i++) { | |
| const drop = document.createElement('div'); | |
| drop.classList.add('rain-drop'); | |
| // Random positions | |
| const left = Math.floor(Math.random() * 60) + 20; // Keep within center area mostly | |
| const delay = Math.random() * 1; | |
| const duration = Math.random() * 0.5 + 0.5; | |
| drop.style.left = `${left}%`; | |
| drop.style.animationDelay = `${delay}s`; | |
| drop.style.animationDuration = `${duration}s`; | |
| container.appendChild(drop); | |
| } | |
| } | |
| function createSnow() { | |
| const container = document.getElementById('snow-visual'); | |
| const flakeCount = 20; | |
| for(let i = 0; i < flakeCount; i++) { | |
| const flake = document.createElement('i'); | |
| flake.classList.add('fas', 'fa-snowflake', 'snow-flake'); | |
| const left = Math.floor(Math.random() * 80) + 10; | |
| const delay = Math.random() * 2; | |
| const duration = Math.random() * 1.5 + 1.5; | |
| const size = Math.random() * 8 + 5; | |
| flake.style.left = `${left}%`; | |
| flake.style.animationDelay = `${delay}s`; | |
| flake.style.animationDuration = `${duration}s`; | |
| flake.style.fontSize = `${size}px`; | |
| flake.style.opacity = Math.random(); | |
| container.appendChild(flake); | |
| } | |
| } | |
| function createWind() { | |
| const container = document.getElementById('wind-visual'); | |
| const lineCount = 6; | |
| for(let i = 0; i < lineCount; i++) { | |
| const line = document.createElement('div'); | |
| line.classList.add('wind-line'); | |
| const top = Math.floor(Math.random() * 80) + 10; | |
| const delay = Math.random() * 2; | |
| const duration = Math.random() * 1 + 0.5; | |
| line.style.top = `${top}%`; | |
| line.style.animationDelay = `${delay}s`; | |
| line.style.animationDuration = `${duration}s`; | |
| container.appendChild(line); | |
| } | |
| } | |
| </script> | |
| </body> | |
| </html> |