Welcome
M1 | The Technical Fundamentals of the Web M2 | Advanced CMS M3 | UX/UI Products M4 | Advanced Prototyping M5 | Advanced Integration & Core Project Training Bonus
About Log In Create Account
LMS Pro LMS Pro
  • Welcome
  • Web Production & Interface Training
    • Module 1 — Technical Fundamentals of the Web
    • Module 2 — Advanced CMS
    • Module 3 — Product UX & UI
    • Module 4 — Advanced Prototyping
    • Module 5 — Advanced Integration & Capstone Project
    • Bonus Module
  • About
  • Log In
  • Sign Up
Skip to content

LMS Pro

LMS Pro — Your platform to learn, grow, succeed

Professional Training

UX/UI Designer

Modern UI Components

Posted on 5 February 202617 February 2026 By LMS Pro No Comments on Composants UI modernes
Module 3 — Product UX & UI

Modern UI Components

Discover advanced techniques for creating modern UI components with glassmorphism effects. Master modern CSS properties to design elegant and interactive interfaces that capture users' attention.

Module: Module 1: Technical Fundamentals of the Web

Level : Beginner

Duration : 20 minutes

Prerequisites: None

Educational objectives

  • Mastering CSS properties to create glassmorphism effects
  • Understanding the use of backdrop-filter and its applications
  • Develop interactive UI components with smooth animations
  • Integrate modern design techniques to improve the user experience
  • Create visually appealing and functional interfaces

Understanding the glass effect

Glassmorphism is a modern design trend that simulates the appearance of frosted or translucent glass. This technique uses semi-transparent backgrounds with blurring effects to create a sense of depth and elegance. The effect relies primarily on the CSS `backdrop-filter` property, which applies graphic filters to the background of an element.

Essential CSS Properties

To create a successful glassmorphism effect, several CSS properties work together. The backdrop-filter property with the value `blur()` creates the characteristic blur effect. Transparency is achieved with `background: rgba()` or `hsla()` to precisely control opacity. Subtle borders with `border: 1px solid rgba(255,255,255,0.3)` add definition. Finally, `box-shadow` allows you to add depth with soft shadows.

Key point The glassmorphism effect works best on colored backgrounds or with images, as it partially reveals the underlying content.

Key points to remember

Glassmorphism combines backdrop-filter, transparency and subtle borders to create a modern and elegant glass effect.

🎯 Mini-exercise: Basic glassmorphism panel

Create a panel with a glass effect on a gradient background, using backdrop-filter and rgba for transparency.

Reference code:



<div class="glass-container">
  <div class="glass-panel">
    <h2>Glassmorphism Panel</h2>
    <p>A modern panel with a glass effect</p>
    <button class="glass-button">Action</button>
  </div>
</div>
body { margin: 0; min-height: 100vh; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); display:flex; align-items: center; justify-content: center; font-family: 'Arial', sans-serif; } .glass-container { perspective: 1000px; } .glass-panel { background: rgba(255, 255, 255, 0.15); backdrop-filter: blur(20px); border: 1px solid rgba(255, 255, 255, 0.3); border-radius: 20px; padding: 40px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); text-align: center; color:white; transform: translateY(0); transition: all 0.4s cubic-bezier(0.23, 1, 0.320, 1); } .glass-panel:hover { transform: translateY(-10px); box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2); background: rgba(255, 255, 255, 0.25); } .glass-panel h2 { margin: 0 0 16px 0; font-size: 24px; font-weight: 300; letter-spacing: 1px; } .glass-panel p { margin: 0 0 24px 0; opacity: 0.9; line-height: 1.6; } .glass-button { background: rgba(255, 255, 255, 0.2); backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.3); border-radius: 30px; color:white; padding: 12px 24px; font-size: 16px; cursor: pointer; transition: all 0.3s ease; } .glass-button:hover { background: rgba(255, 255, 255, 0.3); transform: scale(1.05); }
// Adding a particle effect on hover document.querySelector('.glass-panel').addEventListener('mouseenter', function() { this.style.setProperty('--mouse-x', Math.random()); this.style.setProperty('--mouse-y', Math.random()); });



Result
● Ready
Monaco Editor v0.45

Structure and formatting

A glassmorphic credit card requires a clean HTML structure with elements for the card number, cardholder's name, expiration date, and bank logo. The layout uses realistic proportions (16:10 ratio) and harmonious spacing. The card should have subtle rounded corners and a perspective effect to simulate a real physical card.

Advanced visual effects

