Skeleton loading screens are a crucial aspect of modern web design, enhancing user experience by providing visual feedback during data fetching. These placeholders keep users engaged, reducing perceived wait times.
In this article, we will explore 10 skeleton loading examples that demonstrate various techniques and styles. Each example showcases how to maintain a seamless and interactive user interface.
CODE1
Here's the code:
CODETEXT1
CODE2
Here's the code:
CODETEXT2
CODE3
Here's the code:
CODETEXT3
CODE4
Here's the code:
CODETEXT4
CODE5
Here's the code:
CODETEXT5
Designers and developers, elevate your skeleton loading screens with Subframe's drag-and-drop interface. Its intuitive, responsive canvas ensures pixel-perfect UI every time, making it a favorite among professionals.
Join the community of satisfied users and start for free today!
CODE6
Here's the code:
CODETEXT6
CODE7
Here's the code:
CODETEXT7
CODE8
Here's the code:
CODETEXT8
CODE9
Here's the code:
CODETEXT9
CODE10
Here's the code:
CODETEXT10
Ready to elevate your UI design game? With Subframe, you can create pixel-perfect interfaces, including efficient skeleton loading screens, in minutes. Its drag-and-drop editor and beautifully crafted components make the process seamless.
Don't wait! Start for free and begin designing stunning UIs right away.
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Social Media Feed Skeleton</title> <style> :root { --background: #f9f9fb; --skeleton-base: #e6e9ef; --skeleton-highlight: #f1f3f7; --text-color: #2c3e50; --accent-color: #6c5ce7; --secondary-accent: #a29bfe; --card-shadow: 0 8px 24px rgba(149, 157, 165, 0.1); --animation-duration: 1.5s; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; } body { background-color: var(--background); color: var(--text-color); height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; padding: 20px; overflow-x: hidden; } .container { width: 100%; max-width: 550px; height: auto; position: relative; } .feed-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; position: sticky; top: 0; background-color: var(--background); z-index: 10; padding: 10px 0; } .logo { font-size: 22px; font-weight: 700; color: var(--accent-color); letter-spacing: -0.5px; display: flex; align-items: center; } .logo span { display: inline-block; width: 10px; height: 10px; background-color: var(--secondary-accent); border-radius: 50%; margin-right: 8px; animation: pulse 2s infinite; } .controls { display: flex; align-items: center; gap: 12px; } .control-item { width: 36px; height: 36px; border-radius: 50%; background-color: var(--skeleton-base); display: flex; align-items: center; justify-content: center; position: relative; overflow: hidden; } .control-item::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, var(--skeleton-highlight), transparent); animation: shimmer var(--animation-duration) infinite; } .card { background-color: white; border-radius: 12px; padding: 16px; margin-bottom: 16px; box-shadow: var(--card-shadow); transition: transform 0.3s ease, box-shadow 0.3s ease; position: relative; overflow: hidden; } .card:hover { transform: translateY(-2px); box-shadow: 0 10px 30px rgba(149, 157, 165, 0.2); } .card-header { display: flex; align-items: center; margin-bottom: 14px; } .avatar { width: 44px; height: 44px; border-radius: 50%; background-color: var(--skeleton-base); margin-right: 12px; position: relative; overflow: hidden; } .avatar::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, var(--skeleton-highlight), transparent); animation: shimmer var(--animation-duration) infinite; } .user-info { flex: 1; } .username { height: 16px; width: 120px; background-color: var(--skeleton-base); border-radius: 4px; margin-bottom: 6px; position: relative; overflow: hidden; } .username::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, var(--skeleton-highlight), transparent); animation: shimmer var(--animation-duration) infinite; } .timestamp { height: 12px; width: 80px; background-color: var(--skeleton-base); border-radius: 4px; position: relative; overflow: hidden; } .timestamp::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, var(--skeleton-highlight), transparent); animation: shimmer var(--animation-duration) infinite; } .card-content .text-line { height: 12px; background-color: var(--skeleton-base); border-radius: 4px; margin-bottom: 8px; position: relative; overflow: hidden; } .card-content .text-line::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, var(--skeleton-highlight), transparent); animation: shimmer var(--animation-duration) infinite; } .card-content .text-line:last-child { width: 70%; } .image-placeholder { height: 200px; background-color: var(--skeleton-base); border-radius: 8px; margin: 16px 0; position: relative; overflow: hidden; } .image-placeholder::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, var(--skeleton-highlight), transparent); animation: shimmer var(--animation-duration) infinite; } .card-actions { display: flex; gap: 16px; margin-top: 12px; } .action-btn { height: 14px; width: 60px; background-color: var(--skeleton-base); border-radius: 4px; position: relative; overflow: hidden; } .action-btn::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, var(--skeleton-highlight), transparent); animation: shimmer var(--animation-duration) infinite; } .loading-bar { position: fixed; top: 0; left: 0; height: 3px; width: 100%; background: linear-gradient(90deg, var(--accent-color), var(--secondary-accent)); z-index: 100; animation: loadingProgress 3s ease infinite; } .loader-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: radial-gradient(circle, transparent 60%, rgba(249, 249, 251, 0.8) 100%); pointer-events: none; opacity: 0; transition: opacity 0.5s ease; } .create-post { display: flex; background-color: white; border-radius: 12px; padding: 12px 16px; margin-bottom: 20px; box-shadow: var(--card-shadow); } .create-post .avatar { width: 36px; height: 36px; } .create-post .input-placeholder { flex: 1; height: 36px; background-color: var(--skeleton-base); border-radius: 18px; margin-left: 12px; position: relative; overflow: hidden; } .create-post .input-placeholder::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, var(--skeleton-highlight), transparent); animation: shimmer var(--animation-duration) infinite; } .stories-row { display: flex; overflow-x: scroll; padding: 10px 0; margin-bottom: 16px; scrollbar-width: none; -ms-overflow-style: none; } .stories-row::-webkit-scrollbar { display: none; } .story { flex: 0 0 auto; width: 68px; margin-right: 12px; display: flex; flex-direction: column; align-items: center; } .story .story-circle { width: 60px; height: 60px; border-radius: 50%; padding: 2px; background: linear-gradient(45deg, var(--accent-color), var(--secondary-accent)); margin-bottom: 6px; } .story .story-content { width: 100%; height: 100%; border-radius: 50%; background-color: var(--skeleton-base); position: relative; overflow: hidden; } .story .story-content::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, var(--skeleton-highlight), transparent); animation: shimmer var(--animation-duration) infinite; } .story .story-username { width: 100%; height: 10px; background-color: var(--skeleton-base); border-radius: 4px; position: relative; overflow: hidden; } .story .story-username::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, var(--skeleton-highlight), transparent); animation: shimmer var(--animation-duration) infinite; } .your-story .story-circle { background: #e6e9ef; } .your-story .story-add { position: absolute; bottom: -4px; right: -4px; width: 20px; height: 20px; border-radius: 50%; background-color: var(--accent-color); display: flex; align-items: center; justify-content: center; color: white; font-size: 14px; font-weight: bold; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } .navigation { position: fixed; bottom: 0; left: 0; width: 100%; background-color: white; display: flex; justify-content: space-around; padding: 12px 0; box-shadow: 0 -4px 10px rgba(0, 0, 0, 0.05); } .nav-item { width: 24px; height: 24px; background-color: var(--skeleton-base); border-radius: 4px; position: relative; overflow: hidden; } .nav-item::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, var(--skeleton-highlight), transparent); animation: shimmer var(--animation-duration) infinite; } .loaded-content { opacity: 0; transition: opacity 0.3s ease; } @keyframes shimmer { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } } @keyframes pulse { 0% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.1); opacity: 0.7; } 100% { transform: scale(1); opacity: 1; } } @keyframes loadingProgress { 0% { width: 0%; opacity: 1; } 50% { width: 80%; opacity: 1; } 90% { width: 100%; opacity: 1; } 100% { width: 100%; opacity: 0; } } .fade-in { animation: fadeIn 0.5s ease forwards; } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } .loading-complete { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: rgba(255, 255, 255, 0.95); padding: 20px 40px; border-radius: 12px; box-shadow: var(--card-shadow); text-align: center; opacity: 0; transition: opacity 0.3s ease; pointer-events: none; z-index: 1000; } .loading-complete h3 { color: var(--accent-color); margin-bottom: 8px; } .loading-complete p { color: var(--text-color); font-size: 14px; } .loading-status { position: absolute; top: 16px; right: 16px; font-size: 14px; color: var(--accent-color); font-weight: 500; opacity: 0.8; display: flex; align-items: center; gap: 6px; } .loading-status .dot { width: 8px; height: 8px; background-color: var(--accent-color); border-radius: 50%; display: inline-block; animation: pulseDot 1s infinite; } @keyframes pulseDot { 0%, 100% { opacity: 0.4; } 50% { opacity: 1; } } @media (max-width: 600px) { .container { padding: 0 10px; } .image-placeholder { height: 160px; } } </style> </head> <body> <div class="loading-bar"></div> <div class="container"> <div class="loading-status"> <span class="dot"></span> Loading feed... </div> <div class="feed-header"> <div class="logo"><span></span>Connectr</div> <div class="controls"> <div class="control-item"></div> <div class="control-item"></div> </div> </div> <div class="stories-row"> <div class="story your-story"> <div class="story-circle"> <div class="story-content"> <div class="story-add">+</div> </div> </div> <div class="story-username"></div> </div> <div class="story"> <div class="story-circle"> <div class="story-content"></div> </div> <div class="story-username"></div> </div> <div class="story"> <div class="story-circle"> <div class="story-content"></div> </div> <div class="story-username"></div> </div> <div class="story"> <div class="story-circle"> <div class="story-content"></div> </div> <div class="story-username"></div> </div> <div class="story"> <div class="story-circle"> <div class="story-content"></div> </div> <div class="story-username"></div> </div> <div class="story"> <div class="story-circle"> <div class="story-content"></div> </div> <div class="story-username"></div> </div> </div> <div class="create-post"> <div class="avatar"></div> <div class="input-placeholder"></div> </div> <div class="card" data-load-delay="800"> <div class="card-header"> <div class="avatar"></div> <div class="user-info"> <div class="username"></div> <div class="timestamp"></div> </div> </div> <div class="card-content"> <div class="text-line" style="width: 95%"></div> <div class="text-line" style="width: 90%"></div> <div class="text-line" style="width: 60%"></div> </div> <div class="image-placeholder"></div> <div class="card-actions"> <div class="action-btn"></div> <div class="action-btn"></div> <div class="action-btn"></div> </div> <div class="loader-overlay"></div> </div> <div class="card" data-load-delay="1200"> <div class="card-header"> <div class="avatar"></div> <div class="user-info"> <div class="username"></div> <div class="timestamp"></div> </div> </div> <div class="card-content"> <div class="text-line" style="width: 100%"></div> <div class="text-line" style="width: 95%"></div> <div class="text-line" style="width: 85%"></div> <div class="text-line" style="width: 75%"></div> </div> <div class="card-actions"> <div class="action-btn"></div> <div class="action-btn"></div> <div class="action-btn"></div> </div> <div class="loader-overlay"></div> </div> <div class="card" data-load-delay="1600"> <div class="card-header"> <div class="avatar"></div> <div class="user-info"> <div class="username"></div> <div class="timestamp"></div> </div> </div> <div class="card-content"> <div class="text-line" style="width: 90%"></div> <div class="text-line" style="width: 85%"></div> </div> <div class="image-placeholder"></div> <div class="card-actions"> <div class="action-btn"></div> <div class="action-btn"></div> <div class="action-btn"></div> </div> <div class="loader-overlay"></div> </div> </div> <div class="navigation"> <div class="nav-item"></div> <div class="nav-item"></div> <div class="nav-item"></div> <div class="nav-item"></div> <div class="nav-item"></div> </div> <div class="loading-complete"> <h3>Content Loaded</h3> <p>Your feed is now ready</p> </div> <script> document.addEventListener('DOMContentLoaded', function() { const cards = document.querySelectorAll('.card'); const loadingStatus = document.querySelector('.loading-status'); const loadingComplete = document.querySelector('.loading-complete'); const loadingBar = document.querySelector('.loading-bar'); // Staggered card loading animation cards.forEach(card => { const delay = parseInt(card.getAttribute('data-load-delay')) || 1000; const overlay = card.querySelector('.loader-overlay'); setTimeout(() => { overlay.style.opacity = '0.2'; // Simulate content revealing with a pulse effect setTimeout(() => { card.classList.add('loaded'); overlay.style.opacity = '0'; }, 300); }, delay); }); // Simulate loading completion setTimeout(() => { loadingStatus.style.opacity = '0'; // Show loading complete notification loadingComplete.style.opacity = '1'; setTimeout(() => { loadingComplete.style.opacity = '0'; }, 2000); // Loop the loading bar animation for demo purposes setInterval(() => { loadingBar.style.opacity = '0'; setTimeout(() => { loadingBar.style.opacity = '1'; }, 300); }, 3000); }, 3000); // Create interactive hover effects cards.forEach(card => { card.addEventListener('mouseenter', function() { const randomDelay = Math.floor(Math.random() * 100); const elements = card.querySelectorAll('.avatar, .username, .timestamp, .text-line, .image-placeholder, .action-btn'); elements.forEach((element, index) => { setTimeout(() => { element.style.backgroundColor = 'var(--skeleton-highlight)'; setTimeout(() => { element.style.backgroundColor = 'var(--skeleton-base)'; }, 300); }, randomDelay + (index * 50)); }); }); }); // Add click interactions document.querySelectorAll('.control-item, .nav-item, .action-btn, .story, .input-placeholder').forEach(item => { item.addEventListener('click', function() { this.style.transform = 'scale(0.95)'; setTimeout(() => { this.style.transform = 'scale(1)'; }, 150); }); }); // Simulate scrolling load effect window.addEventListener('scroll', function() { const scrollPos = window.scrollY; const windowHeight = window.innerHeight; cards.forEach(card => { const cardPos = card.getBoundingClientRect().top; if (cardPos < windowHeight - 100) { setTimeout(() => { card.style.opacity = '1'; }, 100); } }); }); }); </script> </body> </html>
<html> <head> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background-color: #f9f9fb; height: 100vh; display: flex; flex-direction: column; align-items: center; padding: 20px; overflow-x: hidden; max-width: 700px; margin: 0 auto; } header { width: 100%; margin-bottom: 20px; } h1 { font-size: 24px; font-weight: 700; margin-bottom: 8px; color: #1a1a1a; } .controls { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; width: 100%; } .search-bar { height: 40px; width: 70%; background: linear-gradient(90deg, #f0f0f0, #e6e6e6); border-radius: 8px; animation: pulse 1.5s infinite alternate; } .filter-button { height: 40px; width: 25%; background: linear-gradient(90deg, #f0f0f0, #e6e6e6); border-radius: 8px; animation: pulse 1.5s infinite alternate; animation-delay: 0.3s; } .product-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 20px; width: 100%; } .product-card { display: flex; flex-direction: column; border-radius: 10px; overflow: hidden; background-color: white; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); transition: transform 0.3s ease, box-shadow 0.3s ease; position: relative; } .product-card:hover { transform: translateY(-5px); box-shadow: 0 10px 20px rgba(0, 0, 0, 0.08); } .product-image { width: 100%; height: 160px; background: linear-gradient(135deg, #f5f7fa, #e3e6f0); position: relative; overflow: hidden; } .product-image::before { content: ""; position: absolute; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.5), transparent); transform: translateX(-100%); animation: shimmer 2s infinite; } .product-content { padding: 15px; display: flex; flex-direction: column; gap: 10px; } .product-title { height: 14px; width: 80%; background: linear-gradient(90deg, #f0f0f0, #e6e6e6); border-radius: 4px; animation: pulse 1.5s infinite alternate; } .product-price { height: 16px; width: 40%; background: linear-gradient(90deg, #f0f0f0, #e6e6e6); border-radius: 4px; animation: pulse 1.5s infinite alternate; animation-delay: 0.2s; } .product-rating { height: 12px; width: 60%; background: linear-gradient(90deg, #f0f0f0, #e6e6e6); border-radius: 4px; animation: pulse 1.5s infinite alternate; animation-delay: 0.4s; } .load-more { height: 50px; width: 200px; margin-top: 30px; background: linear-gradient(90deg, #f0f0f0, #e6e6e6); border-radius: 8px; animation: pulse 1.5s infinite alternate; animation-delay: 0.5s; } @keyframes pulse { 0% { opacity: 0.6; } 100% { opacity: 1; } } @keyframes shimmer { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } } .loading-indicator { position: fixed; top: 20px; right: 20px; display: flex; align-items: center; gap: 8px; padding: 8px 12px; background-color: rgba(255, 255, 255, 0.9); border-radius: 20px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); z-index: 1000; animation: fadeInOut 2s infinite alternate; } .loading-dot { width: 8px; height: 8px; border-radius: 50%; background: linear-gradient(135deg, #6366F1, #8B5CF6); animation: dotPulse 1.5s infinite alternate; } .loading-dot:nth-child(2) { animation-delay: 0.2s; } .loading-dot:nth-child(3) { animation-delay: 0.4s; } @keyframes dotPulse { 0% { transform: scale(0.8); opacity: 0.6; } 100% { transform: scale(1.2); opacity: 1; } } @keyframes fadeInOut { 0% { opacity: 0.7; } 100% { opacity: 1; } } .progress-bar { position: fixed; top: 0; left: 0; height: 3px; background: linear-gradient(90deg, #6366F1, #8B5CF6, #EC4899); z-index: 1001; width: 0%; animation: loadProgress 3s forwards cubic-bezier(0.34, 1.56, 0.64, 1); } @keyframes loadProgress { 0% { width: 0%; } 60% { width: 70%; } 80% { width: 85%; } 100% { width: 100%; } } /* Media Queries for Responsiveness */ @media (max-width: 600px) { .product-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 15px; } .product-image { height: 130px; } h1 { font-size: 20px; } } @media (max-width: 400px) { .product-grid { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 10px; } .product-image { height: 100px; } .product-content { padding: 10px; gap: 8px; } h1 { font-size: 18px; } } </style> </head> <body> <div class="progress-bar"></div> <div class="loading-indicator"> <div class="loading-dot"></div> <div class="loading-dot"></div> <div class="loading-dot"></div> </div> <header> <h1>NOVA Marketplace</h1> <p>Curated selection of premium products loading shortly...</p> </header> <div class="controls"> <div class="search-bar"></div> <div class="filter-button"></div> </div> <div class="product-grid" id="productGrid"> <!-- Product skeleton cards will be dynamically added here --> </div> <div class="load-more"></div> <script> document.addEventListener('DOMContentLoaded', function() { const grid = document.getElementById('productGrid'); const productCount = window.innerWidth < 400 ? 6 : window.innerWidth < 600 ? 8 : 12; // Create skeleton product cards for (let i = 0; i < productCount; i++) { const card = document.createElement('div'); card.className = 'product-card'; card.style.animationDelay = `${i * 0.1}s`; card.innerHTML = ` <div class="product-image"></div> <div class="product-content"> <div class="product-title"></div> <div class="product-price"></div> <div class="product-rating"></div> </div> `; grid.appendChild(card); } // Simulate progress bar completion setTimeout(() => { document.querySelector('.progress-bar').style.width = '100%'; }, 500); // Add hover effects to skeleton cards const cards = document.querySelectorAll('.product-card'); cards.forEach(card => { card.addEventListener('mouseenter', () => { card.querySelector('.product-image').style.background = 'linear-gradient(135deg, #e3e6f0, #f5f7fa)'; }); card.addEventListener('mouseleave', () => { card.querySelector('.product-image').style.background = 'linear-gradient(135deg, #f5f7fa, #e3e6f0)'; }); }); // Handle window resize for responsiveness window.addEventListener('resize', () => { const newProductCount = window.innerWidth < 400 ? 6 : window.innerWidth < 600 ? 8 : 12; if (newProductCount !== grid.children.length) { // Clear existing cards grid.innerHTML = ''; // Create new cards based on new viewport size for (let i = 0; i < newProductCount; i++) { const card = document.createElement('div'); card.className = 'product-card'; card.style.animationDelay = `${i * 0.1}s`; card.innerHTML = ` <div class="product-image"></div> <div class="product-content"> <div class="product-title"></div> <div class="product-price"></div> <div class="product-rating"></div> </div> `; grid.appendChild(card); } } }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>News Article Skeleton</title> <style> /* Base Styles */ :root { --loading-color: #f0f0f0; --loading-highlight: #e0e0e0; --text-color: #222; --background: #fff; --accent: #005bbb; --secondary: #f5f5f5; --timestamp: #888; --border: #eaeaea; } * { 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-color: var(--background); color: var(--text-color); max-width: 700px; height: 700px; margin: 0 auto; padding: 20px; overflow-y: auto; } .skeleton-container { width: 100%; position: relative; } .skeleton-header { margin-bottom: 24px; border-bottom: 1px solid var(--border); padding-bottom: 12px; } .loading { position: relative; background: var(--loading-color); border-radius: 4px; overflow: hidden; } .loading::after { content: ""; position: absolute; top: 0; right: 0; bottom: 0; left: 0; transform: translateX(-100%); background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); animation: shimmer 2s infinite; } @keyframes shimmer { 100% { transform: translateX(100%); } } .skeleton-title { height: 42px; margin-bottom: 16px; width: 90%; } .skeleton-meta { display: flex; gap: 16px; margin-bottom: 16px; } .skeleton-category { height: 20px; width: 100px; } .skeleton-timestamp { height: 20px; width: 140px; } .skeleton-author { display: flex; align-items: center; margin-bottom: 24px; gap: 12px; } .skeleton-author-avatar { height: 40px; width: 40px; border-radius: 50%; } .skeleton-author-name { height: 18px; width: 130px; } .skeleton-image { height: 240px; margin-bottom: 24px; border-radius: 8px; } .skeleton-paragraph { height: 16px; margin-bottom: 12px; border-radius: 4px; } .skeleton-paragraph.short { width: 85%; } .skeleton-paragraph.medium { width: 90%; } .skeleton-paragraph.long { width: 100%; } .skeleton-paragraph.end { width: 60%; } .skeleton-subheading { height: 24px; width: 60%; margin: 24px 0 16px; } .skeleton-quote { height: 100px; margin: 24px 0; background-color: var(--secondary); border-left: 4px solid var(--accent); border-radius: 0 4px 4px 0; } .skeleton-tags { display: flex; gap: 12px; margin-top: 32px; } .skeleton-tag { height: 26px; width: 80px; border-radius: 13px; } .skeleton-related { margin-top: 40px; padding-top: 24px; border-top: 1px solid var(--border); } .skeleton-related-title { height: 24px; width: 200px; margin-bottom: 16px; } .skeleton-related-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; } .skeleton-related-item { height: 80px; border-radius: 6px; } .loaded-content { opacity: 0; transition: opacity 0.8s ease-in-out; } .loaded-content.visible { opacity: 1; } .site-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; padding-bottom: 12px; border-bottom: 1px solid var(--border); } .logo { font-weight: 800; font-size: 24px; color: var(--accent); text-decoration: none; } nav ul { display: flex; list-style: none; gap: 20px; } nav a { color: var(--text-color); text-decoration: none; font-weight: 500; transition: color 0.2s; } nav a:hover { color: var(--accent); } .article-header { margin-bottom: 24px; } .article-title { font-size: 32px; line-height: 1.2; margin-bottom: 16px; font-weight: 700; } .article-meta { display: flex; color: var(--timestamp); font-size: 14px; gap: 16px; margin-bottom: 16px; } .article-category { color: var(--accent); font-weight: 600; } .article-author { display: flex; align-items: center; gap: 12px; margin-bottom: 24px; } .author-avatar { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; } .author-name { font-weight: 600; } .article-image { width: 100%; height: auto; margin-bottom: 24px; border-radius: 8px; object-fit: cover; } .article-content p { margin-bottom: 16px; line-height: 1.6; } .article-content h2 { margin: 28px 0 16px; font-size: 22px; } .article-quote { margin: 24px 0; padding: 16px 20px; background-color: var(--secondary); border-left: 4px solid var(--accent); font-style: italic; line-height: 1.6; } .article-tags { display: flex; gap: 8px; margin-top: 32px; flex-wrap: wrap; } .article-tag { background-color: var(--secondary); padding: 6px 12px; border-radius: 20px; font-size: 13px; font-weight: 500; transition: background-color 0.2s; } .article-tag:hover { background-color: var(--border); cursor: pointer; } .related-articles { margin-top: 40px; padding-top: 24px; border-top: 1px solid var(--border); } .related-title { font-size: 18px; margin-bottom: 16px; font-weight: 600; } .related-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; } .related-item { padding: 12px; background-color: var(--secondary); border-radius: 6px; transition: transform 0.2s, box-shadow 0.2s; } .related-item:hover { transform: translateY(-3px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); cursor: pointer; } .related-item-title { font-weight: 600; font-size: 15px; line-height: 1.4; } .progress-indicator { position: fixed; top: 0; left: 0; width: 0; height: 4px; background-color: var(--accent); z-index: 100; transition: width 0.2s; } .dark-mode-toggle { cursor: pointer; background: none; border: none; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; margin-left: 20px; color: var(--text-color); } @media (max-width: 500px) { .skeleton-related-grid { grid-template-columns: 1fr; } .related-grid { grid-template-columns: 1fr; } .article-title { font-size: 26px; } .site-header { flex-direction: column; align-items: flex-start; } nav ul { margin-top: 12px; gap: 12px; } .skeleton-image { height: 180px; } } /* Dark Mode */ body.dark-mode { --loading-color: #333; --loading-highlight: #444; --text-color: #f0f0f0; --background: #121212; --secondary: #1e1e1e; --timestamp: #aaa; --border: #333; } </style> </head> <body> <div class="progress-indicator" id="progressBar"></div> <!-- Skeleton Loading State --> <div class="skeleton-container" id="skeletonContainer"> <div class="skeleton-header"> <div class="loading skeleton-title"></div> <div class="skeleton-meta"> <div class="loading skeleton-category"></div> <div class="loading skeleton-timestamp"></div> </div> <div class="skeleton-author"> <div class="loading skeleton-author-avatar"></div> <div class="loading skeleton-author-name"></div> </div> </div> <div class="loading skeleton-image"></div> <div class="loading skeleton-paragraph long"></div> <div class="loading skeleton-paragraph medium"></div> <div class="loading skeleton-paragraph long"></div> <div class="loading skeleton-paragraph short"></div> <div class="loading skeleton-subheading"></div> <div class="loading skeleton-paragraph medium"></div> <div class="loading skeleton-paragraph long"></div> <div class="loading skeleton-paragraph medium"></div> <div class="loading skeleton-quote"></div> <div class="loading skeleton-paragraph short"></div> <div class="loading skeleton-paragraph medium"></div> <div class="loading skeleton-paragraph long"></div> <div class="loading skeleton-paragraph end"></div> <div class="skeleton-tags"> <div class="loading skeleton-tag"></div> <div class="loading skeleton-tag"></div> <div class="loading skeleton-tag"></div> </div> <div class="skeleton-related"> <div class="loading skeleton-related-title"></div> <div class="skeleton-related-grid"> <div class="loading skeleton-related-item"></div> <div class="loading skeleton-related-item"></div> </div> </div> </div> <!-- Actual Content (Initially Hidden) --> <div class="loaded-content" id="loadedContent"> <header class="site-header"> <a href="#" class="logo">The Daily Chronicle</a> <div style="display: flex; align-items: center;"> <nav> <ul> <li><a href="#">Politics</a></li> <li><a href="#">Tech</a></li> <li><a href="#">Science</a></li> </ul> </nav> <button class="dark-mode-toggle" id="darkModeToggle"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path> </svg> </button> </div> </header> <article> <header class="article-header"> <h1 class="article-title">Breakthrough AI System Mimics Human Visual Reasoning</h1> <div class="article-meta"> <span class="article-category">Technology</span> <span class="article-time">Published 2 hours ago</span> </div> <div class="article-author"> <img src="https://i.pravatar.cc/80?img=11" alt="Author" class="author-avatar"> <span class="author-name">Dr. Sarah Chen</span> </div> </header> <img src="https://images.unsplash.com/photo-1677442135509-abf8613cd12c?q=80&w=3540&auto=format&fit=crop&ixlib=rb-4.0.3" alt="AI visualization" class="article-image"> <div class="article-content"> <p>Researchers at Cambridge University have unveiled a groundbreaking artificial intelligence system capable of mimicking human visual reasoning with unprecedented accuracy. The system, named VisualCortex, demonstrates an ability to interpret complex scenes and make contextual inferences that were previously only possible for humans.</p> <p>Unlike traditional computer vision models that identify objects in isolation, VisualCortex can understand spatial relationships, recognize partially obscured objects, and even make predictions about upcoming events based on visual cues—capabilities that closely mirror human cognitive processes.</p> <p>The research team, led by Professor Maya Rodriguez, spent three years developing algorithms that more closely replicate the neural pathways of the human visual cortex. "What makes this system revolutionary is that it doesn't just see pixels—it understands scenes holistically, much like humans do," explained Rodriguez.</p> <h2>Beyond Pattern Recognition</h2> <p>Current AI systems excel at pattern recognition but struggle with context-dependent reasoning. VisualCortex addresses this limitation through a novel neural architecture that simultaneously processes both object-level details and scene-wide semantics.</p> <p>In benchmark tests, the system correctly interpreted ambiguous visual scenarios with 87% accuracy—nearly matching human performance of 92%. It also demonstrated the ability to reason about physical properties, such as whether a stack of objects would remain stable or topple over.</p> <blockquote class="article-quote"> "We're crossing a threshold where AI is beginning to perceive the world in ways that mirror human perception. This isn't just about better image recognition—it's about machines that can reason visually about their environment, a fundamental aspect of true intelligence." </blockquote> <p>The implications extend far beyond academic interest. Autonomous vehicles could better predict pedestrian behavior, medical imaging systems could detect subtle anomalies that currently require specialist interpretation, and augmented reality applications could interact more naturally with physical spaces.</p> <p>However, Rodriguez cautions that VisualCortex still falls short of human visual cognition in several areas, particularly in understanding cultural context and emotional cues in visual information. "We've made a significant leap forward, but there's still considerable ground to cover," she noted.</p> <p>The team plans to release a limited API for research purposes next month, with potential commercial applications to follow pending further testing and ethical review.</p> </div> <div class="article-tags"> <span class="article-tag">Artificial Intelligence</span> <span class="article-tag">Computer Vision</span> <span class="article-tag">Neural Networks</span> <span class="article-tag">Research</span> </div> <div class="related-articles"> <h3 class="related-title">Related Articles</h3> <div class="related-grid"> <div class="related-item"> <div class="related-item-title">AI Ethics Board Proposes New Standards for Visual Recognition Systems</div> </div> <div class="related-item"> <div class="related-item-title">How Neuroscience is Informing the Next Generation of AI</div> </div> </div> </div> </article> </div> <script> // Simulate loading time and reveal content document.addEventListener('DOMContentLoaded', function() { // Simulate loading time between 1.5 and 2.5 seconds const loadTime = Math.random() * 1000 + 1500; setTimeout(function() { document.getElementById('skeletonContainer').style.display = 'none'; const content = document.getElementById('loadedContent'); content.style.display = 'block'; // Delay the opacity transition for a smoother effect setTimeout(function() { content.classList.add('visible'); }, 100); }, loadTime); // Reading progress indicator window.addEventListener('scroll', function() { const windowHeight = window.innerHeight; const documentHeight = document.documentElement.scrollHeight - windowHeight; const scrollTop = window.scrollY || document.documentElement.scrollTop; const progress = (scrollTop / documentHeight) * 100; document.getElementById('progressBar').style.width = progress + '%'; }); // Dark mode toggle const darkModeToggle = document.getElementById('darkModeToggle'); darkModeToggle.addEventListener('click', function() { document.body.classList.toggle('dark-mode'); if (document.body.classList.contains('dark-mode')) { darkModeToggle.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>'; } else { darkModeToggle.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>'; } }); // Make related articles interactive const relatedItems = document.querySelectorAll('.related-item'); relatedItems.forEach(item => { item.addEventListener('click', function() { // Simulate loading when clicking on related articles document.getElementById('loadedContent').classList.remove('visible'); setTimeout(function() { document.getElementById('loadedContent').classList.add('visible'); }, 800); }); }); // Make tags interactive const tags = document.querySelectorAll('.article-tag'); tags.forEach(tag => { tag.addEventListener('click', function() { // Simple animation to acknowledge tag click this.style.transform = 'scale(0.95)'; setTimeout(() => { this.style.transform = 'scale(1)'; }, 100); }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Analytics Dashboard Skeleton</title> <style> :root { --primary: #2c3e50; --secondary: #3498db; --accent: #e74c3c; --light: #ecf0f1; --dark: #2c3e50; --success: #2ecc71; --warning: #f39c12; --card-shadow: 0 4px 8px rgba(0, 0, 0, 0.05); --hover-shadow: 0 6px 12px rgba(0, 0, 0, 0.1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background-color: #f5f7fa; color: var(--dark); height: 700px; width: 700px; overflow-x: hidden; position: relative; } .dashboard { padding: 20px; display: grid; grid-template-columns: repeat(12, 1fr); grid-template-rows: auto; gap: 16px; height: 100%; width: 100%; overflow-y: auto; overflow-x: hidden; } .header { grid-column: span 12; display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; opacity: 0; transform: translateY(-20px); animation: fadeInDown 0.7s 0.1s forwards; } .header h1 { font-size: 1.5rem; font-weight: 600; } .date-selector { display: flex; align-items: center; gap: 10px; } .date-selector select { padding: 8px 12px; border: 1px solid #ddd; border-radius: 6px; background-color: white; cursor: pointer; transition: all 0.3s; } .date-selector select:hover { border-color: var(--secondary); box-shadow: var(--card-shadow); } .card { background: white; border-radius: 10px; padding: 20px; box-shadow: var(--card-shadow); transition: all 0.3s ease-in-out; opacity: 0; transform: translateY(20px); position: relative; overflow: hidden; } .card:hover { box-shadow: var(--hover-shadow); transform: translateY(0) scale(1.02); } .stat-card { grid-column: span 3; display: flex; flex-direction: column; justify-content: space-between; } @media (max-width: 850px) { .stat-card { grid-column: span 6; } } @media (max-width: 600px) { .stat-card { grid-column: span 12; } } .stat-title { font-size: 0.85rem; color: #7f8c8d; margin-bottom: 8px; } .stat-value { font-size: 1.8rem; font-weight: 700; margin-bottom: 10px; } .stat-change { font-size: 0.8rem; padding: 4px 8px; border-radius: 16px; width: fit-content; display: flex; align-items: center; gap: 4px; } .positive { background-color: rgba(46, 204, 113, 0.15); color: var(--success); } .negative { background-color: rgba(231, 76, 60, 0.15); color: var(--accent); } .chart-card { grid-column: span 8; display: flex; flex-direction: column; } @media (max-width: 700px) { .chart-card { grid-column: span 12; } } .chart-container { flex: 1; position: relative; min-height: 200px; } .bar-chart, .line-chart { height: 100%; width: 100%; display: flex; align-items: flex-end; justify-content: space-between; padding-top: 20px; } .chart-labels { display: flex; justify-content: space-around; margin-top: 10px; font-size: 0.8rem; color: #7f8c8d; } .bar { width: 10%; background: linear-gradient(to top, var(--secondary), #45aaf2); border-radius: 4px 4px 0 0; margin: 0 1%; position: relative; transition: height 1s cubic-bezier(0.175, 0.885, 0.32, 1.275); height: 0; } .bar:before { content: attr(data-value); position: absolute; top: -25px; left: 50%; transform: translateX(-50%); font-size: 0.75rem; font-weight: 500; opacity: 0; transition: opacity 0.3s; } .bar:hover:before { opacity: 1; } .line-plot { position: absolute; top: 0; left: 0; width: 100%; height: 100%; padding: 20px 0; } .line { position: absolute; height: 3px; background-color: var(--secondary); transform-origin: left center; transform: scaleX(0); transition: transform 1s ease-out; } .dot { width: 10px; height: 10px; border-radius: 50%; background-color: var(--secondary); border: 2px solid white; position: absolute; transform: scale(0); transition: transform 0.3s ease-out; z-index: 2; } .line-dot-container { position: absolute; width: 100%; height: 100%; } .data-grid { grid-column: span 4; overflow: hidden; } @media (max-width: 700px) { .data-grid { grid-column: span 12; } } .data-row { display: flex; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid #ecf0f1; transition: all 0.3s; opacity: 0; transform: translateX(20px); } .data-row:hover { background-color: #f8f9fa; } .data-row:last-child { border-bottom: none; } .data-label { font-weight: 500; font-size: 0.85rem; } .data-value { font-weight: 600; font-size: 0.85rem; } .doughnut-chart { grid-column: span 6; display: flex; flex-direction: column; } @media (max-width: 700px) { .doughnut-chart { grid-column: span 12; } } .doughnut-container { position: relative; flex: 1; display: flex; justify-content: center; align-items: center; } .doughnut { width: 150px; height: 150px; position: relative; border-radius: 50%; } .segment { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border-radius: 50%; clip-path: polygon(50% 50%, 100% 0, 100% 100%); transform-origin: center; opacity: 0; transition: opacity 0.6s ease-out; } .doughnut-center { position: absolute; width: 80px; height: 80px; background: white; border-radius: 50%; top: 50%; left: 50%; transform: translate(-50%, -50%); display: flex; align-items: center; justify-content: center; flex-direction: column; z-index: 10; } .center-value { font-size: 1.3rem; font-weight: 700; } .center-label { font-size: 0.7rem; color: #7f8c8d; } .legend { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin-top: 15px; } .legend-item { display: flex; align-items: center; gap: 5px; font-size: 0.8rem; } .legend-color { width: 12px; height: 12px; border-radius: 2px; } .map-card { grid-column: span 6; min-height: 280px; } @media (max-width: 700px) { .map-card { grid-column: span 12; } } .map-container { position: relative; height: 100%; overflow: hidden; margin-top: 10px; } .world-map { background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODAwIiBoZWlnaHQ9IjUwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTIzLjQ1LDEyOS43NGwtNC4xNiwxLjc1bC0xNC43OSw0LjE3bC0xMy4wNCwtNC4xN2wtMTAuNDEsLTEuNzVsLTEyLjE2LDEuNzVsLTEuNzUsNS4yNWwxLjc1LDEzLjA0bC01LjI1LDEwLjQxYzAsMCAtNS4yNSw1LjI1IC03Ljg3LDUuMjVjLTIuNjIsMCAtNy44OCwxLjc1IC03Ljg4LDEuNzVsLTMuNSw1LjI1bDMuNSw0LjE3bDMuNSwxNi41NGwtMy41LDEwLjQyYzAsMCAwLDguNzUgLTAuODcsMTAuNGMtMC44OCwxLjY3IC0xLjc1LDcuODkgLTEuNzUsNy44OWwtMi42Myw0LjE3bDIuNjMsMi42MmwwLDkuNjJsLTYuMTMsNC4xN2wtMi42MiwyLjYybDIuNjIsOC43NWwtNi4xMyw2LjEzbDAsNS4yNWwtNi4xMiw3Ljg3bC0zLjUsMy41bDMuNSw3Ljg4YzAsMCAzLjUsMCAxMC41LDBjNywwIDEwLjUsLTIuNjMgMTUuNzUsLTIuNjNjNS4yNSwwIDUuMjUsLTMuNSA4Ljc1LC0zLjVjMy41LDAgMTEuMzcsLTEwLjUgMTEuMzcsLTEwLjVsMS43NSwtNS4yNWw1LjI1LC0zLjVsOC43NSwwbDQuMzgsMy41bDQuMzcsLS44N2wtNC4zNywtNy44OGwxLjc1LC04Ljc1bC0xLjc1LC0yLjYybDAuODgsLTcuODhsLTIuNjMsLTcuODdsMCwtNy44OGM4Ljc1LDAgMTMuMTMsMCAxMy4xMywwbDYuMTIsLTYuMTJsNC4zOCwwbDQuMzcsLTMuNWwxNy41LC0zLjVsMTAuNSw0LjM3bDExLjM4LC01LjI1bDAsLTUuMjVsLTE2LjYzLC0yLjYybC03Ljg3LC02LjEzbC03Ljg4LDBsLTMuNSwtNC4zN2wtMTAuNSwwbC03Ljg3LC02LjEzbC00LjM3LC03Ljg3bDAsLTMuNWwtMy41LC02LjEybDMuNSwtMS43NWw4Ljc1LDBsMi42MywtNi4xM2w4Ljc1LC00LjM3TDEyMy40NSwxMjkuNzR6IiBzdHJva2U9IiNjY2NjY2MiIHN0cm9rZS13aWR0aD0iMC41IiBmaWxsPSIjZWVlZWVlIi8+PHBhdGggZD0iTTQ4Mi45NSwxMzIuMzZsLTkuNjIsLTQuMzdsLTEzLjEzLC0xLjc1bC05LjYyLDEuNzVsLTEyLjI1LC0xLjc1bC0xMy4xMywzLjVsLTEyLjI1LDBsLTIyLjc1LC03Ljg3bC0xNC44NywtMy41bC0xMC41LDEuNzVsLTguNzUsNi4xMmwtOC43NSw2LjEzbDEuNzUsNi4xMmwwLDYuMTNsLTMuNSw0LjM3bDQxLjEyLDE5LjI1bDYuMTMsMTAuNWw3Ljg3LDUuMjVsNS4yNSwxMC41bDMuNSw2LjEybDUuMjUsMy41bDYuMTMsOC43NWwxMC41LDguNzVsMTQuODcsNC4zOGwxMC41LDkuNjJsMTIuMjUsLTEuNzVsNi4xMiwtNC4zN2wtNC4zNywtNC4zN2w3Ljg3LC0zLjVsLTEuNzUsLTMuNWw1LjI1LC0yLjYybDAsLTMuNWwtNC4zNywtMS43NWwtMS43NSwtNS4yNWwzLjUsLTMuNWw2LjEyLDBsLTEuNzUsLTExLjM3bC0xLjc1LC00LjM4bC02LjEyLC01LjI1bDQuMzcsLTQuMzdsLTEuNzUsLTQuMzdsLTkuNjIsLTMuNWwtNC4zOCwxLjc1bC0xLjc1LC04Ljc1bDkuNjMsLTQuMzdsLTEuNzUsLTcuODdsMCwtNi4xM2wxMC41LC0xLjc1TDQ4Mi45NSwxMzIuMzZ6IiBzdHJva2U9IiNjY2NjY2MiIHN0cm9rZS13aWR0aD0iMC41IiBmaWxsPSIjZWVlZWVlIi8+PHBhdGggZD0iTTMzNC40NSwxMjMuNjFsNC4zOCwtNS4yNWwyMi43NSwtNC4zN2wxMC41LDQuMzdsOC43NSwtMS43NWwxMC41LC05LjYybDIuNjIsLTkuNjNsLTYuMTIsLTMuNWwtMTIuMjUsMi42M2wtOC43NSw2LjEybC0xNy41LDQuMzdsLTIyLjc1LC0xLjc1bC0xNy41LDMuNWwtOS42MiwxMC41bC02LjEzLDBsMy41LDQuMzdsLTMuNSwxLjc1bDAsNC4zN2w3Ljg3LDIuNjNsMTIuMjUsMGwxMi4yNSwtNC4zOEwzMzQuNDUsMTIzLjYxeiIgc3Ryb2tlPSIjY2NjY2NjIiBzdHJva2Utd2lkdGg9IjAuNSIgZmlsbD0iI2VlZWVlZSIvPjxjaXJjbGUgY3g9IjIwMCIgY3k9IjE4MCIgcj0iMTUiIGZpbGw9InJnYmEoMjM0LCA4NSwgMjAsIDAuNykiIGZpbGwtb3BhY2l0eT0iMC43Ii8+PGNpcmNsZSBjeD0iMzUwIiBjeT0iMTIwIiByPSIxMyIgZmlsbD0icmdiYSgyMzQsIDg1LCAyMCwgMC43KSIgZmlsbC1vcGFjaXR5PSIwLjciLz48Y2lyY2xlIGN4PSI0MjAiIGN5PSIxNzAiIHI9IjE4IiBmaWxsPSJyZ2JhKDIzNCwgODUsIDIwLCAwLjcpIiBmaWxsLW9wYWNpdHk9IjAuNyIvPjwvc3ZnPg=='); background-size: cover; background-position: center; height: calc(100% - 20px); width: 100%; opacity: 0; transform: scale(0.95); transition: all 1s ease-out; } .map-point { position: absolute; width: 12px; height: 12px; border-radius: 50%; background-color: var(--accent); transform: scale(0); transition: transform 0.3s ease-out; cursor: pointer; z-index: 2; } .map-point:after { content: ''; position: absolute; width: 30px; height: 30px; border-radius: 50%; background-color: rgba(231, 76, 60, 0.3); top: 50%; left: 50%; transform: translate(-50%, -50%); animation: pulse 2s infinite; } .map-tooltip { position: absolute; background-color: white; padding: 8px 12px; border-radius: 4px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); font-size: 0.8rem; white-space: nowrap; opacity: 0; transition: opacity 0.3s; pointer-events: none; z-index: 10; } .loading-skeleton { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, #f0f0f0 25%, #f8f8f8 50%, #f0f0f0 75%); background-size: 200% 100%; animation: loading 1.5s infinite; border-radius: 8px; } @keyframes fadeInDown { from { opacity: 0; transform: translateY(-20px); } to { opacity: 1; transform: translateY(0); } } @keyframes pulse { 0% { transform: translate(-50%, -50%) scale(0.5); opacity: 1; } 100% { transform: translate(-50%, -50%) scale(1.5); opacity: 0; } } @keyframes loading { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } .tab-container { display: flex; margin-bottom: 10px; } .tab { padding: 8px 16px; background-color: #f5f7fa; border-radius: 6px; font-size: 0.85rem; font-weight: 500; cursor: pointer; margin-right: 8px; transition: all 0.2s; } .tab.active { background-color: var(--secondary); color: white; } .tab:hover:not(.active) { background-color: #e0e6ed; } .card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; } .card-title { font-size: 1rem; font-weight: 600; } .card-options { display: flex; gap: 5px; } .option-button { width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; border-radius: 4px; background-color: #f5f7fa; cursor: pointer; transition: all 0.2s; } .option-button:hover { background-color: #e0e6ed; } .option-button svg { width: 16px; height: 16px; color: #7f8c8d; } </style> </head> <body> <div class="dashboard"> <div class="header"> <h1>Performance Analytics</h1> <div class="date-selector"> <select id="timeRange"> <option value="day">Last 24 hours</option> <option value="week" selected>Last 7 days</option> <option value="month">Last 30 days</option> <option value="quarter">Last quarter</option> </select> </div> </div> <div class="card stat-card"> <div class="loading-skeleton"></div> <div class="stat-title">Active Users</div> <div class="stat-value">12,493</div> <div class="stat-change positive"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="18 15 12 9 6 15"></polyline> </svg> 8.2% vs previous </div> </div> <div class="card stat-card"> <div class="loading-skeleton"></div> <div class="stat-title">Conversion Rate</div> <div class="stat-value">3.8%</div> <div class="stat-change positive"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="18 15 12 9 6 15"></polyline> </svg> 2.1% vs previous </div> </div> <div class="card stat-card"> <div class="loading-skeleton"></div> <div class="stat-title">Average Order Value</div> <div class="stat-value">$147.36</div> <div class="stat-change negative"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="6 9 12 15 18 9"></polyline> </svg> 3.4% vs previous </div> </div> <div class="card stat-card"> <div class="loading-skeleton"></div> <div class="stat-title">Revenue</div> <div class="stat-value">$285,642</div> <div class="stat-change positive"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="18 15 12 9 6 15"></polyline> </svg> 12.8% vs previous </div> </div> <div class="card chart-card"> <div class="loading-skeleton"></div> <div class="card-header"> <div class="card-title">Revenue Trends</div> <div class="tab-container"> <div class="tab active" data-chart="revenue">Revenue</div> <div class="tab" data-chart="orders">Orders</div> </div> </div> <div class="chart-container"> <div class="bar-chart" id="revenueChart"> <div class="bar" data-value="$32.4k" style="height: 0%"></div> <div class="bar" data-value="$36.8k" style="height: 0%"></div> <div class="bar" data-value="$42.1k" style="height: 0%"></div> <div class="bar" data-value="$39.5k" style="height: 0%"></div> <div class="bar" data-value="$46.3k" style="height: 0%"></div> <div class="bar" data-value="$51.2k" style="height: 0%"></div> <div class="bar" data-value="$37.4k" style="height: 0%"></div> </div> <div class="line-dot-container"> <div class="line" style="width: 14.3%; left: 7.1%; top: 60%;"></div> <div class="line" style="width: 14.3%; left: 21.4%; top: 52%; transform: rotate(-15deg);"></div> <div class="line" style="width: 14.3%; left: 35.7%; top: 40%; transform: rotate(8deg);"></div> <div class="line" style="width: 14.3%; left: 50%; top: 45%; transform: rotate(-18deg);"></div> <div class="line" style="width: 14.3%; left: 64.3%; top: 32%; transform: rotate(5deg);"></div> <div class="line" style="width: 14.3%; left: 78.6%; top: 25%; transform: rotate(30deg);"></div> <div class="dot" style="left: 7.1%; top: 60%;"></div> <div class="dot" style="left: 21.4%; top: 52%;"></div> <div class="dot" style="left: 35.7%; top: 40%;"></div> <div class="dot" style="left: 50%; top: 45%;"></div> <div class="dot" style="left: 64.3%; top: 32%;"></div> <div class="dot" style="left: 78.6%; top: 25%;"></div> <div class="dot" style="left: 92.9%; top: 58%;"></div> </div> </div> <div class="chart-labels"> <div>Mon</div> <div>Tue</div> <div>Wed</div> <div>Thu</div> <div>Fri</div> <div>Sat</div> <div>Sun</div> </div> </div> <div class="card data-grid"> <div class="loading-skeleton"></div> <div class="card-header"> <div class="card-title">Top Products</div> <div class="card-options"> <div class="option-button"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect> <line x1="16" y1="2" x2="16" y2="6"></line> <line x1="8" y1="2" x2="8" y2="6"></line> <line x1="3" y1="10" x2="21" y2="10"></line> </svg> </div> <div class="option-button"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="1"></circle> <circle cx="12" cy="5" r="1"></circle> <circle cx="12" cy="19" r="1"></circle> </svg> </div> </div> </div> <div class="data-row"> <div class="data-label">SmartTrack Pro</div> <div class="data-value">$18,425</div> </div> <div class="data-row"> <div class="data-label">DataSync Suite</div> <div class="data-value">$12,849</div> </div> <div class="data-row"> <div class="data-label">MetricFlow Lite</div> <div class="data-value">$9,582</div> </div> <div class="data-row"> <div class="data-label">InsightEdge API</div> <div class="data-value">$7,463</div> </div> <div class="data-row"> <div class="data-label">VizPro Enterprise</div> <div class="data-value">$6,258</div> </div> </div> <div class="card doughnut-chart"> <div class="loading-skeleton"></div> <div class="card-header"> <div class="card-title">Traffic Sources</div> <div class="card-options"> <div class="option-button"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="6 9 12 15 18 9"></polyline> </svg> </div> </div> </div> <div class="doughnut-container"> <div class="doughnut"> <div class="segment" style="background-color: #3498db; transform: rotate(0deg);"></div> <div class="segment" style="background-color: #e74c3c; transform: rotate(144deg);"></div> <div class="segment" style="background-color: #2ecc71; transform: rotate(216deg);"></div> <div class="segment" style="background-color: #f39c12; transform: rotate(288deg);"></div> <div class="doughnut-center"> <div class="center-value">268k</div> <div class="center-label">Total Visits</div> </div> </div> </div> <div class="legend"> <div class="legend-item"> <div class="legend-color" style="background-color: #3498db;"></div> <span>Direct (40%)</span> </div> <div class="legend-item"> <div class="legend-color" style="background-color: #e74c3c;"></div> <span>Organic (20%)</span> </div> <div class="legend-item"> <div class="legend-color" style="background-color: #2ecc71;"></div> <span>Referral (20%)</span> </div> <div class="legend-item"> <div class="legend-color" style="background-color: #f39c12;"></div> <span>Social (20%)</span> </div> </div> </div> <div class="card map-card"> <div class="loading-skeleton"></div> <div class="card-header"> <div class="card-title">Active Markets</div> <div class="card-options"> <div class="option-button"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="11" cy="11" r="8"></circle> <line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> </div> </div> </div> <div class="map-container"> <div class="world-map"></div> <div class="map-point" style="top: 35%; left: 22%;" data-tooltip="North America: 42,382 users"></div> <div class="map-point" style="top: 30%; left: 48%;" data-tooltip="Europe: 36,940 users"></div> <div class="map-point" style="top: 45%; left: 75%;" data-tooltip="Asia: 31,852 users"></div> <div class="map-tooltip"></div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const cards = document.querySelectorAll('.card'); // Remove loading skeletons in sequence setTimeout(() => { cards.forEach((card, index) => { setTimeout(() => { const skeleton = card.querySelector('.loading-skeleton'); if (skeleton) { skeleton.style.opacity = '0'; setTimeout(() => { skeleton.remove(); // Special animations for specific components if (card.classList.contains('chart-card')) { animateChart(); } else if (card.classList.contains('doughnut-chart')) { animateDoughnut(); } else if (card.classList.contains('map-card')) { animateMap(); } else if (card.classList.contains('data-grid')) { animateDataGrid(); } else { // General card animation card.style
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Mobile App Onboarding</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { display: flex; justify-content: center; align-items: center; min-height: 700px; overflow: hidden; background-color: #f5f5f7; } .phone-container { position: relative; width: 300px; height: 600px; background: linear-gradient(135deg, #ffffff, #f7f7f7); border-radius: 30px; overflow: hidden; box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1), 0 3px 10px rgba(0, 0, 0, 0.05); transition: transform 0.5s ease; } .phone-container:hover { transform: scale(1.02); } .onboarding-container { position: relative; width: 100%; height: 100%; overflow: hidden; } .status-bar { display: flex; justify-content: space-between; padding: 12px 16px; background: linear-gradient(to right, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.7)); backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px); position: absolute; top: 0; left: 0; width: 100%; z-index: 10; } .time { font-weight: 600; font-size: 14px; color: #333; } .icons { display: flex; gap: 8px; } .icons div { width: 16px; height: 16px; background-color: #333; border-radius: 2px; } .slide { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; flex-direction: column; align-items: center; padding: 80px 20px 40px; transition: transform 0.6s cubic-bezier(0.44, 0.185, 0.575, 0.86), opacity 0.6s ease; opacity: 0; transform: translateX(100%); } .slide.active { opacity: 1; transform: translateX(0); } .slide.prev { transform: translateX(-100%); } .profile-image { width: 150px; height: 150px; border-radius: 50%; margin-bottom: 40px; position: relative; overflow: hidden; box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1); } .profile-image::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient( 45deg, rgba(128, 103, 255, 0.7), rgba(68, 147, 246, 0.7), rgba(245, 124, 195, 0.7) ); animation: gradientRotate 10s infinite alternate; opacity: 0.8; } @keyframes gradientRotate { 0% { filter: hue-rotate(0deg); } 100% { filter: hue-rotate(360deg); } } .profile-image i { position: relative; z-index: 2; font-size: 60px; color: white; display: flex; justify-content: center; align-items: center; height: 100%; } .slide-title { font-size: 24px; font-weight: 700; margin-bottom: 16px; color: #333; text-align: center; opacity: 0; transform: translateY(20px); transition: opacity 0.6s ease 0.2s, transform 0.6s ease 0.2s; } .slide.active .slide-title { opacity: 1; transform: translateY(0); } .slide-description { font-size: 15px; color: #666; text-align: center; margin-bottom: 40px; line-height: 1.6; opacity: 0; transform: translateY(20px); transition: opacity 0.6s ease 0.4s, transform 0.6s ease 0.4s; } .slide.active .slide-description { opacity: 1; transform: translateY(0); } .input-container { width: 100%; margin-bottom: 16px; opacity: 0; transform: translateY(20px); transition: opacity 0.6s ease 0.6s, transform 0.6s ease 0.6s; } .slide.active .input-container { opacity: 1; transform: translateY(0); } .input-field { width: 100%; padding: 16px; border-radius: 12px; border: 2px solid #e0e0e0; background-color: rgba(255, 255, 255, 0.8); font-size: 15px; transition: border-color 0.3s, box-shadow 0.3s; } .input-field:focus { outline: none; border-color: #8067ff; box-shadow: 0 0 0 3px rgba(128, 103, 255, 0.2); } .button-container { width: 100%; display: flex; justify-content: center; margin-top: 20px; opacity: 0; transform: translateY(20px); transition: opacity 0.6s ease 0.8s, transform 0.6s ease 0.8s; } .slide.active .button-container { opacity: 1; transform: translateY(0); } .button { padding: 16px 40px; border-radius: 30px; background: linear-gradient(to right, #8067ff, #4493f6); color: white; font-weight: 600; font-size: 16px; border: none; cursor: pointer; box-shadow: 0 4px 15px rgba(128, 103, 255, 0.4); transition: transform 0.3s, box-shadow 0.3s; position: relative; overflow: hidden; } .button:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(128, 103, 255, 0.5); } .button:active { transform: translateY(1px); box-shadow: 0 2px 10px rgba(128, 103, 255, 0.4); } .button::after { content: ''; position: absolute; top: 50%; left: 50%; width: 5px; height: 5px; background: rgba(255, 255, 255, 0.8); opacity: 0; border-radius: 100%; transform: scale(1) translate(-50%, -50%); transform-origin: 0 0; } .button:focus:not(:active)::after { animation: ripple 1s ease-out; } @keyframes ripple { 0% { transform: scale(0) translate(-50%, -50%); opacity: 1; } 100% { transform: scale(50) translate(-50%, -50%); opacity: 0; } } .progress-container { display: flex; justify-content: center; position: absolute; bottom: 30px; left: 0; width: 100%; } .progress-dot { width: 8px; height: 8px; border-radius: 50%; background-color: #e0e0e0; margin: 0 6px; transition: transform 0.3s, background-color 0.3s; } .progress-dot.active { background-color: #8067ff; transform: scale(1.5); } .skip-button { position: absolute; top: 70px; right: 20px; background: none; border: none; color: #8067ff; font-weight: 500; font-size: 14px; cursor: pointer; opacity: 0.8; transition: opacity 0.3s; } .skip-button:hover { opacity: 1; } .feature-list { width: 100%; margin-bottom: 30px; } .feature-item { display: flex; align-items: center; margin-bottom: 16px; padding: 12px; background-color: rgba(255, 255, 255, 0.8); border-radius: 12px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); opacity: 0; transform: translateX(30px); transition: opacity 0.4s, transform 0.4s; } .slide.active .feature-item:nth-child(1) { transition-delay: 0.4s; } .slide.active .feature-item:nth-child(2) { transition-delay: 0.6s; } .slide.active .feature-item:nth-child(3) { transition-delay: 0.8s; } .slide.active .feature-item { opacity: 1; transform: translateX(0); } .feature-icon { width: 40px; height: 40px; border-radius: 10px; background: linear-gradient(135deg, #8067ff, #4493f6); display: flex; justify-content: center; align-items: center; margin-right: 12px; color: white; font-size: 18px; } .feature-text { flex: 1; } .feature-title { font-weight: 600; font-size: 14px; color: #333; margin-bottom: 2px; } .feature-desc { font-size: 12px; color: #666; } .preference-item { display: flex; align-items: center; justify-content: space-between; width: 100%; padding: 12px; background-color: rgba(255, 255, 255, 0.8); border-radius: 12px; margin-bottom: 12px; opacity: 0; transform: translateY(20px); transition: opacity 0.5s, transform 0.5s; } .slide.active .preference-item:nth-child(1) { transition-delay: 0.4s; } .slide.active .preference-item:nth-child(2) { transition-delay: 0.6s; } .slide.active .preference-item:nth-child(3) { transition-delay: 0.8s; } .slide.active .preference-item { opacity: 1; transform: translateY(0); } .preference-label { font-weight: 500; font-size: 14px; color: #333; } .toggle { position: relative; width: 50px; height: 26px; border-radius: 30px; background-color: #e0e0e0; cursor: pointer; transition: background-color 0.3s; } .toggle.active { background-color: #8067ff; } .toggle::after { content: ''; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%; background-color: white; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); transition: transform 0.3s; } .toggle.active::after { transform: translateX(24px); } .success-icon { font-size: 60px; color: #4CAF50; margin-bottom: 20px; animation: scaleIn 0.5s ease forwards; transform: scale(0); } @keyframes scaleIn { 0% { transform: scale(0); } 70% { transform: scale(1.2); } 100% { transform: scale(1); } } .emoji-container { display: flex; justify-content: center; gap: 12px; margin: 20px 0; width: 100%; } .emoji { width: 50px; height: 50px; border-radius: 50%; background: linear-gradient(to bottom, #f7f7f7, #e0e0e0); display: flex; justify-content: center; align-items: center; font-size: 24px; box-shadow: 0 3px 8px rgba(0, 0, 0, 0.1); cursor: pointer; transition: transform 0.3s, box-shadow 0.3s; user-select: none; } .emoji:hover { transform: translateY(-3px); box-shadow: 0 5px 12px rgba(0, 0, 0, 0.15); } .emoji.selected { background: linear-gradient(to bottom, #8067ff, #4493f6); transform: scale(1.1); color: white; } @media (max-width: 500px) { .phone-container { width: 280px; height: 570px; } .slide-title { font-size: 22px; } .slide-description { font-size: 14px; } } </style> </head> <body> <div class="phone-container"> <div class="status-bar"> <div class="time">11:42</div> <div class="icons"> <div class="signal"></div> <div class="wifi"></div> <div class="battery"></div> </div> </div> <div class="onboarding-container"> <button class="skip-button">Skip</button> <div class="slide active"> <div class="profile-image"> <i class="fas">👋</i> </div> <h2 class="slide-title">Welcome to Sojourn</h2> <p class="slide-description">Your personal travel companion that helps you discover hidden gems and plan memorable journeys with ease.</p> <div class="button-container"> <button class="button next-button">Get Started</button> </div> </div> <div class="slide"> <div class="profile-image"> <i class="fas">🌟</i> </div> <h2 class="slide-title">Discover & Explore</h2> <p class="slide-description">See what makes Sojourn different from other travel planning apps.</p> <div class="feature-list"> <div class="feature-item"> <div class="feature-icon">🗺️</div> <div class="feature-text"> <div class="feature-title">Interactive Maps</div> <div class="feature-desc">Explore destinations with offline-capable maps</div> </div> </div> <div class="feature-item"> <div class="feature-icon">💬</div> <div class="feature-text"> <div class="feature-title">Local Insights</div> <div class="feature-desc">Authentic recommendations from locals</div> </div> </div> <div class="feature-item"> <div class="feature-icon">⚡</div> <div class="feature-text"> <div class="feature-title">Smart Itineraries</div> <div class="feature-desc">AI-powered planning that adapts to your style</div> </div> </div> </div> <div class="button-container"> <button class="button next-button">Next</button> </div> </div> <div class="slide"> <div class="profile-image"> <i class="fas">🔍</i> </div> <h2 class="slide-title">Tell Us About Yourself</h2> <p class="slide-description">Help us personalize your experience.</p> <div class="input-container"> <input type="text" class="input-field" placeholder="Your name"> </div> <div class="input-container"> <input type="email" class="input-field" placeholder="Email address"> </div> <div class="button-container"> <button class="button next-button">Continue</button> </div> </div> <div class="slide"> <div class="profile-image"> <i class="fas">⚙️</i> </div> <h2 class="slide-title">Customize Your Experience</h2> <p class="slide-description">Set your preferences for a tailored journey.</p> <div class="preference-item"> <div class="preference-label">Push Notifications</div> <div class="toggle"></div> </div> <div class="preference-item"> <div class="preference-label">Location Services</div> <div class="toggle active"></div> </div> <div class="preference-item"> <div class="preference-label">Personalized Recommendations</div> <div class="toggle active"></div> </div> <div class="button-container"> <button class="button next-button">Next</button> </div> </div> <div class="slide"> <div class="profile-image"> <i class="fas">😊</i> </div> <h2 class="slide-title">Travel Style</h2> <p class="slide-description">What kind of traveler are you?</p> <div class="emoji-container"> <div class="emoji" data-value="adventurer">🏔️</div> <div class="emoji" data-value="relaxer">🏖️</div> <div class="emoji" data-value="foodie">🍽️</div> <div class="emoji" data-value="cultural">🏛️</div> </div> <div class="button-container"> <button class="button next-button">Complete Setup</button> </div> </div> <div class="slide"> <div class="success-icon">✓</div> <h2 class="slide-title">You're All Set!</h2> <p class="slide-description">Your journey with Sojourn begins now. Explore destinations, create memories, and travel like never before.</p> <div class="button-container"> <button class="button">Start Exploring</button> </div> </div> <div class="progress-container"> <div class="progress-dot active"></div> <div class="progress-dot"></div> <div class="progress-dot"></div> <div class="progress-dot"></div> <div class="progress-dot"></div> <div class="progress-dot"></div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const slides = document.querySelectorAll('.slide'); const dots = document.querySelectorAll('.progress-dot'); const nextButtons = document.querySelectorAll('.next-button'); const skipButton = document.querySelector('.skip-button'); const toggles = document.querySelectorAll('.toggle'); const emojis = document.querySelectorAll('.emoji'); let currentSlide = 0; // Initialize slides updateSlides(); // Add event listeners to next buttons nextButtons.forEach(button => { button.addEventListener('click', nextSlide); }); // Skip to last slide skipButton.addEventListener('click', () => { currentSlide = slides.length - 1; updateSlides(); }); // Toggle switch functionality toggles.forEach(toggle => { toggle.addEventListener('click', function() { this.classList.toggle('active'); }); }); // Emoji selection emojis.forEach(emoji => { emoji.addEventListener('click', function() { // Remove selected class from all emojis emojis.forEach(e => e.classList.remove('selected')); // Add selected class to clicked emoji this.classList.add('selected'); }); }); function nextSlide() { if (currentSlide < slides.length - 1) { currentSlide++; updateSlides(); } } function updateSlides() { slides.forEach((slide, index) => { if (index < currentSlide) { slide.className = 'slide prev'; } else if (index === currentSlide) { slide.className = 'slide active'; } else { slide.className = 'slide'; } }); dots.forEach((dot, index) => { if (index === currentSlide) { dot.classList.add('active'); } else { dot.classList.remove('active'); } }); // Hide skip button on last slide if (currentSlide === slides.length - 1) { skipButton.style.display = 'none'; } else { skipButton.style.display = 'block'; } } // Prevent form submission behavior document.querySelectorAll('.input-field').forEach(input => { input.addEventListener('keypress', function(e) { if (e.key === 'Enter') { e.preventDefault(); nextSlide(); } }); }); // Add ripple effect to buttons const buttons = document.querySelectorAll('.button'); buttons.forEach(button => { button.addEventListener('mousedown', function(e) { const rect = button.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; const ripple = document.createElement('span'); ripple.style.position = 'absolute'; ripple.style.width = '1px'; ripple.style.height = '1px'; ripple.style.borderRadius = '50%'; ripple.style.backgroundColor = 'rgba(255, 255, 255, 0.7)'; ripple.style.transform = 'scale(0)'; ripple.style.left = x + 'px'; ripple.style.top = y + 'px'; ripple.style.animation = 'ripple-effect 0.6s linear'; button.appendChild(ripple); setTimeout(() => { ripple.remove(); }, 600); }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Video Streaming Thumbnail Skeletons</title> <style> :root { --background: #121212; --card-bg: #1e1e1e; --skeleton-base: #2a2a2a; --skeleton-highlight: #3a3a3a; --accent: #ff4d4d; --accent-2: #3b82f6; --text: #e0e0e0; --text-secondary: #a0a0a0; } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', sans-serif; background-color: var(--background); color: var(--text); min-height: 100vh; display: flex; flex-direction: column; padding: 1.5rem; max-width: 700px; margin: 0 auto; } .container { width: 100%; max-width: 700px; margin: 0 auto; } header { margin-bottom: 1.5rem; } h1 { font-size: 1.5rem; margin-bottom: 0.5rem; font-weight: 700; background: linear-gradient(90deg, var(--accent), var(--accent-2)); -webkit-background-clip: text; background-clip: text; color: transparent; } .subtitle { color: var(--text-secondary); font-size: 0.9rem; line-height: 1.5; } .categories { display: flex; gap: 0.75rem; margin: 1.25rem 0; flex-wrap: wrap; } .category { padding: 0.5rem 1rem; background-color: rgba(255, 255, 255, 0.05); border-radius: 50px; font-size: 0.8rem; cursor: pointer; transition: all 0.2s ease; border: 1px solid transparent; } .category:hover, .category.active { background-color: rgba(255, 77, 77, 0.1); border-color: var(--accent); color: var(--accent); } .category.active { background-color: rgba(255, 77, 77, 0.2); } .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1.25rem; } .skeleton-video { position: relative; background-color: var(--card-bg); border-radius: 0.75rem; overflow: hidden; height: 100%; transition: transform 0.3s ease, box-shadow 0.3s ease; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } .skeleton-video:hover { transform: translateY(-5px); box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2); } .skeleton-thumbnail { position: relative; width: 100%; padding-top: 56.25%; /* 16:9 aspect ratio */ background-color: var(--skeleton-base); overflow: hidden; border-radius: 0.75rem 0.75rem 0 0; } .skeleton-thumbnail::before { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, var(--skeleton-base) 0%, var(--skeleton-highlight) 50%, var(--skeleton-base) 100%); background-size: 200% 100%; animation: shimmer 2s infinite; } .skeleton-play-icon { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 40px; height: 40px; border-radius: 50%; background-color: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center; opacity: 0.7; } .skeleton-play-icon::before { content: ""; border-style: solid; border-width: 8px 0 8px 12px; border-color: transparent transparent transparent var(--text); margin-left: 3px; } .skeleton-duration { position: absolute; bottom: 10px; right: 10px; background-color: rgba(0, 0, 0, 0.7); padding: 0.25rem 0.5rem; border-radius: 4px; font-size: 0.7rem; color: var(--text); } .skeleton-progress { position: absolute; bottom: 0; left: 0; height: 3px; width: 0; background: linear-gradient(90deg, var(--accent), var(--accent-2)); animation: progress 3s ease-in-out infinite; } .skeleton-details { padding: 1rem; } .skeleton-title { height: 14px; width: 90%; background-color: var(--skeleton-base); border-radius: 4px; margin-bottom: 0.75rem; position: relative; overflow: hidden; } .skeleton-title::before { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, var(--skeleton-base) 0%, var(--skeleton-highlight) 50%, var(--skeleton-base) 100%); background-size: 200% 100%; animation: shimmer 2s infinite; } .skeleton-channel { height: 10px; width: 60%; background-color: var(--skeleton-base); border-radius: 4px; margin-bottom: 0.5rem; position: relative; overflow: hidden; } .skeleton-channel::before { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, var(--skeleton-base) 0%, var(--skeleton-highlight) 50%, var(--skeleton-base) 100%); background-size: 200% 100%; animation: shimmer 2s infinite; animation-delay: 0.1s; } .skeleton-meta { height: 8px; width: 75%; background-color: var(--skeleton-base); border-radius: 4px; position: relative; overflow: hidden; } .skeleton-meta::before { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, var(--skeleton-base) 0%, var(--skeleton-highlight) 50%, var(--skeleton-base) 100%); background-size: 200% 100%; animation: shimmer 2s infinite; animation-delay: 0.2s; } .controls { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; } .toggle-container { display: flex; align-items: center; gap: 0.5rem; } .toggle-label { font-size: 0.85rem; color: var(--text-secondary); } .toggle { position: relative; width: 48px; height: 24px; } .toggle input { opacity: 0; width: 0; height: 0; } .toggle-slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: var(--skeleton-base); transition: .4s; border-radius: 34px; } .toggle-slider:before { position: absolute; content: ""; height: 18px; width: 18px; left: 3px; bottom: 3px; background-color: var(--text); transition: .4s; border-radius: 50%; } input:checked + .toggle-slider { background-color: var(--accent); } input:checked + .toggle-slider:before { transform: translateX(24px); } .loader-options { display: flex; gap: 0.75rem; } .loader-option { padding: 0.5rem; background-color: var(--card-bg); border-radius: 4px; border: 1px solid var(--skeleton-base); cursor: pointer; transition: all 0.2s ease; } .loader-option:hover, .loader-option.active { border-color: var(--accent); } .loader-option.active { background-color: rgba(255, 77, 77, 0.1); } /* Animations */ @keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } @keyframes progress { 0% { width: 0%; } 50% { width: 75%; } 75% { width: 85%; } 90% { width: 90%; } 100% { width: 100%; } } /* Responsive adjustments */ @media (max-width: 600px) { .grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 1rem; } .controls { flex-direction: column; align-items: flex-start; gap: 1rem; } .loader-options { width: 100%; justify-content: space-between; } } .showing-count { font-size: 0.85rem; color: var(--text-secondary); margin-top: 1.5rem; } /* Loading animation for newly added videos */ .skeleton-video.new-item { animation: fadeInUp 0.5s ease forwards; } @keyframes fadeInUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } </style> </head> <body> <div class="container"> <header> <h1>StreamPrep Skeletons</h1> <p class="subtitle">Customizable thumbnail loaders while your high-definition content buffers. Design your loading experience to match your streaming platform's aesthetics.</p> </header> <div class="controls"> <div class="toggle-container"> <span class="toggle-label">Dark Mode Skeletons</span> <label class="toggle"> <input type="checkbox" id="theme-toggle" checked> <span class="toggle-slider"></span> </label> </div> <div class="loader-options"> <div class="loader-option active" data-speed="normal"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="13 17 18 12 13 7"></polyline> <polyline points="6 17 11 12 6 7"></polyline> </svg> </div> <div class="loader-option" data-speed="slow"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="5" y1="12" x2="19" y2="12"></line> <polyline points="12 5 19 12 12 19"></polyline> </svg> </div> <div class="loader-option" data-speed="fast"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"></path> </svg> </div> </div> </div> <div class="categories"> <div class="category active">All Content</div> <div class="category">Movies</div> <div class="category">TV Shows</div> <div class="category">Documentaries</div> <div class="category">Trending</div> </div> <div class="grid" id="video-grid"> <!-- Skeleton videos will be generated via JavaScript --> </div> <p class="showing-count">Showing <span id="count">8</span> video skeletons</p> </div> <script> document.addEventListener('DOMContentLoaded', function() { const grid = document.getElementById('video-grid'); const themeToggle = document.getElementById('theme-toggle'); const countElement = document.getElementById('count'); const categories = document.querySelectorAll('.category'); const loaderOptions = document.querySelectorAll('.loader-option'); // Default settings let totalVideos = 8; let animationSpeed = 'normal'; // Create the initial skeleton videos createSkeletonVideos(totalVideos); // Toggle theme themeToggle.addEventListener('change', function() { document.documentElement.style.setProperty('--background', this.checked ? '#121212' : '#f5f5f5'); document.documentElement.style.setProperty('--card-bg', this.checked ? '#1e1e1e' : '#ffffff'); document.documentElement.style.setProperty('--skeleton-base', this.checked ? '#2a2a2a' : '#e6e6e6'); document.documentElement.style.setProperty('--skeleton-highlight', this.checked ? '#3a3a3a' : '#f0f0f0'); document.documentElement.style.setProperty('--text', this.checked ? '#e0e0e0' : '#333333'); document.documentElement.style.setProperty('--text-secondary', this.checked ? '#a0a0a0' : '#666666'); }); // Category filter simulation categories.forEach(category => { category.addEventListener('click', function() { categories.forEach(c => c.classList.remove('active')); this.classList.add('active'); // Simulate loading new content based on category grid.innerHTML = ''; // Randomize number of videos to show when changing categories totalVideos = Math.floor(Math.random() * 5) + 6; // 6-10 videos countElement.textContent = totalVideos; createSkeletonVideos(totalVideos, true); }); }); // Animation speed controls loaderOptions.forEach(option => { option.addEventListener('click', function() { loaderOptions.forEach(o => o.classList.remove('active')); this.classList.add('active'); animationSpeed = this.dataset.speed; updateAnimationSpeed(animationSpeed); }); }); // Function to create skeleton videos function createSkeletonVideos(count, isNewItems = false) { for (let i = 0; i < count; i++) { // Random durations for realistic feel const minutes = Math.floor(Math.random() * 59) + 1; const seconds = Math.floor(Math.random() * 59); const duration = `${minutes}:${seconds < 10 ? '0' + seconds : seconds}`; // Create skeleton video element const skeletonVideo = document.createElement('div'); skeletonVideo.className = `skeleton-video ${isNewItems ? 'new-item' : ''}`; // Add a slight delay for each item to create a cascade effect if (isNewItems) { skeletonVideo.style.animationDelay = `${i * 0.1}s`; } skeletonVideo.innerHTML = ` <div class="skeleton-thumbnail"> <div class="skeleton-play-icon"></div> <div class="skeleton-duration">${duration}</div> <div class="skeleton-progress"></div> </div> <div class="skeleton-details"> <div class="skeleton-title"></div> <div class="skeleton-channel"></div> <div class="skeleton-meta"></div> </div> `; grid.appendChild(skeletonVideo); // Add hover event to simulate hover interaction skeletonVideo.addEventListener('mouseenter', function() { const progress = this.querySelector('.skeleton-progress'); progress.style.animation = 'none'; progress.offsetHeight; // Trigger reflow progress.style.animation = `progress ${getAnimationDuration()} ease-in-out infinite`; }); } } // Function to update animation speed function updateAnimationSpeed(speed) { const shimmerElements = document.querySelectorAll('.skeleton-thumbnail, .skeleton-title, .skeleton-channel, .skeleton-meta'); const progressElements = document.querySelectorAll('.skeleton-progress'); shimmerElements.forEach(element => { element.style.animationDuration = getAnimationDuration(speed, 'shimmer'); }); progressElements.forEach(element => { element.style.animationDuration = getAnimationDuration(speed, 'progress'); }); } // Helper function to get animation duration based on speed setting function getAnimationDuration(speed = animationSpeed, type = 'progress') { if (type === 'shimmer') { switch (speed) { case 'slow': return '4s'; case 'fast': return '1s'; default: return '2s'; } } else { // progress switch (speed) { case 'slow': return '6s'; case 'fast': return '1.5s'; default: return '3s'; } } } }); </script> </body> </html>
<html> <head> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Helvetica Neue', Arial, sans-serif; } body { background-color: #f9f9fb; display: flex; flex-direction: column; height: 100vh; width: 100%; max-width: 700px; margin: 0 auto; padding: 20px; } .app-container { display: flex; flex-direction: column; height: 100%; width: 100%; max-width: 700px; background-color: #ffffff; border-radius: 16px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05); overflow: hidden; position: relative; } .calendar-header { padding: 24px; border-bottom: 1px solid #f0f0f5; display: flex; justify-content: space-between; align-items: center; } .month-nav { display: flex; align-items: center; gap: 16px; } .month-title { font-size: 1.5rem; font-weight: 600; color: #2a2a3c; } .nav-btn { height: 36px; width: 36px; border-radius: 50%; background-color: #f5f5f7; border: none; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: background-color 0.2s; } .nav-btn:hover { background-color: #e8e8ed; } .nav-btn svg { height: 16px; width: 16px; color: #5e5e72; } .view-options { display: flex; gap: 8px; } .view-btn { padding: 8px 12px; background-color: #f5f5f7; border: none; border-radius: 8px; color: #5e5e72; font-size: 0.85rem; font-weight: 500; cursor: pointer; transition: all 0.2s; } .view-btn.active { background-color: #5662e1; color: white; } .view-btn:hover:not(.active) { background-color: #e8e8ed; } .weekdays { display: grid; grid-template-columns: repeat(7, 1fr); padding: 12px 16px; background-color: #ffffff; border-bottom: 1px solid #f0f0f5; } .weekday { text-align: center; font-size: 0.8rem; font-weight: 500; color: #8a8a9b; text-transform: uppercase; } .calendar-grid { display: grid; grid-template-columns: repeat(7, 1fr); grid-template-rows: repeat(5, 1fr); flex: 1; padding: 0 16px 16px; overflow-y: auto; } .skeleton-day { aspect-ratio: 1; padding: 8px; margin: 4px; border-radius: 8px; display: flex; flex-direction: column; gap: 4px; position: relative; overflow: hidden; background-color: #fafafa; } .skeleton-day-number { height: 20px; width: 20px; background-color: #eaeaea; border-radius: 50%; margin-bottom: 4px; opacity: 0; animation: fadeIn 0.5s forwards; } .skeleton-event { height: 16px; width: 85%; background-color: #eaeaea; border-radius: 4px; margin-bottom: 4px; position: relative; overflow: hidden; opacity: 0; animation: fadeIn 0.5s forwards; } @keyframes fadeIn { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: translateY(0); } } .skeleton-event::after, .skeleton-day-number::after { content: ""; position: absolute; top: 0; right: 0; bottom: 0; left: 0; background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.6) 50%, transparent 100%); animation: shimmer 1.5s infinite; } @keyframes shimmer { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } } .action-bar { display: flex; justify-content: space-between; padding: 16px 24px; background-color: #ffffff; border-top: 1px solid #f0f0f5; } .add-btn { padding: 10px 20px; background-color: #5662e1; color: #ffffff; border: none; border-radius: 8px; font-weight: 500; cursor: pointer; display: flex; align-items: center; gap: 8px; transition: background-color 0.2s; box-shadow: 0 4px 12px rgba(86, 98, 225, 0.2); } .add-btn:hover { background-color: #4552c9; } .add-btn svg { height: 16px; width: 16px; } .filter-btn { padding: 10px 20px; background-color: #f5f5f7; color: #5e5e72; border: none; border-radius: 8px; font-weight: 500; cursor: pointer; display: flex; align-items: center; gap: 8px; transition: background-color 0.2s; } .filter-btn:hover { background-color: #e8e8ed; } .filter-btn svg { height: 16px; width: 16px; } .side-panel { position: absolute; top: 0; right: -350px; height: 100%; width: 350px; background-color: #ffffff; box-shadow: -5px 0 15px rgba(0, 0, 0, 0.05); transition: right 0.3s ease-in-out; z-index: 10; padding: 24px; display: flex; flex-direction: column; } .side-panel.active { right: 0; } .panel-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; } .panel-title { font-size: 1.25rem; font-weight: 600; color: #2a2a3c; } .close-btn { background: none; border: none; color: #5e5e72; cursor: pointer; font-size: 1.5rem; } .panel-content { display: flex; flex-direction: column; gap: 16px; } .form-group { display: flex; flex-direction: column; gap: 8px; } .form-label { font-size: 0.9rem; font-weight: 500; color: #5e5e72; } .form-input { padding: 10px 12px; border: 1px solid #e0e0e5; border-radius: 8px; font-size: 0.95rem; transition: border-color 0.2s; } .form-input:focus { border-color: #5662e1; outline: none; } .panel-footer { margin-top: auto; display: flex; gap: 12px; justify-content: flex-end; } .btn { padding: 10px 20px; border-radius: 8px; font-weight: 500; cursor: pointer; transition: all 0.2s; } .btn-primary { background-color: #5662e1; color: white; border: none; } .btn-primary:hover { background-color: #4552c9; } .btn-secondary { background-color: #f5f5f7; color: #5e5e72; border: none; } .btn-secondary:hover { background-color: #e8e8ed; } .overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.3); opacity: 0; visibility: hidden; transition: opacity 0.3s; z-index: 5; } .overlay.active { opacity: 1; visibility: visible; } /* Color variants for skeleton events */ .color-blue { background-color: rgba(86, 98, 225, 0.2); border-left: 3px solid #5662e1; } .color-green { background-color: rgba(75, 192, 140, 0.2); border-left: 3px solid #4bc08c; } .color-orange { background-color: rgba(255, 145, 77, 0.2); border-left: 3px solid #ff914d; } .color-purple { background-color: rgba(175, 82, 222, 0.2); border-left: 3px solid #af52de; } /* Responsive styles */ @media (max-width: 480px) { .weekday { font-size: 0.7rem; } .month-title { font-size: 1.25rem; } .view-btn { padding: 6px 10px; font-size: 0.75rem; } .side-panel { width: 100%; right: -100%; } } </style> </head> <body> <div class="app-container"> <div class="calendar-header"> <div class="month-nav"> <button class="nav-btn"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="15 18 9 12 15 6"></polyline> </svg> </button> <h2 class="month-title">November 2023</h2> <button class="nav-btn"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="9 18 15 12 9 6"></polyline> </svg> </button> </div> <div class="view-options"> <button class="view-btn">Day</button> <button class="view-btn">Week</button> <button class="view-btn active">Month</button> </div> </div> <div class="weekdays"> <div class="weekday">Sun</div> <div class="weekday">Mon</div> <div class="weekday">Tue</div> <div class="weekday">Wed</div> <div class="weekday">Thu</div> <div class="weekday">Fri</div> <div class="weekday">Sat</div> </div> <div class="calendar-grid" id="calendar-grid"></div> <div class="action-bar"> <button class="add-btn" id="add-event-btn"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="12" y1="5" x2="12" y2="19"></line> <line x1="5" y1="12" x2="19" y2="12"></line> </svg> Add Event </button> <button class="filter-btn"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"></polygon> </svg> Filter </button> </div> <div class="side-panel" id="side-panel"> <div class="panel-header"> <h3 class="panel-title">Add New Event</h3> <button class="close-btn" id="close-panel">×</button> </div> <div class="panel-content"> <div class="form-group"> <label class="form-label">Event Title</label> <input type="text" class="form-input" placeholder="Add title"> </div> <div class="form-group"> <label class="form-label">Date</label> <input type="date" class="form-input"> </div> <div class="form-group"> <label class="form-label">Start Time</label> <input type="time" class="form-input"> </div> <div class="form-group"> <label class="form-label">End Time</label> <input type="time" class="form-input"> </div> <div class="form-group"> <label class="form-label">Description</label> <input type="text" class="form-input" placeholder="Add description"> </div> </div> <div class="panel-footer"> <button class="btn btn-secondary" id="cancel-btn">Cancel</button> <button class="btn btn-primary">Save Event</button> </div> </div> <div class="overlay" id="overlay"></div> </div> <script> document.addEventListener('DOMContentLoaded', () => { const calendarGrid = document.getElementById('calendar-grid'); const addEventBtn = document.getElementById('add-event-btn'); const closePanel = document.getElementById('close-panel'); const cancelBtn = document.getElementById('cancel-btn'); const sidePanel = document.getElementById('side-panel'); const overlay = document.getElementById('overlay'); // Class list for color variations const colorClasses = ['color-blue', 'color-green', 'color-orange', 'color-purple']; // Random number of events (1-3) for each day const getRandomEvents = () => Math.floor(Math.random() * 3) + 1; // Create skeleton days const createCalendar = () => { calendarGrid.innerHTML = ''; const days = 35; // 5 weeks x 7 days for (let i = 0; i < days; i++) { const skeletonDay = document.createElement('div'); skeletonDay.className = 'skeleton-day'; const dayNumber = document.createElement('div'); dayNumber.className = 'skeleton-day-number'; dayNumber.style.animationDelay = `${i * 0.03}s`; skeletonDay.appendChild(dayNumber); // Add random number of events for this day const eventsCount = getRandomEvents(); for (let j = 0; j < eventsCount; j++) { const event = document.createElement('div'); event.className = `skeleton-event ${colorClasses[Math.floor(Math.random() * colorClasses.length)]}`; event.style.animationDelay = `${(i * 0.03) + ((j + 1) * 0.1)}s`; skeletonDay.appendChild(event); } calendarGrid.appendChild(skeletonDay); } }; // Initialize calendar createCalendar(); // Side panel toggle const togglePanel = () => { sidePanel.classList.toggle('active'); overlay.classList.toggle('active'); }; addEventBtn.addEventListener('click', togglePanel); closePanel.addEventListener('click', togglePanel); cancelBtn.addEventListener('click', togglePanel); overlay.addEventListener('click', togglePanel); // Handle view button clicks const viewButtons = document.querySelectorAll('.view-btn'); viewButtons.forEach(btn => { btn.addEventListener('click', () => { viewButtons.forEach(b => b.classList.remove('active')); btn.classList.add('active'); // Simulating view change by recreating calendar with different loading animations calendarGrid.style.opacity = '0'; setTimeout(() => { calendarGrid.style.opacity = '1'; createCalendar(); }, 300); }); }); // Navigation buttons const navButtons = document.querySelectorAll('.nav-btn'); navButtons.forEach(btn => { btn.addEventListener('click', () => { // Simulate month change with loading animation calendarGrid.style.opacity = '0'; setTimeout(() => { calendarGrid.style.opacity = '1'; createCalendar(); }, 300); }); }); // Add hover effect to skeleton days setTimeout(() => { const skeletonDays = document.querySelectorAll('.skeleton-day'); skeletonDays.forEach(day => { day.addEventListener('mouseover', () => { day.style.transform = 'scale(1.03)'; day.style.boxShadow = '0 5px 15px rgba(0,0,0,0.05)'; day.style.transition = 'all 0.2s ease'; day.style.backgroundColor = '#f5f5f7'; day.style.cursor = 'pointer'; }); day.addEventListener('mouseout', () => { day.style.transform = 'scale(1)'; day.style.boxShadow = 'none'; day.style.backgroundColor = '#fafafa'; }); day.addEventListener('click', () => { togglePanel(); }); }); }, 1500); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Admin Panel Card Skeleton</title> <style> :root { --primary: #2563eb; --primary-light: #3b82f6; --secondary: #10b981; --dark: #111827; --light: #f9fafb; --gray: #4b5563; --gray-light: #9ca3af; --shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; } body { background-color: #f3f4f6; height: 100vh; display: flex; justify-content: center; align-items: center; padding: 1rem; overflow-x: hidden; color: var(--dark); } .dashboard-container { max-width: 680px; width: 100%; height: 680px; background-color: white; border-radius: 12px; box-shadow: var(--shadow); padding: 1.5rem; overflow-y: auto; position: relative; } .dashboard-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; padding-bottom: 1rem; border-bottom: 1px solid #e5e7eb; } .logo { display: flex; align-items: center; gap: 0.75rem; } .logo-icon { width: 2rem; height: 2rem; background: linear-gradient(135deg, var(--primary), var(--primary-light)); border-radius: 8px; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; } .logo-text { font-weight: 600; font-size: 1.25rem; } .nav-toggle { background: none; border: none; cursor: pointer; width: 40px; height: 40px; border-radius: 8px; display: flex; align-items: center; justify-content: center; transition: var(--transition); } .nav-toggle:hover { background-color: #f3f4f6; } .cards-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1.25rem; } .card { background-color: white; border-radius: 10px; overflow: hidden; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); transition: var(--transition); border: 1px solid #e5e7eb; position: relative; } .card:hover { transform: translateY(-3px); box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); } .card-skeleton { background: white; position: relative; overflow: hidden; } .card-skeleton::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.6) 50%, rgba(255, 255, 255, 0) 100%); animation: shimmer 1.5s infinite; transform: translateX(-100%); } .card-header { padding: 1rem; border-bottom: 1px solid #e5e7eb; background-color: #fafafa; } .header-skeleton { height: 1.5rem; width: 70%; border-radius: 4px; background-color: #e5e7eb; margin-bottom: 0.5rem; } .subheader-skeleton { height: 1rem; width: 40%; border-radius: 4px; background-color: #e5e7eb; } .card-content { padding: 1rem; } .content-skeleton { height: 0.875rem; width: 100%; border-radius: 4px; background-color: #e5e7eb; margin-bottom: 0.75rem; } .content-skeleton:last-child { width: 60%; margin-bottom: 0; } .card-footer { padding: 1rem; border-top: 1px solid #e5e7eb; display: flex; gap: 0.75rem; } .button-skeleton { height: 2.25rem; border-radius: 6px; background-color: #e5e7eb; flex: 1; } .action-skeleton { height: 2.25rem; width: 2.25rem; border-radius: 6px; background-color: #e5e7eb; } .card-loaded .header-skeleton, .card-loaded .subheader-skeleton, .card-loaded .content-skeleton, .card-loaded .button-skeleton, .card-loaded .action-skeleton { opacity: 0; transition: opacity 0.3s ease; } .card-real-content { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; flex-direction: column; opacity: 0; transition: opacity 0.4s ease; } .card-loaded .card-real-content { opacity: 1; } .card-title { font-weight: 600; font-size: 1.125rem; margin-bottom: 0.25rem; color: var(--dark); } .card-subtitle { font-size: 0.875rem; color: var(--gray); margin-bottom: 1rem; } .card-text { font-size: 0.875rem; line-height: 1.5; color: var(--gray); margin-bottom: 1rem; } .card-stats { display: flex; align-items: center; gap: 1rem; margin-bottom: 0.5rem; } .stat { display: flex; align-items: center; gap: 0.5rem; } .stat-number { font-weight: 600; color: var(--dark); } .stat-label { font-size: 0.75rem; color: var(--gray-light); } .card-button { padding: 0.5rem 1rem; border-radius: 6px; background-color: var(--primary); color: white; font-weight: 500; font-size: 0.875rem; border: none; cursor: pointer; transition: background-color 0.2s ease; flex: 1; } .card-button:hover { background-color: var(--primary-light); } .card-action { width: 2.25rem; height: 2.25rem; border-radius: 6px; background-color: #f3f4f6; border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: background-color 0.2s ease; } .card-action:hover { background-color: #e5e7eb; } .card-tag { display: inline-block; padding: 0.25rem 0.5rem; border-radius: 4px; font-size: 0.75rem; font-weight: 500; margin-right: 0.5rem; margin-bottom: 0.5rem; } .tag-success { background-color: rgba(16, 185, 129, 0.1); color: var(--secondary); } .tag-primary { background-color: rgba(37, 99, 235, 0.1); color: var(--primary); } .progress-bar { height: 6px; background-color: #e5e7eb; border-radius: 3px; overflow: hidden; margin-bottom: 0.75rem; } .progress-value { height: 100%; border-radius: 3px; background: linear-gradient(90deg, var(--primary), var(--primary-light)); width: 0%; transition: width 1s ease; } .refresh-container { position: absolute; top: 1.5rem; right: 1.5rem; z-index: 10; } .refresh-button { background-color: white; border: 1px solid #e5e7eb; box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); border-radius: 8px; padding: 0.5rem; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: var(--transition); } .refresh-button:hover { background-color: #f9fafb; } .refresh-icon { width: 1.25rem; height: 1.25rem; transition: transform 0.4s ease; } .refresh-button.refreshing .refresh-icon { animation: spin 1s linear infinite; } @keyframes shimmer { 100% { transform: translateX(100%); } } @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } @media (max-width: 600px) { .cards-grid { grid-template-columns: 1fr; } .dashboard-container { padding: 1rem; height: 100%; } } </style> </head> <body> <div class="dashboard-container"> <div class="dashboard-header"> <div class="logo"> <div class="logo-icon">A</div> <div class="logo-text">AdminSkeleton</div> </div> <button class="nav-toggle"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" y1="12" x2="21" y2="12"></line> <line x1="3" y1="6" x2="21" y2="6"></line> <line x1="3" y1="18" x2="21" y2="18"></line> </svg> </button> </div> <div class="refresh-container"> <button class="refresh-button" id="refresh-button"> <svg class="refresh-icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M23 4v6h-6"></path> <path d="M1 20v-6h6"></path> <path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10"></path> <path d="M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path> </svg> </button> </div> <div class="cards-grid" id="cards-grid"> <!-- Card 1 --> <div class="card"> <div class="card-skeleton"> <div class="card-header"> <div class="header-skeleton"></div> <div class="subheader-skeleton"></div> </div> <div class="card-content"> <div class="content-skeleton"></div> <div class="content-skeleton"></div> <div class="content-skeleton"></div> </div> <div class="card-footer"> <div class="button-skeleton"></div> <div class="action-skeleton"></div> </div> </div> <div class="card-real-content"> <div class="card-header"> <div class="card-title">User Analytics</div> <div class="card-subtitle">Last 30 days overview</div> </div> <div class="card-content"> <div class="card-stats"> <div class="stat"> <div class="stat-number">8.4k</div> <div class="stat-label">visitors</div> </div> <div class="stat"> <div class="stat-number">12%</div> <div class="stat-label">growth</div> </div> </div> <div class="progress-bar"> <div class="progress-value" style="width: 75%"></div> </div> <div class="card-text">New visitors increased by 12% this month compared to the previous period. Mobile traffic is up 8%.</div> </div> <div class="card-footer"> <button class="card-button">View Details</button> <button class="card-action"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="1"></circle> <circle cx="19" cy="12" r="1"></circle> <circle cx="5" cy="12" r="1"></circle> </svg> </button> </div> </div> </div> <!-- Card 2 --> <div class="card"> <div class="card-skeleton"> <div class="card-header"> <div class="header-skeleton"></div> <div class="subheader-skeleton"></div> </div> <div class="card-content"> <div class="content-skeleton"></div> <div class="content-skeleton"></div> <div class="content-skeleton"></div> </div> <div class="card-footer"> <div class="button-skeleton"></div> <div class="action-skeleton"></div> </div> </div> <div class="card-real-content"> <div class="card-header"> <div class="card-title">System Status</div> <div class="card-subtitle">Critical metrics</div> </div> <div class="card-content"> <div class="card-tag tag-success">All systems operational</div> <div class="card-tag tag-primary">99.8% uptime</div> <div class="progress-bar"> <div class="progress-value" style="width: 92%"></div> </div> <div class="card-text">Server response time averages 120ms. Latest maintenance completed 3 days ago with zero downtime.</div> </div> <div class="card-footer"> <button class="card-button">Check Status</button> <button class="card-action"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M12 5v14"></path> <path d="M5 12h14"></path> </svg> </button> </div> </div> </div> <!-- Card 3 --> <div class="card"> <div class="card-skeleton"> <div class="card-header"> <div class="header-skeleton"></div> <div class="subheader-skeleton"></div> </div> <div class="card-content"> <div class="content-skeleton"></div> <div class="content-skeleton"></div> <div class="content-skeleton"></div> </div> <div class="card-footer"> <div class="button-skeleton"></div> <div class="action-skeleton"></div> </div> </div> <div class="card-real-content"> <div class="card-header"> <div class="card-title">Content Management</div> <div class="card-subtitle">Recent updates</div> </div> <div class="card-content"> <div class="card-text">42 articles published this week. 8 pending approvals in the editorial queue.</div> <div class="card-stats"> <div class="stat"> <div class="stat-number">156</div> <div class="stat-label">total</div> </div> <div class="stat"> <div class="stat-number">+18%</div> <div class="stat-label">weekly</div> </div> </div> <div class="progress-bar"> <div class="progress-value" style="width: 60%"></div> </div> </div> <div class="card-footer"> <button class="card-button">Manage Content</button> <button class="card-action"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polygon points="5 3 19 12 5 21 5 3"></polygon> </svg> </button> </div> </div> </div> <!-- Card 4 --> <div class="card"> <div class="card-skeleton"> <div class="card-header"> <div class="header-skeleton"></div> <div class="subheader-skeleton"></div> </div> <div class="card-content"> <div class="content-skeleton"></div> <div class="content-skeleton"></div> <div class="content-skeleton"></div> </div> <div class="card-footer"> <div class="button-skeleton"></div> <div class="action-skeleton"></div> </div> </div> <div class="card-real-content"> <div class="card-header"> <div class="card-title">Infrastructure</div> <div class="card-subtitle">Resource allocation</div> </div> <div class="card-content"> <div class="card-tag tag-primary">Autoscaling active</div> <div class="card-text">CPU utilization at 38%. Memory usage stable at 4.2GB/8GB. Disk I/O operations within normal parameters.</div> <div class="progress-bar"> <div class="progress-value" style="width: 38%"></div> </div> </div> <div class="card-footer"> <button class="card-button">Manage Resources</button> <button class="card-action"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="3"></circle> <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path> </svg> </button> </div> </div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Simulate cards loading loadCards(); // Refresh button functionality const refreshButton = document.getElementById('refresh-button'); refreshButton.addEventListener('click', function() { refreshButton.classList.add('refreshing'); // Reset all cards to skeleton state const cards = document.querySelectorAll('.card'); cards.forEach(card => { card.classList.remove('card-loaded'); }); // Simulate loading again setTimeout(() => { loadCards(); refreshButton.classList.remove('refreshing'); }, 1500); }); // Progress value animation const progressBars = document.querySelectorAll('.progress-value'); progressBars.forEach(bar => { const targetWidth = bar.style.width; bar.style.width = '0%'; setTimeout(() => { bar.style.width = targetWidth; }, 500); }); }); function loadCards() { const cards = document.querySelectorAll('.card'); // Load each card with a delay cards.forEach((card, index) => { setTimeout(() => { card.classList.add('card-loaded'); }, 400 + (index * 150)); }); } // Add hover effects and interactions document.querySelectorAll('.card-button').forEach(button => { button.addEventListener('click', function(e) { e.preventDefault(); const parentCard = this.closest('.card'); // Create ripple effect on button click const ripple = document.createElement('span'); ripple.classList.add('ripple'); ripple.style.position = 'absolute'; ripple.style.borderRadius = '50%'; ripple.style.backgroundColor = 'rgba(255, 255, 255, 0.7)'; ripple.style.transform = 'scale(0)'; ripple.style.animation = 'ripple 0.6s linear'; ripple.style.pointerEvents = 'none'; this.appendChild(ripple); // Flash animation on parent card parentCard.style.transition = 'box-shadow 0.3s ease'; parentCard.style.boxShadow = '0 0 0 2px var(--primary)'; setTimeout(() => { parentCard.style.boxShadow = ''; ripple.remove(); }, 600); }); }); // Nav toggle functionality document.querySelector('.nav-toggle').addEventListener('click', function() { const cardsGrid = document.getElementById('cards-grid'); cardsGrid.style.opacity = '0.7'; setTimeout(() => { cardsGrid.style.opacity = '1'; }, 300); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>SaaS Features Skeleton</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; } :root { --bg-primary: #f8fafc; --text-primary: #1e293b; --text-secondary: #64748b; --primary: #3b82f6; --primary-light: #60a5fa; --accent: #8b5cf6; --card-bg: #ffffff; --card-border: #e2e8f0; --shimmer: rgba(226, 232, 240, 0.5); } body { background: var(--bg-primary); color: var(--text-primary); width: 100%; height: 700px; max-width: 700px; overflow-x: hidden; position: relative; } .container { max-width: 700px; margin: 0 auto; padding: 2rem 1.5rem; overflow-y: auto; height: 100%; scrollbar-width: none; } .container::-webkit-scrollbar { display: none; } header { text-align: center; margin-bottom: 2.5rem; } h1 { font-size: 2.2rem; margin-bottom: 0.5rem; background: linear-gradient(135deg, var(--primary) 0%, var(--accent) 100%); -webkit-background-clip: text; background-clip: text; color: transparent; font-weight: 800; } .subtitle { font-size: 1.1rem; color: var(--text-secondary); max-width: 540px; margin: 0 auto; line-height: 1.6; } .features { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1.5rem; margin-bottom: 2rem; } .feature-card { background: var(--card-bg); border-radius: 12px; padding: 1.5rem; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.03); border: 1px solid var(--card-border); transition: all 0.3s ease-in-out; position: relative; overflow: hidden; height: 100%; display: flex; flex-direction: column; } .feature-card:hover { transform: translateY(-5px); box-shadow: 0 12px 30px rgba(0, 0, 0, 0.07); border-color: rgba(59, 130, 246, 0.3); } .feature-icon { background: linear-gradient(135deg, var(--primary-light) 0%, var(--primary) 100%); width: 50px; height: 50px; border-radius: 10px; display: flex; align-items: center; justify-content: center; margin-bottom: 1.2rem; position: relative; overflow: hidden; } .feature-icon::after { content: ''; position: absolute; top: 0; left: -100%; width: 200%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent); animation: shimmer 2s infinite; } .feature-title { font-size: 1.2rem; font-weight: 700; margin-bottom: 0.5rem; position: relative; display: inline-block; } .feature-title::before { content: ''; position: absolute; height: 10px; width: 80%; bottom: 3px; left: -2px; background: linear-gradient(135deg, rgba(59, 130, 246, 0.1) 0%, rgba(139, 92, 246, 0.1) 100%); z-index: -1; border-radius: 4px; } .feature-description { color: var(--text-secondary); font-size: 0.95rem; line-height: 1.6; margin-bottom: 1.2rem; flex-grow: 1; } .placeholder-line { height: 10px; background: var(--shimmer); border-radius: 6px; margin-bottom: 0.5rem; position: relative; overflow: hidden; width: 100%; } .placeholder-line::after { content: ''; position: absolute; top: 0; left: -100%; width: 200%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.8), transparent); animation: shimmer 2s infinite; } .placeholder-line:nth-child(even) { width: 85%; } .placeholder-line:nth-child(3n) { width: 75%; } .placeholder-line:last-child { margin-bottom: 0; } .feature-btn { background: transparent; color: var(--primary); border: 1px solid var(--primary); border-radius: 8px; padding: 0.5rem 1rem; font-size: 0.9rem; cursor: pointer; transition: all 0.3s; align-self: flex-start; font-weight: 500; display: flex; align-items: center; gap: 0.5rem; } .feature-btn:hover { background: var(--primary); color: white; } .feature-btn .arrow { transition: transform 0.3s; } .feature-btn:hover .arrow { transform: translateX(3px); } .loading-dot { height: 8px; width: 8px; border-radius: 50%; display: inline-block; margin: 0 2px; animation: dots 1.5s infinite; background: var(--primary); opacity: 0.7; } .loading-dot:nth-child(2) { animation-delay: 0.5s; } .loading-dot:nth-child(3) { animation-delay: 1s; } .dot-container { display: flex; justify-content: center; align-items: center; margin-top: 2rem; } .staggered { animation-delay: calc(var(--i) * 0.2s); opacity: 0; transform: translateY(20px); animation: fadeInUp 0.7s ease forwards; } .bg-gradient { position: absolute; top: -300px; right: -300px; width: 600px; height: 600px; border-radius: 50%; background: linear-gradient(135deg, rgba(59, 130, 246, 0.05) 0%, rgba(139, 92, 246, 0.05) 100%); z-index: -1; filter: blur(80px); } .bg-gradient-2 { position: absolute; bottom: -200px; left: -100px; width: 400px; height: 400px; border-radius: 50%; background: linear-gradient(135deg, rgba(139, 92, 246, 0.05) 0%, rgba(59, 130, 246, 0.05) 100%); z-index: -1; filter: blur(60px); } @keyframes shimmer { 0% { left: -100%; } 100% { left: 100%; } } @keyframes fadeInUp { to { opacity: 1; transform: translateY(0); } } @keyframes dots { 0%, 100% { transform: translateY(0); opacity: 0.7; } 50% { transform: translateY(-5px); opacity: 1; } } .load-progress { height: 3px; width: 100%; background: var(--card-border); position: absolute; top: 0; left: 0; overflow: hidden; } .progress-bar { height: 100%; width: 30%; background: linear-gradient(90deg, var(--primary), var(--accent)); position: absolute; top: 0; left: -30%; animation: loading 2s infinite linear; } @keyframes loading { 0% { left: -30%; } 100% { left: 100%; } } @media (max-width: 600px) { h1 { font-size: 1.8rem; } .subtitle { font-size: 1rem; } .features { grid-template-columns: 1fr; } .container { padding: 1.5rem 1rem; } } </style> </head> <body> <div class="bg-gradient"></div> <div class="bg-gradient-2"></div> <div class="load-progress"> <div class="progress-bar"></div> </div> <div class="container"> <header> <h1>FlowSuite Platform</h1> <p class="subtitle">Discover the powerful features that help modern teams streamline workflows, collaborate seamlessly, and drive business results.</p> </header> <div class="features"> <div class="feature-card staggered" style="--i: 1"> <div class="feature-icon"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M21 14H14V21H21V14Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M10 14H3V21H10V14Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M21 3H14V10H21V3Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M10 3H3V10H10V3Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <h3 class="feature-title">Workspace Automation</h3> <div class="feature-description"> <div class="placeholder-line"></div> <div class="placeholder-line"></div> <div class="placeholder-line"></div> </div> <button class="feature-btn"> Learn more <span class="arrow">→</span> </button> </div> <div class="feature-card staggered" style="--i: 2"> <div class="feature-icon"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2L2 7L12 12L22 7L12 2Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M2 17L12 22L22 17" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M2 12L12 17L22 12" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <h3 class="feature-title">Data Integration Hub</h3> <div class="feature-description"> <div class="placeholder-line"></div> <div class="placeholder-line"></div> <div class="placeholder-line"></div> </div> <button class="feature-btn"> Explore <span class="arrow">→</span> </button> </div> <div class="feature-card staggered" style="--i: 3"> <div class="feature-icon"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M12 8V16" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M8 12H16" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <h3 class="feature-title">AI-Powered Insights</h3> <div class="feature-description"> <div class="placeholder-line"></div> <div class="placeholder-line"></div> <div class="placeholder-line"></div> </div> <button class="feature-btn"> Discover <span class="arrow">→</span> </button> </div> <div class="feature-card staggered" style="--i: 4"> <div class="feature-icon"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M17 21V19C17 17.9391 16.5786 16.9217 15.8284 16.1716C15.0783 15.4214 14.0609 15 13 15H5C3.93913 15 2.92172 15.4214 2.17157 16.1716C1.42143 16.9217 1 17.9391 1 19V21" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M9 11C11.2091 11 13 9.20914 13 7C13 4.79086 11.2091 3 9 3C6.79086 3 5 4.79086 5 7C5 9.20914 6.79086 11 9 11Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M23 21V19C22.9993 18.1137 22.7044 17.2528 22.1614 16.5523C21.6184 15.8519 20.8581 15.3516 20 15.13" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M16 3.13C16.8604 3.35031 17.623 3.85071 18.1676 4.55232C18.7122 5.25392 19.0078 6.11683 19.0078 7.005C19.0078 7.89318 18.7122 8.75608 18.1676 9.45769C17.623 10.1593 16.8604 10.6597 16 10.88" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <h3 class="feature-title">Team Collaboration</h3> <div class="feature-description"> <div class="placeholder-line"></div> <div class="placeholder-line"></div> <div class="placeholder-line"></div> </div> <button class="feature-btn"> View details <span class="arrow">→</span> </button> </div> <div class="feature-card staggered" style="--i: 5"> <div class="feature-icon"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M19.4 15C19.2669 15.3016 19.2272 15.6362 19.286 15.9606C19.3448 16.285 19.4995 16.5843 19.73 16.82L19.79 16.88C19.976 17.0657 20.1235 17.2863 20.2241 17.5291C20.3248 17.7719 20.3766 18.0322 20.3766 18.295C20.3766 18.5578 20.3248 18.8181 20.2241 19.0609C20.1235 19.3037 19.976 19.5243 19.79 19.71C19.6043 19.896 19.3837 20.0435 19.1409 20.1441C18.8981 20.2448 18.6378 20.2966 18.375 20.2966C18.1122 20.2966 17.8519 20.2448 17.6091 20.1441C17.3663 20.0435 17.1457 19.896 16.96 19.71L16.9 19.65C16.6643 19.4195 16.365 19.2648 16.0406 19.206C15.7162 19.1472 15.3816 19.1869 15.08 19.32C14.7842 19.4468 14.532 19.6572 14.3543 19.9255C14.1766 20.1938 14.0813 20.5082 14.08 20.83V21C14.08 21.5304 13.8693 22.0391 13.4942 22.4142C13.1191 22.7893 12.6104 23 12.08 23C11.5496 23 11.0409 22.7893 10.6658 22.4142C10.2907 22.0391 10.08 21.5304 10.08 21V20.91C10.0723 20.579 9.96512 20.258 9.77251 19.9887C9.5799 19.7194 9.31074 19.5143 9 19.4C8.69838 19.2669 8.36381 19.2272 8.03941 19.286C7.71502 19.3448 7.41568 19.4995 7.18 19.73L7.12 19.79C6.93425 19.976 6.71368 20.1235 6.47088 20.2241C6.22808 20.3248 5.96783 20.3766 5.705 20.3766C5.44217 20.3766 5.18192 20.3248 4.93912 20.2241C4.69632 20.1235 4.47575 19.976 4.29 19.79C4.10405 19.6043 3.95653 19.3837 3.85588 19.1409C3.75523 18.8981 3.70343 18.6378 3.70343 18.375C3.70343 18.1122 3.75523 17.8519 3.85588 17.6091C3.95653 17.3663 4.10405 17.1457 4.29 16.96L4.35 16.9C4.58054 16.6643 4.73519 16.365 4.794 16.0406C4.85282 15.7162 4.81312 15.3816 4.68 15.08C4.55324 14.7842 4.34276 14.532 4.07447 14.3543C3.80618 14.1766 3.49179 14.0813 3.17 14.08H3C2.46957 14.08 1.96086 13.8693 1.58579 13.4942C1.21071 13.1191 1 12.6104 1 12.08C1 11.5496 1.21071 11.0409 1.58579 10.6658C1.96086 10.2907 2.46957 10.08 3 10.08H3.09C3.42099 10.0723 3.742 9.96512 4.0113 9.77251C4.28059 9.5799 4.48572 9.31074 4.6 9C4.73312 8.69838 4.77282 8.36381 4.714 8.03941C4.65519 7.71502 4.50054 7.41568 4.27 7.18L4.21 7.12C4.02405 6.93425 3.87653 6.71368 3.77588 6.47088C3.67523 6.22808 3.62343 5.96783 3.62343 5.705C3.62343 5.44217 3.67523 5.18192 3.77588 4.93912C3.87653 4.69632 4.02405 4.47575 4.21 4.29C4.39575 4.10405 4.61632 3.95653 4.85912 3.85588C5.10192 3.75523 5.36217 3.70343 5.625 3.70343C5.88783 3.70343 6.14808 3.75523 6.39088 3.85588C6.63368 3.95653 6.85425 4.10405 7.04 4.29L7.1 4.35C7.33568 4.58054 7.63502 4.73519 7.95941 4.794C8.28381 4.85282 8.61838 4.81312 8.92 4.68H9C9.29577 4.55324 9.54802 4.34276 9.72569 4.07447C9.90337 3.80618 9.99872 3.49179 10 3.17V3C10 2.46957 10.2107 1.96086 10.5858 1.58579C10.9609 1.21071 11.4696 1 12 1C12.5304 1 13.0391 1.21071 13.4142 1.58579C13.7893 1.96086 14 2.46957 14 3V3.09C14.0013 3.41179 14.0966 3.72618 14.2743 3.99447C14.452 4.26276 14.7042 4.47324 15 4.6C15.3016 4.73312 15.6362 4.77282 15.9606 4.714C16.285 4.65519 16.5843 4.50054 16.82 4.27L16.88 4.21C17.0657 4.02405 17.2863 3.87653 17.5291 3.77588C17.7719 3.67523 18.0322 3.62343 18.295 3.62343C18.5578 3.62343 18.8181 3.67523 19.0609 3.77588C19.3037 3.87653 19.5243 4.02405 19.71 4.21C19.896 4.39575 20.0435 4.61632 20.1441 4.85912C20.2448 5.10192 20.2966 5.36217 20.2966 5.625C20.2966 5.88783 20.2448 6.14808 20.1441 6.39088C20.0435 6.63368 19.896 6.85425 19.71 7.04L19.65 7.1C19.4195 7.33568 19.2648 7.63502 19.206 7.95941C19.1472 8.28381 19.1869 8.61838 19.32 8.92V9C19.4468 9.29577 19.6572 9.54802 19.9255 9.72569C20.1938 9.90337 20.5082 9.99872 20.83 10H21C21.5304 10 22.0391 10.2107 22.4142 10.5858C22.7893 10.9609 23 11.4696 23 12C23 12.5304 22.7893 13.0391 22.4142 13.4142C22.0391 13.7893 21.5304 14 21 14H20.91C20.5882 14.0013 20.2738 14.0966 20.0055 14.2743C19.7372 14.452 19.5268 14.7042 19.4 15Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <h3 class="feature-title">Advanced Customization</h3> <div class="feature-description"> <div class="placeholder-line"></div> <div class="placeholder-line"></div> <div class="placeholder-line"></div> </div> <button class="feature-btn"> Configure <span class="arrow">→</span> </button> </div> <div class="feature-card staggered" style="--i: 6"> <div class="feature-icon"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M18 8C19.6569 8 21 6.65685 21 5C21 3.34315 19.6569 2 18 2C16.3431 2 15 3.34315 15 5C15 6.65685 16.3431 8 18 8Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M6 15C7.65685 15 9 13.6569 9 12C9 10.3431 7.65685 9 6 9C4.34315 9 3 10.3431 3 12C3 13.6569 4.34315 15 6 15Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M18 22C19.6569 22 21 20.6569 21 19C21 17.3431 19.6569 16 18 16C16.3431 16 15 17.3431 15 19C15 20.6569 16.3431 22 18 22Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M8.59 13.51L15.42 17.49" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M15.41 6.51L8.59 10.49" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <h3 class="feature-title">Enterprise Security</h3> <div class="feature-description"> <div class="placeholder-line"></div> <div class="placeholder-line"></div> <div class="placeholder-line"></div> </div> <button class="feature-btn"> View details <span class="arrow">→</span> </button> </div> </div> <div class="dot-container"> <div class="loading-dot"></div> <div class="loading-dot"></div> <div class="loading-dot"></div> </div> </div> <script> document.addEventListener('DOMContentLoaded', () => { // Add hover effects for feature cards const featureCards = document.querySelectorAll('.feature-card'); featureCards.forEach(card => { card.addEventListener('mouseenter', () => { const lines = card.querySelectorAll('.placeholder-line'); lines.forEach((line, index) => { line.style.transition = 'width 0.3s ease'; line.style.width = `${85 + Math.random() * 15}%`; line.style.animationDelay = `${index * 0.1}s`; }); }); card.addEventListener('mouseleave', () => { const lines = card.querySelectorAll('.placeholder-line'); lines.forEach((line, index) => { if (index % 2 === 0) { line.style.width = '100%'; } else if (index % 3 === 0) { line.style.width = '75%'; } else { line.style.width = '85%'; } }); }); }); // Make the buttons interactive const buttons = document.querySelectorAll('.feature-btn'); buttons.forEach(button => { button.addEventListener('click', function(e) { e.preventDefault(); // Add a quick pulse animation const card = this.closest('.feature-card'); card.style.animation = 'none'; card.offsetHeight; // Trigger reflow card.style.animation = 'pulse 0.5s'; // Change button text to show loading effect const originalText = this.innerHTML; this.innerHTML = 'Loading<span class="loading-dot"></span><span class="loading-dot"></span><span class="loading-dot"></span>'; // Reset after 2 seconds setTimeout(() => { this.innerHTML = originalText; }, 2000); }); }); // Add the pulse animation to the stylesheet const style = document.createElement('style'); style.textContent = ` @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.03); } 100% { transform: scale(1); } } `; document.head.appendChild(style); // Simulate "loading" of feature content setTimeout(() => { featureCards.forEach((card, index) => { setTimeout(() => { const placeholders = card.querySelectorAll('.placeholder-line'); const featureDescription = card.querySelector('.feature-description'); // Replace placeholder lines with actual content for each card switch(index) { case 0: featureDescription.innerHTML = 'Automate repetitive tasks with our intelligent workflow engine. Build custom processes without coding and reduce manual work by up to 65%.'; break; case 1: featureDescription.innerHTML = 'Connect and sync data across 200+ platforms with our no-code integration hub. Real-time data flow keeps your systems in perfect harmony.'; break; case 2: featureDescription.innerHTML = 'Leverage machine learning algorithms to uncover actionable insights from your data. Predictive analytics help forecast trends and guide decisions.'; break; case 3: featureDescription.innerHTML = 'Foster seamless teamwork with shared workspaces, real-time document editing, and smart notifications that keep everyone in sync.'; break; case 4: featureDescription.innerHTML = 'Tailor the platform to your exact needs with our extensive customization options. Build unique workflows and interfaces without technical expertise.'; break; case 5: featureDescription.innerHTML = 'Protect your data with enterprise-grade security including end-to-end encryption, role-based access control, and compliance with global standards.'; break; } // Add fade in animation to the text featureDescription.style.animation = 'fadeIn 0.5s ease forwards'; }, index * 300); // Stagger the replacement }); // Add the fade in animation to the stylesheet const fadeStyle = document.createElement('style'); fadeStyle.textContent = ` @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } `; document.head.appendChild(fadeStyle); // Hide the loading dots after all cards have "loaded" setTimeout(() => { document.querySelector('.dot-container').style.display = 'none'; }, 2000); }, 3000); // Start replacing after 3 seconds }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Corporate Blog Skeleton Loader</title> <style> :root { --primary-color: #2c3e50; --secondary-color: #ecf0f1; --accent-color: #3498db; --shimmer-color: rgba(255, 255, 255, 0.3); --loading-grey: #e2e5e7; --loading-dark-grey: #c8cdd0; --spacing-unit: 16px; --border-radius: 6px; --transition-timing: cubic-bezier(0.4, 0, 0.2, 1); } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; background-color: #f8f9fa; color: var(--primary-color); line-height: 1.6; max-width: 700px; margin: 0 auto; overflow-x: hidden; padding: var(--spacing-unit); height: 700px; display: flex; flex-direction: column; } .container { display: flex; flex-direction: column; gap: calc(var(--spacing-unit) * 1.5); max-width: 100%; background-color: white; padding: calc(var(--spacing-unit) * 1.5); border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); flex: 1; overflow-y: auto; position: relative; } .container::-webkit-scrollbar { width: 6px; } .container::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 3px; } .container::-webkit-scrollbar-thumb { background: var(--loading-dark-grey); border-radius: 3px; } .header { display: flex; align-items: center; justify-content: space-between; margin-bottom: calc(var(--spacing-unit) * 2); padding-bottom: var(--spacing-unit); border-bottom: 1px solid var(--loading-grey); } .company-info { display: flex; align-items: center; gap: var(--spacing-unit); } .logo-placeholder { width: 40px; height: 40px; border-radius: 50%; background-color: var(--loading-grey); position: relative; overflow: hidden; } .company-text { display: flex; flex-direction: column; gap: 4px; } .company-name { width: 120px; height: 14px; background-color: var(--loading-grey); border-radius: var(--border-radius); position: relative; overflow: hidden; } .company-tagline { width: 90px; height: 10px; background-color: var(--loading-grey); border-radius: var(--border-radius); position: relative; overflow: hidden; } .nav-placeholder { display: flex; gap: var(--spacing-unit); } .nav-item { width: 60px; height: 12px; background-color: var(--loading-grey); border-radius: var(--border-radius); position: relative; overflow: hidden; } .post-skeleton { display: flex; flex-direction: column; gap: var(--spacing-unit); padding: var(--spacing-unit); border-radius: 8px; background-color: white; transition: transform 0.3s var(--transition-timing); cursor: default; position: relative; } .post-skeleton:hover { transform: translateY(-4px); box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08); } .post-date { width: 90px; height: 10px; background-color: var(--loading-grey); border-radius: var(--border-radius); margin-bottom: 4px; position: relative; overflow: hidden; } .post-title { width: 100%; height: 22px; background-color: var(--loading-grey); border-radius: var(--border-radius); margin-bottom: var(--spacing-unit); position: relative; overflow: hidden; } .post-meta { display: flex; align-items: center; gap: var(--spacing-unit); margin-bottom: var(--spacing-unit); } .author-avatar { width: 30px; height: 30px; border-radius: 50%; background-color: var(--loading-grey); position: relative; overflow: hidden; } .author-name { width: 120px; height: 12px; background-color: var(--loading-grey); border-radius: var(--border-radius); position: relative; overflow: hidden; } .post-image { width: 100%; height: 180px; background-color: var(--loading-grey); border-radius: var(--border-radius); margin-bottom: var(--spacing-unit); position: relative; overflow: hidden; } .post-excerpt { display: flex; flex-direction: column; gap: 8px; } .excerpt-line { width: 100%; height: 12px; background-color: var(--loading-grey); border-radius: var(--border-radius); position: relative; overflow: hidden; } .excerpt-line:last-child { width: 70%; } .post-footer { display: flex; justify-content: space-between; align-items: center; margin-top: calc(var(--spacing-unit) * 0.75); } .post-tags { display: flex; gap: 8px; } .tag { width: 60px; height: 10px; background-color: var(--loading-grey); border-radius: var(--border-radius); position: relative; overflow: hidden; } .read-more { width: 80px; height: 12px; background-color: var(--loading-grey); border-radius: var(--border-radius); position: relative; overflow: hidden; } .sidebar { display: flex; flex-direction: column; gap: var(--spacing-unit); width: 30%; } .sidebar-title { width: 100%; height: 16px; background-color: var(--loading-grey); border-radius: var(--border-radius); margin-bottom: 8px; position: relative; overflow: hidden; } .sidebar-item { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; } .sidebar-image { width: 50px; height: 50px; background-color: var(--loading-grey); border-radius: var(--border-radius); position: relative; overflow: hidden; } .sidebar-text { width: calc(100% - 62px); height: 12px; background-color: var(--loading-grey); border-radius: var(--border-radius); position: relative; overflow: hidden; } .shimmer-element { position: relative; overflow: hidden; } .shimmer-element::after { content: ''; position: absolute; top: 0; right: 0; bottom: 0; left: 0; transform: translateX(-100%); background-image: linear-gradient( 90deg, rgba(255, 255, 255, 0) 0%, var(--shimmer-color) 50%, rgba(255, 255, 255, 0) 100% ); animation: shimmer var(--shimmer-duration, 2s) infinite; } @keyframes shimmer { 100% { transform: translateX(100%); } } .pulse-element { animation: pulse var(--pulse-duration, 2s) infinite alternate; } @keyframes pulse { 0% { opacity: 0.6; } 100% { opacity: 1; } } .section-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: calc(var(--spacing-unit) * 0.75); } .section-title { width: 150px; height: 18px; background-color: var(--loading-grey); border-radius: var(--border-radius); position: relative; overflow: hidden; } .section-action { width: 80px; height: 14px; background-color: var(--loading-grey); border-radius: var(--border-radius); position: relative; overflow: hidden; } .skeleton-layout { display: flex; flex-direction: column; gap: calc(var(--spacing-unit) * 2); } .placeholder-badge { position: absolute; top: var(--spacing-unit); right: var(--spacing-unit); width: 60px; height: 20px; background-color: var(--loading-grey); border-radius: 10px; overflow: hidden; } .compact-skeleton { display: flex; gap: var(--spacing-unit); margin-bottom: var(--spacing-unit); padding-bottom: var(--spacing-unit); border-bottom: 1px solid var(--loading-grey); } .compact-image { width: 80px; height: 80px; background-color: var(--loading-grey); border-radius: var(--border-radius); flex-shrink: 0; position: relative; overflow: hidden; } .compact-content { flex: 1; display: flex; flex-direction: column; gap: 8px; justify-content: space-between; } .compact-title { width: 100%; height: 16px; background-color: var(--loading-grey); border-radius: var(--border-radius); position: relative; overflow: hidden; } .compact-meta { width: 70%; height: 10px; background-color: var(--loading-grey); border-radius: var(--border-radius); position: relative; overflow: hidden; } .compact-excerpt { width: 100%; height: 10px; background-color: var(--loading-grey); border-radius: var(--border-radius); position: relative; overflow: hidden; } .newsletter-skeleton { background-color: #f5f7fa; border-radius: 8px; padding: var(--spacing-unit); display: flex; flex-direction: column; gap: var(--spacing-unit); margin-top: calc(var(--spacing-unit) * 2); } .newsletter-header { width: 70%; height: 18px; background-color: var(--loading-grey); border-radius: var(--border-radius); margin-bottom: 8px; position: relative; overflow: hidden; } .newsletter-text { width: 100%; height: 12px; background-color: var(--loading-grey); border-radius: var(--border-radius); margin-bottom: 4px; position: relative; overflow: hidden; } .newsletter-form { display: flex; gap: var(--spacing-unit); margin-top: 8px; } .newsletter-input { flex: 1; height: 36px; background-color: var(--loading-grey); border-radius: var(--border-radius); position: relative; overflow: hidden; } .newsletter-button { width: 100px; height: 36px; background-color: var(--loading-grey); border-radius: var(--border-radius); position: relative; overflow: hidden; } @media (max-width: 500px) { :root { --spacing-unit: 12px; } .header { flex-direction: column; align-items: flex-start; gap: var(--spacing-unit); } .nav-placeholder { width: 100%; justify-content: space-between; } .post-skeleton { padding: var(--spacing-unit); } .post-image { height: 140px; } .newsletter-form { flex-direction: column; } .newsletter-button { width: 100%; } } /* Loading Animation Variations */ .shimmer-slow::after { --shimmer-duration: 3s; } .shimmer-fast::after { --shimmer-duration: 1.5s; } .pulse-slow { --pulse-duration: 3s; } .pulse-fast { --pulse-duration: 1.2s; } /* Skeleton variation colors */ .variation-1 { background-color: #e6eaf0 !important; } .variation-2 { background-color: #e0e5eb !important; } .toolbar { display: flex; justify-content: space-between; align-items: center; padding: var(--spacing-unit) 0; margin-bottom: var(--spacing-unit); } .search-bar { width: 200px; height: 32px; background-color: var(--loading-grey); border-radius: 16px; position: relative; overflow: hidden; } .filter-buttons { display: flex; gap: 8px; } .filter-button { width: 80px; height: 32px; background-color: var(--loading-grey); border-radius: 16px; position: relative; overflow: hidden; } .bottom-bar { display: flex; justify-content: center; align-items: center; gap: var(--spacing-unit); padding: var(--spacing-unit); margin-top: auto; } .load-more { width: 120px; height: 40px; background-color: var(--loading-grey); border-radius: var(--border-radius); position: relative; overflow: hidden; } .pagination { display: flex; gap: 8px; } .page-item { width: 36px; height: 36px; background-color: var(--loading-grey); border-radius: var(--border-radius); position: relative; overflow: hidden; } </style> </head> <body> <div class="container"> <header class="header"> <div class="company-info"> <div class="logo-placeholder shimmer-element"></div> <div class="company-text"> <div class="company-name shimmer-element"></div> <div class="company-tagline shimmer-element"></div> </div> </div> <nav class="nav-placeholder"> <div class="nav-item shimmer-element"></div> <div class="nav-item shimmer-element"></div> <div class="nav-item shimmer-element"></div> </nav> </header> <div class="toolbar"> <div class="search-bar shimmer-element shimmer-slow"></div> <div class="filter-buttons"> <div class="filter-button shimmer-element"></div> <div class="filter-button shimmer-element shimmer-fast"></div> </div> </div> <div class="section-header"> <div class="section-title shimmer-element"></div> <div class="section-action shimmer-element shimmer-slow"></div> </div> <div class="skeleton-layout"> <article class="post-skeleton"> <div class="placeholder-badge shimmer-element shimmer-fast"></div> <div class="post-date shimmer-element"></div> <div class="post-title shimmer-element variation-1"></div> <div class="post-meta"> <div class="author-avatar shimmer-element"></div> <div class="author-name shimmer-element"></div> </div> <div class="post-image shimmer-element pulse-element"></div> <div class="post-excerpt"> <div class="excerpt-line shimmer-element"></div> <div class="excerpt-line shimmer-element"></div> <div class="excerpt-line shimmer-element"></div> <div class="excerpt-line shimmer-element"></div> </div> <div class="post-footer"> <div class="post-tags"> <div class="tag shimmer-element"></div> <div class="tag shimmer-element"></div> </div> <div class="read-more shimmer-element variation-2"></div> </div> </article> <div class="compact-skeleton"> <div class="compact-image shimmer-element pulse-element"></div> <div class="compact-content"> <div class="compact-title shimmer-element"></div> <div class="compact-meta shimmer-element shimmer-slow"></div> <div class="compact-excerpt shimmer-element"></div> <div class="compact-excerpt shimmer-element"></div> </div> </div> <div class="compact-skeleton"> <div class="compact-image shimmer-element pulse-slow"></div> <div class="compact-content"> <div class="compact-title shimmer-element"></div> <div class="compact-meta shimmer-element shimmer-fast"></div> <div class="compact-excerpt shimmer-element"></div> <div class="compact-excerpt shimmer-element"></div> </div> </div> <article class="post-skeleton"> <div class="post-date shimmer-element"></div> <div class="post-title shimmer-element variation-2"></div> <div class="post-meta"> <div class="author-avatar shimmer-element"></div> <div class="author-name shimmer-element"></div> </div> <div class="post-image shimmer-element pulse-slow"></div> <div class="post-excerpt"> <div class="excerpt-line shimmer-element"></div> <div class="excerpt-line shimmer-element"></div> <div class="excerpt-line shimmer-element"></div> </div> <div class="post-footer"> <div class="post-tags"> <div class="tag shimmer-element"></div> <div class="tag shimmer-element"></div> </div> <div class="read-more shimmer-element variation-1"></div> </div> </article> <div class="newsletter-skeleton"> <div class="newsletter-header shimmer-element"></div> <div class="newsletter-text shimmer-element"></div> <div class="newsletter-text shimmer-element" style="width: 90%"></div> <div class="newsletter-form"> <div class="newsletter-input shimmer-element"></div> <div class="newsletter-button shimmer-element variation-1"></div> </div> </div> </div> <div class="bottom-bar"> <div class="load-more shimmer-element variation-2"></div> <div class="pagination"> <div class="page-item shimmer-element"></div> <div class="page-item shimmer-element"></div> <div class="page-item shimmer-element"></div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Add visual variation to shimmer animations const shimmerElements = document.querySelectorAll('.shimmer-element'); shimmerElements.forEach((element, index) => { // Add slight delay variations to create a more natural loading effect element.style.animationDelay = `${(index % 5) * 0.15}s`; // Randomly assign variation classes to some elements if (Math.random() > 0.7) { element.classList.add(Math.random() > 0.5 ? 'variation-1' : 'variation-2'); } }); // Create a progressive revealing effect for skeletons const skeletons = document.querySelectorAll('.post-skeleton, .compact-skeleton'); skeletons.forEach((skeleton, index) => { skeleton.style.opacity = '0'; skeleton.style.transform = 'translateY(20px)'; skeleton.style.transition = 'opacity 0.5s ease, transform 0.5s ease'; setTimeout(() => { skeleton.style.opacity = '1'; skeleton.style.transform = 'translateY(0)'; }, 300 + (index * 150)); }); // Simulate loading progress setTimeout(() => { document.querySelector('.newsletter-skeleton').style.opacity = '1'; }, 1200); // Interactive hover effects on skeleton items skeletons.forEach(skeleton => { skeleton.addEventListener('mouseenter', () => { const shimmerElements = skeleton.querySelectorAll('.shimmer-element'); shimmerElements.forEach(el => { el.style.animationDuration = '1s'; }); }); skeleton.addEventListener('mouseleave', () => { const shimmerElements = skeleton.querySelectorAll('.shimmer-element'); shimmerElements.forEach(el => { el.style.animationDuration = ''; }); }); }); // Responsive adjustments function adjustForScreenSize() { const container = document.querySelector('.container'); if (window.innerWidth < 500) { container.style.padding = '12px'; // Hide some elements on mobile const lastCompactSkeleton = document.querySelectorAll('.compact-skeleton')[1]; if (lastCompactSkeleton) { lastCompactSkeleton.style.display = 'none'; } } else { container.style.padding = '24px'; const compactSkeletons = document.querySelectorAll('.compact-skeleton'); compactSkeletons.forEach(skeleton => { skeleton.style.display = 'flex'; }); } } window.addEventListener('resize', adjustForScreenSize); adjustForScreenSize(); }); </script> </body> </html>