The visual effects of a glassmorphic map include dynamic reflections, realistic shadows, and smooth animations. Gradients can simulate holograms or iridescent effects. Using 3D transformations with `transform-style: preserve-3d` allows for rotation and tilt effects. Micro-interactions, such as state changes on hover, enhance the impression of realism.

Key point A successful credit card combines visual realism and functionality, with clickable areas and clear visual states.

Key points to remember

A successful glassmorphism map combines realistic proportions, subtle visual effects, and fluid interactions for a premium user experience.

🎯 Mini-exercise: Interactive credit card

Create a credit card with glassmorphism effect, 3D rotation on hover and animation of card details.

Reference code:



<div class="credit-card-scene">
  <div class="credit-card">
    <div class="card-front">
      <div class="card-logo">💳</div>
      <div class="card-chip"></div>
      <div class="card-number">4532 1234 5678 9012</div>
      <div class="card-details">
        <div class="card-holder">
          <span class="label">Card Holder</span>
          <span class="value">John Doe</span>
        </div>
        <div class="card-expiry">
          <span class="label">Expires</span>
          <span class="value">12/28</span>
        </div>
      </div>
      <div class="card-brand">PREMIUM</div>
    </div>
  </div>
</div>
body { margin: 0; min-height: 100vh; background: linear-gradient(135deg, #1e3c72 0%, #2a5298 50%, #667eea 100%); display:flex; align-items: center; justify-content: center; font-family: 'Arial', sans-serif; } .credit-card-scene { perspective: 1000px; padding: 50px; } .credit-card { width: 400px; height: 250px; position: relative; transform-style: preserve-3d; transition: transform 0.6s cubic-bezier(0.23, 1, 0.320, 1); cursor: pointer; } .credit-card:hover { transform: rotateY(15deg) rotateX(5deg) scale(1.05); } .card-front { width: 100%; height: 100%; background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%); backdrop-filter: blur(20px); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 20px; padding: 30px; box-sizing: border-box; position: relative; overflow:hidden; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3), inset 0 2px 0 rgba(255, 255, 255, 0.2); } .card-front::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); transition: left 0.5s; } .credit-card:hover .card-front::before { left: 100%; } .card-logo { font-size: 28px; position: absolute; top: 20px; right: 30px; filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2)); } .card-chip { width: 45px; height: 35px; background: linear-gradient(45deg, #ffd700, #ffed4e); border-radius: 6px; position: relative; margin: 20px 0; box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2); } .card-chip::before { content: ''; position: absolute; top: 5px; left: 5px; right: 5px; bottom: 5px; border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 3px; } .card-number { font-size: 24px; font-weight: 300; color:white; letter-spacing: 4px; margin: 25px 0; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); font-family: 'Courier New', minivan; } .card-details { display: flex; justify-content: space-between; margin-top: 30px; } .card-holder, .card-expiry { display: flex; flex-direction: column; } .label { font-size: 10px; color: rgba(255, 255, 255, 0.7); text-transform: uppercase; letter-spacing: 1px; margin-bottom: 5px; } .value { font-size: 16px; color:white; font-weight: 500; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); } .card-brand { position: absolute; bottom: 20px; right: 30px; font-size: 14px; font-weight: bold; color:white; letter-spacing: 2px; opacity: 0.8; }
// Animation of card numbers const cardNumber = document.querySelector('.card-number'); const originalNumber = cardNumber.textContent; let isRevealed = false; document.querySelector('.credit-card').addEventListener('click', function() { if (!isRevealed) { // Reveal animation cardNumber.style.transform = 'rotateX(90deg)'; setTimeout(() => { cardNumber.textContent = '4532 **** **** 9012'; cardNumber.style.transform = 'rotateX(0deg)'; isRevealed = true; }, 200); } else { // Masking Animation cardNumber.style.transform = 'rotateX(90deg)'; setTimeout(() => { cardNumber.textContent = originalNumber; cardNumber.style.transform = 'rotateX(0deg)'; isRevealed = false; }, 200); } }); // Mouse tracking effect document.querySelector('.credit-card').addEventListener('mousemove', function(e) { const rect = this.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; const centerX = rect.width / 2; const centerY = rect.height / 2; const rotateX = (y - centerY) / 10; const rotateY = (centerX - x) / 10; this.style.transform = `rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale(1.05)`; document.querySelector('.credit-card').addEventListener('mouseleave', function() { this.style.transform = 'rotateX(0deg) rotateY(0deg) scale(1)'; });



Result
● Ready
Monaco Editor v0.45

Micro-interactions and user feedback

Micro-interactions are essential for creating an engaging user experience. They include state changes on hover, click animations, and smooth transitions between states. These small animations bring the interface to life and provide immediate feedback to user actions. CSS properties like `transition`, `transform`, and `opacity` allow you to create these effects without impacting performance.

Advanced CSS animations with @keyframes

@keyframes animations offer precise control over complex animation sequences. They allow you to create effects like pulses, continuous rotations, and shape morphing. Timing functions like cubic-bezier() customize the acceleration and deceleration. The animation can be triggered by pseudo-classes (:hover, :focus) or controlled by JavaScript for more complex interactions.

Key point : Animations must have a clear intention and enhance the user experience without becoming distracting or impacting performance.

Key points to remember

Successful animations combine fluid micro-interactions and sophisticated @keyframes to create an engaging and intuitive user experience.

🎯 Mini-exercise: Map with complex animations

Create an interactive map with 3D flip animations, particle effects, and smooth transitions between states.

Reference code:



<div class="animated-card-container">
  <div class="animated-card" data-tilt>
    <div class="card-inner">
      <div class="card-face card-front">
        <div class="particles"></div>
        <div class="glow-effect"></div>
        <div class="card-content">
          <h3>Premium Card</h3>
          <div class="card-number">•••• •••• •••• 1234</div>
          <div class="card-info">
            <span>John Smith</span>
            <span>12/28</span>
          </div>
          <button class="flip-btn">Flip Card</button>
        </div>
      </div>
      <div class="card-face card-back">
        <div class="magnetic-strip"></div>
        <div class="cvv-area">
          <span>CVV</span>
          <div class="cvv-box">123</div>
        </div>
        <button class="flip-btn back">Flip Back</button>
      </div>
    </div>
  </div>
</div>
body { margin: 0; min-height: 100vh; background: radial-gradient(ellipse at top, #1e3c72, #2a5298); display:flex; align-items: center; justify-content: center; font-family: 'Arial', sans-serif; overflow:hidden; } .animated-card-container { perspective: 1000px; position: relative; } .animated-card { width: 350px; height: 220px; position: relative; cursor: pointer; transition: transform 0.1s ease; } .card-inner { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .animated-card.flipped .card-inner { transform: rotateY(180deg); } .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; border-radius: 20px; overflow:hidden; } .card-front { background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%); backdrop-filter: blur(20px); border: 1px solid rgba(255, 255, 255, 0.2); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3), inset 0 2px 0 rgba(255, 255, 255, 0.2); } .card-back { background: linear-gradient(135deg, rgba(50, 50, 50, 0.9) 0%, rgba(30, 30, 30, 0.95) 100%); backdrop-filter: blur(20px); border: 1px solid rgba(255, 255, 255, 0.1); transform: rotateY(180deg); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4); } .particles { position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0; transition: opacity 0.3s ease; } .animated-card:hover .particles { opacity: 1; animation: particleFloat 3s ease-in-out infinite; } @keyframes particleFloat { 0%, 100% { transform: translateY(0) rotate(0deg); } 33% { transform: translateY(-10px) rotate(120deg); } 66% { transform: translateY(5px) rotate(240deg); } } .glow-effect { position: absolute; top: -50%; left: -50%; width: 200%; height: 200%; background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%); opacity: 0; transition: opacity 0.3s ease; animation: rotate 6s linear infinite; } .animated-card:hover .glow-effect { opacity: 1; } @keyframes rotate { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } .card-content { padding: 30px; color:white; height: 100%; display:flex; flex-direction: column; justify-content: space-between; position: relative; z-index: 2; } .card-content h3 { margin: 0; font-size: 18px; font-weight: 300; letter-spacing: 2px; opacity: 0; transform: translateY(20px); animation: slideInUp 0.6s ease forwards 0.2s; } .card-number { font-size: 22px; font-family: 'Courier New', minivan; letter-spacing: 3px; margin: 20px 0; opacity: 0; transform: translateY(20px); animation: slideInUp 0.6s ease forwards 0.4s; } .card-info { display: flex; justify-content: space-between; font-size: 12px; text-transform: uppercase; letter-spacing: 1px; opacity: 0; transform: translateY(20px); animation: slideInUp 0.6s ease forwards 0.6s; } .flip-btn { background: rgba(255, 255, 255, 0.2); backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.3); border-radius: 25px; color:white; padding: 8px 16px; font-size: 12px; cursor: pointer; transition: all 0.3s ease; align-self: flex-start; opacity: 0; transform: translateY(20px); animation: slideInUp 0.6s ease forwards 0.8s; } .flip-btn:hover { background: rgba(255, 255, 255, 0.3); transform: translateY(-2px); } @keyframes slideInUp { to { opacity: 1; transform: translateY(0); } } .magnetic-strip { width: 100%; height: 50px; background: linear-gradient(90deg, #333, #111); margin: 20px 0; } .cvv-area { padding: 30px; color:white; } .cvv-area span { font-size: 12px; opacity: 0.7; } .cvv-box { background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 4px; padding: 10px; margin: 10px 0; width: 60px; text-align: center; font-family: 'Courier New', minivan; } .flip-btn.back { position: absolute; bottom: 30px; right: 30px; }
// Handling card flip document.querySelectorAll('.flip-btn').forEach(btn => { btn.addEventListener('click', function() { const card = document.querySelector('.animated-card'); card.classList.toggle('flipped'); }); }); // Mouse tracking effect with tilt 3D const card = document.querySelector('.animated-card'); card.addEventListener('mousemove', function(e) { const rect = this.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; const centerX = rect.width / 2; const centerY = rect.height / 2; const rotateX = (y - centerY) / 8; const rotateY = (centerX - x) / 8; this.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale3d(1.05, 1.05, 1.05)`; card.addEventListener('mouseleave', function() { this.style.transform = 'perspective(1000px) rotateX(0) rotateY(0) scale3d(1, 1, 1)'; }); // Animation of particles function createParticles() { const particlesContainer = document.querySelector('.particles'); for(let i = 0; i < 20; i++) { const particle = document.createElement('div'); particle.style.cssText = ` position: absolute; width: 2px; height: 2px; background: rgba(255,255,255,0.6); border-radius: 50%; left: ${Math.random() * 100}%; top: ${Math.random() * 100}%; animation: particleDrift ${2 + Math.random() * 3}s linear infinite; animation-delay: ${Math.random() * 2}s; `; particlesContainer.appendChild(particle); } } // Style for particle animation const style = document.createElement('style'); style.textContent = ` @keyframes particleDrift { 0% { transform: translateY(0) scale(1); opacity: 0; } 10% { opacity: 1; } 90% { opacity: 1; } 100% { transform: translateY(-100px) scale(0); opacity: 0; } } `; document.head.appendChild(style); createParticles();



Result
● Ready
Monaco Editor v0.45

Performance of glassmorphism effects

Glassmorphism effects, while aesthetically pleasing, can negatively impact performance if poorly implemented. The backdrop-filter property is resource-intensive because it requires complex rendering calculations. It is essential to limit the number of elements using this property simultaneously. Using will-change: backdrop-filter can optimize rendering by preparing the browser for the transformations.

CSS optimization techniques

Optimization involves several strategies: using `transform` and `opacity` for animations because they only trigger the composition phase, avoiding properties that force reflow such as animated `width` or `height`, and preferring `transform: scale()`. Using `contain: layout style paint` isolates elements and limits recalculations. `@keyframes` animations are more efficient than repeated JavaScript transitions.

Key point A modern interface must maintain 60fps by limiting expensive operations and using browser optimizations.

Key points to remember

Optimizing glassmorphism components requires a balance between visual effect and performance, favoring properties optimized by the browser.

🎯 Mini-exercise: High-performance optimized interface

Create a glassmorphic dashboard with multiple maps, smooth animations, and optimization techniques to maintain 60fps.

Reference code:



<div class="optimized-dashboard">
  <div class="dashboard-header">
    <h1>Optimized Dashboard</h1>
    <div class="performance-meter">
      <span class="fps-counter">60 FPS</span>
    </div>
  </div>
  
  <div class="cards-grid">
    <div class="dashboard-card" data-card="1">
      <div class="card-header">
        <span class="card-icon">📊</span>
        <span class="card-title">Analytics</span>
      </div>
      <div class="card-content">
        <div class="metric-value">1,234</div>
        <div class="metric-label">Total Views</div>
        <div class="progress-bar">
          <div class="progress-fill" data-progress="75"></div>
        </div>
      </div>
    </div>
    
    <div class="dashboard-card" data-card="2">
      <div class="card-header">
        <span class="card-icon">👥</span>
        <span class="card-title">Users</span>
      </div>
      <div class="card-content">
        <div class="metric-value">567</div>
        <div class="metric-label">Active Users</div>
        <div class="progress-bar">
          <div class="progress-fill" data-progress="62"></div>
        </div>
      </div>
    </div>
    
    <div class="dashboard-card" data-card="3">
      <div class="card-header">
        <span class="card-icon">💰</span>
        <span class="card-title">Revenue</span>
      </div>
      <div class="card-content">
        <div class="metric-value">$12,456</div>
        <div class="metric-label">This Month</div>
        <div class="progress-bar">
          <div class="progress-fill" data-progress="88"></div>
        </div>
      </div>
    </div>
    
    <div class="dashboard-card" data-card="4">
      <div class="card-header">
        <span class="card-icon">⚡</span>
        <span class="card-title">Performance</span>
      </div>
      <div class="card-content">
        <div class="metric-value">98.5%</div>
        <div class="metric-label">Uptime</div>
        <div class="progress-bar">
          <div class="progress-fill" data-progress="98"></div>
        </div>
      </div>
    </div>
  </div>
</div>
* { box-sizing: border-box; } body { margin: 0; min-height: 100vh; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; padding: 20px; overflow-x: hidden; } .optimized-dashboard { max-width: 1200px; margin: 0 auto; /* Optimization: Isolation to limit repaints */ contain: layout style paint; } .dashboard-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 30px; color:white; } .dashboard-header h1 { margin: 0; font-size: 32px; font-weight: 300; letter-spacing: 1px; } .performance-meter { background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 25px; padding: 8px 16px; font-size: 14px; } .fps-counter { color: #4ade80; font-weight: bold; } .cards-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 24px; /* Optimization: Optimized subgrid */ contain: layout; } .dashboard-card { background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(20px); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 20px; padding: 24px; color:white; position: relative; overflow:hidden; cursor: pointer; /* Performance-critical optimizations */ will-change: transform; transform: translateZ(0); /* Force GPU layer */ transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1); /* Limitation of repaints */ contain: layout style; } .dashboard-card::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent); transition: left 0.5s ease; } .dashboard-card:hover { transform: translateY(-8px) scale(1.02); box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2); } .dashboard-card:hover::before { left: 100%; } .card-header { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; } .card-icon { font-size: 24px; filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2)); } .card-title { font-size: 16px; font-weight: 500; opacity: 0.9; text-transform: uppercase; letter-spacing: 1px; } .card-content { /* Content optimization */ contain: layout style; } .metric-value { font-size: 36px; font-weight: 700; margin-bottom: 8px; background: linear-gradient(135deg, #fff 0%, #f8fafc 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } .metric-label { font-size: 14px; opacity: 0.8; margin-bottom: 16px; text-transform: uppercase; letter-spacing: 0.5px; } .progress-bar { width: 100%; height: 8px; background: rgba(255, 255, 255, 0.1); border-radius: 4px; overflow:hidden; position: relative; } .progress-fill { height: 100%; background: linear-gradient(90deg, #4ade80, #22d3ee); border-radius: 4px; width: 0; transition: width 1.2s cubic-bezier(0.4, 0, 0.2, 1); /* Optimization for width animation */ will-change: width; } .progress-fill::after { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); animation: shimmer 2s ease-in-out infinite; } @keyframes shimmer { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } } /* Optimized input animations */ .dashboard-card { opacity: 0; transform: translateY(30px); animation: cardSlideIn 0.6s cubic-bezier(0.4, 0, 0.2, 1) forwards; } .dashboard-card[data-card="1"] { animation-delay: 0.1s; } .dashboard-card[data-card="2"] { animation-delay: 0.2s; } .dashboard-card[data-card="3"] { animation-delay: 0.3s; } .dashboard-card[data-card="4"] { animation-delay: 0.4s; } @keyframes cardSlideIn { to { opacity: 1; transform: translateY(0); } } /* Media queries for responsive optimization */ @media (max-width: 768px) { .cards-grid { grid-template-columns: 1fr; gap: 16px; } .dashboard-card { padding: 20px; } /* Disabling some effects on mobile for performance */ .dashboard-card::before { display: none; } .progress-fill::after { display: none; } }
// Performance optimization with RequestAnimationFrame class PerformanceOptimizer { constructor() { this.isAnimating = false; this.pendingAnimations = new Set(); this.fpsCounter = document.querySelector('.fps-counter'); this.lastTime = performance.now(); this.frameCount = 0; this.init(); } init() { this.initProgressBars(); this.initFPSCounter(); this.initIntersectionObserver(); } // Optimized animation of progress bars initProgressBars() { const progressBars = document.querySelectorAll('.progress-fill'); // Using a delay to avoid simultaneous animations progressBars.forEach((bar, index) => { setTimeout(() => { const progress = bar.getAttribute('data-progress'); requestAnimationFrame(() => { bar.style.width = `${progress}%`; }); }, index * 200); }); } // FPS counter for performance monitoring initFPSCounter() { const updateFPS = () => { const currentTime = performance.now(); this.frameCount++; if (currentTime >= this.lastTime + 1000) { const fps = Math.round((this.frameCount * 1000) / (currentTime - this.lastTime)); this.fpsCounter.textContent = `${fps} FPS`; // Change color depending on performance if (fps >= 50) { this.fpsCounter.style.color = '#4ade80'; // Green } else if (fps >= 30) { this.fpsCounter.style.color = '#fbbf24'; // Yellow } else { this.fpsCounter.style.color = '#ef4444'; // Red } this.frameCount = 0; this.lastTime = currentTime; } requestAnimationFrame(updateFPS); }; requestAnimationFrame(updateFPS); } // Intersection Observer for scroll animations initIntersectionObserver() { const cards = document.querySelectorAll('.dashboard-card'); const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { // Animation only when the element is visible entry.target.style.animationPlayState = 'running'; } }); }, { threshold: 0.1, rootMargin: '50px' }); cards.forEach(card => { card.style.animationPlayState = 'paused'; observer.observe(card); }); } } // Throttling optimized for mouse events function throttle(func, delay) { let timeoutId; let lastExecTime = 0; return function (...args) { const currentTime = Date.now(); if (currentTime - lastExecTime > delay) { func.apply(this, args); lastExecTime = currentTime; } else { clearTimeout(timeoutId); timeoutId = setTimeout(() => { func.apply(this, args); lastExecTime = Date.now(); }, delay - (currentTime - lastExecTime)); } }; } // Optimized management of interactions const cards = document.querySelectorAll('.dashboard-card'); cards.forEach(card => { // Using passive listeners to improve performance const handleMouseMove = throttle((e) => { const rect = card.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; const centerX = rect.width / 2; const centerY = rect.height / 2; const rotateX = (y - centerY) / 20; const rotateY = (centerX - x) / 20; // Using transform to avoid reflows requestAnimationFrame(() => { card.style.transform = ` translateY(-8px) scale(1.02) rotateX(${rotateX}deg) rotateY(${rotateY}deg) `; }, 16); card.addEventListener('mousemove', handleMouseMove, { passive: true }); card.addEventListener('mouseleave', () => { requestAnimationFrame(() => { card.style.transform = 'translateY(0) scale(1) rotateX(0) rotateY(0)'; }); }, { passive: true }); }); // Initialize the optimization system document.addEventListener('DOMContentLoaded', () => { new PerformanceOptimizer(); // Debug: Log performance metrics if (performance.mark) { performance.mark('dashboard-loaded'); console.log('Optimized dashboard loaded:', performance.now(), 'ms'); } });



Result
● Ready
Monaco Editor v0.45

Accessibility of glassmorphism components

Accessibility is crucial for glassmorphic components because their translucent nature can pose readability challenges. Sufficient contrast between the text and the background must be ensured, even with the transparency effect. Users with visual impairments should

Summary

Key points to remember

  • Modular components Reusable UI components accelerate development and ensure visual consistency.
  • Glassmorphism : backdrop-filter and transparency create modern and elegant interfaces.
  • Micro-interactions Immediate visual feedback improves the user experience.
  • Regular practice Technical mastery is acquired through experimentation and the completion of concrete projects.

Sources

To deepen your knowledge:

  • 🔗MDN – backdrop filter and transparency effects→
  • 🔗CSS-Tricks – Guide to Glassmorphism→

Validate your knowledge

Test your understanding with this 10-question quiz:

Loading quiz...
Categories: Accessibility Animation CSS Web Fundamentals HTML JavaScript JS UX

Post navigation

❮ Previous Post: Animated burger menu: CSS morphing with advanced transitions
Next Post: Advanced CSS Animations Part 2 ❯

See also

Micro-interactions
Advanced CSS Animations Part 2
February 5, 2026
Information architecture
The ergonomics of UI maps: guiding the eye to provide better information
January 6, 2026

LMS Pro LMS Pro is an educational platform dedicated to Professional Training. LMS Pro 2026 All rights reserved

You must log in

Forgot password?
No account yet., click here
LMS Pro

Create an account

Fill in this information

Already have an account? Log in
LMS Pro
English
French