﻿{"id":562,"date":"2026-02-06T00:22:25","date_gmt":"2026-02-05T23:22:25","guid":{"rendered":"https:\/\/lmspro.fr\/2-4-composants-ui-modernes\/"},"modified":"2026-02-17T19:36:40","modified_gmt":"2026-02-17T18:36:40","slug":"composants-ui-modernes-2","status":"publish","type":"post","link":"https:\/\/lmspro.fr\/en\/composants-ui-modernes-2\/","title":{"rendered":"Modern UI Components"},"content":{"rendered":"<h2>2.4 Composants UI modernes<\/h2>\n<p class=\"wpa-text\">Explorez votre cr\u00e9ativit\u00e9 pour d\u00e9velopper des animations CSS pouss\u00e9es et cr\u00e9er des composants UI modernes captivants. Dans cette le\u00e7on, nous d\u00e9couvrirons comment concevoir des interfaces utilisateur dynamiques qui allient esth\u00e9tique moderne et fonctionnalit\u00e9 avanc\u00e9e gr\u00e2ce aux techniques CSS les plus r\u00e9centes.<\/p>\n<div class=\"article-meta\">\n<p><strong>Module :<\/strong> Module 1 : Fondamentaux techniques du web<\/p>\n<p><strong>Niveau :<\/strong> Interm\u00e9diaire<\/p>\n<p><strong>Dur\u00e9e :<\/strong> 45 minutes<\/p>\n<p><strong>Pr\u00e9requis :<\/strong> Bases HTML\/CSS, notions de Flexbox et Grid<\/p>\n<\/div>\n<h2>Objectifs p\u00e9dagogiques<\/h2>\n<ul>\n<li>Ma\u00eetriser les animations CSS avanc\u00e9es avec @keyframes et propri\u00e9t\u00e9s transform<\/li>\n<li>Cr\u00e9er des composants UI modernes avec des effets visuels sophistiqu\u00e9s<\/li>\n<li>Impl\u00e9menter des micro-interactions pour am\u00e9liorer l&rsquo;exp\u00e9rience utilisateur<\/li>\n<li>Utiliser les techniques CSS modernes comme backdrop-filter et clip-path<\/li>\n<li>D\u00e9velopper des interfaces responsives avec des animations fluides<\/li>\n<\/ul>\n<div class=\"wpa-accordion wpa-accordion-flush\" id=\"accordion-2-4-composants-ui-modernes\">\n<div class=\"wpa-accordion-item\">\n<button class=\"wpa-accordion-header\" data-wpa-target=\"#accordion-2-4-composants-ui-modernes-item-1\" aria-expanded=\"false\"><span class=\"wpa-accordion-title\"><span class=\"wpa-accordion-number\">01<\/span> Animations CSS avanc\u00e9es et transformations<\/span><span class=\"wpa-accordion-icon\"><\/span><\/button><\/p>\n<div id=\"accordion-2-4-composants-ui-modernes-item-1\" class=\"wpa-accordion-body\">\n<div class=\"wpa-accordion-content\">\n<h4>Les fondamentaux des animations CSS modernes<\/h4>\n<p>Les animations CSS avanc\u00e9es constituent le c\u0153ur des interfaces modernes. Elles permettent de cr\u00e9er des transitions fluides, des micro-interactions engageantes et des effets visuels sophistiqu\u00e9s. Les propri\u00e9t\u00e9s transform, @keyframes et animation offrent un contr\u00f4le pr\u00e9cis sur le mouvement et la transformation des \u00e9l\u00e9ments. La propri\u00e9t\u00e9 transform permet des rotations, translations, mises \u00e0 l&rsquo;\u00e9chelle et distorsions en 2D et 3D, tandis que @keyframes d\u00e9finit les \u00e9tapes cl\u00e9s d&rsquo;une animation complexe. Les timing-functions personnalis\u00e9es, comme cubic-bezier(), permettent de cr\u00e9er des courbes d&rsquo;animation naturelles et expressives.<\/p>\n<h4>Transformations 3D et perspective<\/h4>\n<p>Les transformations 3D ajoutent une dimension suppl\u00e9mentaire aux animations web. La propri\u00e9t\u00e9 perspective cr\u00e9e un point de fuite qui simule la profondeur, tandis que transform-style: preserve-3d maintient les transformations 3D des \u00e9l\u00e9ments enfants. Les rotations sur les axes X, Y et Z (rotateX(), rotateY(), rotateZ()) permettent de cr\u00e9er des effets de retournement, de basculement et de rotation dans l&rsquo;espace. La propri\u00e9t\u00e9 backface-visibility contr\u00f4le la visibilit\u00e9 de la face arri\u00e8re des \u00e9l\u00e9ments transform\u00e9s, essentielle pour les effets de carte retourn\u00e9e.<\/p>\n<div class=\"info-box\">\n<p><strong>Point cl\u00e9<\/strong> : Les performances d&rsquo;animation sont optimales avec les propri\u00e9t\u00e9s transform et opacity, qui d\u00e9clenchent la composition GPU plut\u00f4t que le repaint du navigateur.<\/p>\n<\/div>\n<div class=\"tuto-objectif\" style=\"background: #f5f5f5; border-left: 4px solid #667eea; padding: 16px 20px; margin-top: 24px; border-radius: 0 8px 8px 0;\">\n<h3 style=\"color: #667eea; margin: 0 0 8px 0; font-size: 16px;\">\u00c0 retenir<\/h3>\n<p style=\"margin: 0; color: #333;\">Les animations CSS avanc\u00e9es combinant @keyframes, transform 3D et timing-functions personnalis\u00e9es cr\u00e9ent des exp\u00e9riences visuelles immersives et performantes.<\/p>\n<\/div>\n<div class=\"tuto-exercise\" style=\"background: #fff3e0; border-left: 4px solid #ff9800; padding: 16px 20px; margin-top: 20px; border-radius: 0 8px 8px 0;\">\n<h4 style=\"color: #ff9800; margin: 0 0 8px 0; font-size: 15px;\">\ud83c\udfaf Mini-exercice : Card flip 3D interactive<\/h4>\n<p style=\"margin: 0; color: #333; font-size: 14px;\">Cr\u00e9ez une carte qui se retourne en 3D au survol, r\u00e9v\u00e9lant du contenu sur sa face arri\u00e8re avec une animation fluide et une perspective r\u00e9aliste.<\/p>\n<\/div>\n<div class=\"codepen-block\" data-block-id=\"exercise-1\">\n<p class=\"codepen-block-label\">Code de r\u00e9f\u00e9rence :<\/p>\n<div class=\"codepen-header\">\n<div class=\"codepen-tabs\">\n<button class=\"codepen-tab active\" data-tab=\"html\">HTML<\/button><br \/>\n<button class=\"codepen-tab\" data-tab=\"css\">CSS<\/button><br \/>\n<button class=\"codepen-tab\" data-tab=\"javascript\">JS<\/button>\n<\/div>\n<p><button class=\"codepen-copy-btn\">Copier<\/button>\n<\/div>\n<div class=\"codepen-code-container\">\n<pre class=\"codepen-code active\" data-lang=\"html\">&lt;div class=\"flip-card\"&gt;\n  &lt;div class=\"flip-card-inner\"&gt;\n    &lt;div class=\"flip-card-front\"&gt;\n      &lt;h3&gt;Composant UI&lt;\/h3&gt;\n      &lt;p&gt;Interface moderne&lt;\/p&gt;\n    &lt;\/div&gt;\n    &lt;div class=\"flip-card-back\"&gt;\n      &lt;h3&gt;Animation CSS&lt;\/h3&gt;\n      &lt;p&gt;Transform 3D avanc\u00e9&lt;\/p&gt;\n    &lt;\/div&gt;\n  &lt;\/div&gt;\n&lt;\/div&gt;<\/pre>\n<pre class=\"codepen-code\" data-lang=\"css\">.flip-card {\n  background-color: transparent;\n  width: 300px;\n  height: 200px;\n  perspective: 1000px;\n  margin: 50px auto;\n}\n\n.flip-card-inner {\n  position: relative;\n  width: 100%;\n  height: 100%;\n  text-align: center;\n  transition: transform 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275);\n  transform-style: preserve-3d;\n}\n\n.flip-card:hover .flip-card-inner {\n  transform: rotateY(180deg);\n}\n\n.flip-card-front, .flip-card-back {\n  position: absolute;\n  width: 100%;\n  height: 100%;\n  backface-visibility: hidden;\n  border-radius: 16px;\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n  box-shadow: 0 10px 30px rgba(0,0,0,0.2);\n}\n\n.flip-card-front {\n  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n  color: white;\n}\n\n.flip-card-back {\n  background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);\n  color: white;\n  transform: rotateY(180deg);\n}<\/pre>\n<pre class=\"codepen-code\" data-lang=\"javascript\">\/\/ Code JavaScript optionnel pour contr\u00f4les avanc\u00e9s<\/pre>\n<\/div>\n<\/div>\n<div class=\"monaco-sandbox\" data-block-id=\"exercise-1\">\n<div class=\"monaco-header\">\n<div class=\"monaco-tabs\">\n<button class=\"monaco-tab active\" data-lang=\"html\">HTML<\/button><br \/>\n<button class=\"monaco-tab\" data-lang=\"css\">CSS<\/button><br \/>\n<button class=\"monaco-tab\" data-lang=\"javascript\">JS<\/button>\n<\/div>\n<div class=\"monaco-actions\">\n<button class=\"monaco-btn monaco-btn-run\">\u25b6 Ex\u00e9cuter<\/button><br \/>\n<button class=\"monaco-btn monaco-btn-reset\">\u21ba Reset<\/button>\n<\/div>\n<\/div>\n<div class=\"monaco-container\">\n<div class=\"monaco-editor-wrapper\">\n<div class=\"monaco-editor-pane active\" data-lang=\"html\"><\/div>\n<div class=\"monaco-editor-pane\" data-lang=\"css\"><\/div>\n<div class=\"monaco-editor-pane\" data-lang=\"javascript\"><\/div>\n<\/div>\n<div class=\"monaco-preview-wrapper\">\n<div class=\"monaco-preview-header\">Result<\/div>\n<\/div>\n<\/div>\n<div class=\"monaco-status\">\n<span class=\"monaco-status-left\">\u25cf Pr\u00eat<\/span><br \/>\n<span class=\"monaco-status-right\">Monaco Editor v0.45<\/span>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"wpa-accordion-item\">\n<button class=\"wpa-accordion-header\" data-wpa-target=\"#accordion-2-4-composants-ui-modernes-item-2\" aria-expanded=\"false\"><span class=\"wpa-accordion-title\"><span class=\"wpa-accordion-number\">02<\/span> Effets visuels modernes et glassmorphism<\/span><span class=\"wpa-accordion-icon\"><\/span><\/button><\/p>\n<div id=\"accordion-2-4-composants-ui-modernes-item-2\" class=\"wpa-accordion-body\">\n<div class=\"wpa-accordion-content\">\n<h4>Le glassmorphism et backdrop-filter<\/h4>\n<p>Le glassmorphism est une tendance design qui simule l&rsquo;effet du verre d\u00e9poli, cr\u00e9ant des interfaces \u00e9l\u00e9gantes et modernes. Cette technique utilise principalement backdrop-filter: blur() pour flouter l&rsquo;arri\u00e8re-plan, combin\u00e9 \u00e0 des bordures subtiles et des transparences. L&rsquo;effet de verre s&rsquo;obtient par la superposition d&rsquo;un fond semi-transparent, d&rsquo;un flou d&rsquo;arri\u00e8re-plan et de reflets subtils. Les propri\u00e9t\u00e9s border et box-shadow avec des valeurs l\u00e9g\u00e8res renforcent l&rsquo;illusion de profondeur. Cette approche fonctionne particuli\u00e8rement bien sur des arri\u00e8re-plans color\u00e9s ou des images, cr\u00e9ant une hi\u00e9rarchie visuelle naturelle.<\/p>\n<h4>Gradients avanc\u00e9s et animations de couleurs<\/h4>\n<p>Les gradients CSS modernes d\u00e9passent les simples transitions lin\u00e9aires. Les gradients radiaux, coniques (conic-gradient) et les m\u00e9langes de couleurs multiples cr\u00e9ent des effets visuels sophistiqu\u00e9s. L&rsquo;animation de gradients par keyframes permet des transitions de couleurs fluides et captivantes. La propri\u00e9t\u00e9 background-size combin\u00e9e \u00e0 des positions variables cr\u00e9e des effets de mouvement sur les gradients. Les techniques de masquage (mask-image) et les modes de m\u00e9lange (mix-blend-mode) permettent de combiner plusieurs gradients pour des effets complexes et originaux.<\/p>\n<div class=\"info-box\">\n<p><strong>Point cl\u00e9<\/strong> : backdrop-filter n\u00e9cessite un \u00e9l\u00e9ment semi-transparent pour r\u00e9v\u00e9ler l&rsquo;effet de flou sur l&rsquo;arri\u00e8re-plan. Toujours pr\u00e9voir une alternative pour les navigateurs non compatibles.<\/p>\n<\/div>\n<div class=\"tuto-objectif\" style=\"background: #f5f5f5; border-left: 4px solid #667eea; padding: 16px 20px; margin-top: 24px; border-radius: 0 8px 8px 0;\">\n<h3 style=\"color: #667eea; margin: 0 0 8px 0; font-size: 16px;\">\u00c0 retenir<\/h3>\n<p style=\"margin: 0; color: #333;\">Le glassmorphism et les gradients anim\u00e9s cr\u00e9ent des interfaces visuellement riches qui suivent les tendances design contemporaines tout en maintenant une excellente lisibilit\u00e9.<\/p>\n<\/div>\n<div class=\"tuto-exercise\" style=\"background: #fff3e0; border-left: 4px solid #ff9800; padding: 16px 20px; margin-top: 20px; border-radius: 0 8px 8px 0;\">\n<h4 style=\"color: #ff9800; margin: 0 0 8px 0; font-size: 15px;\">\ud83c\udfaf Mini-exercice : Card glassmorphism avec gradient anim\u00e9<\/h4>\n<p style=\"margin: 0; color: #333; font-size: 14px;\">Cr\u00e9ez une carte avec effet de verre utilisant backdrop-filter et un gradient d&rsquo;arri\u00e8re-plan anim\u00e9 qui change de couleurs en continu.<\/p>\n<\/div>\n<div class=\"codepen-block\" data-block-id=\"exercise-2\">\n<p class=\"codepen-block-label\">Code de r\u00e9f\u00e9rence :<\/p>\n<div class=\"codepen-header\">\n<div class=\"codepen-tabs\">\n<button class=\"codepen-tab active\" data-tab=\"html\">HTML<\/button><br \/>\n<button class=\"codepen-tab\" data-tab=\"css\">CSS<\/button><br \/>\n<button class=\"codepen-tab\" data-tab=\"javascript\">JS<\/button>\n<\/div>\n<p><button class=\"codepen-copy-btn\">Copier<\/button>\n<\/div>\n<div class=\"codepen-code-container\">\n<pre class=\"codepen-code active\" data-lang=\"html\">&lt;div class=\"glass-container\"&gt;\n  &lt;div class=\"glass-card\"&gt;\n    &lt;h3&gt;Glassmorphism&lt;\/h3&gt;\n    &lt;p&gt;Interface moderne avec effet de verre et gradient anim\u00e9&lt;\/p&gt;\n    &lt;button class=\"glass-btn\"&gt;D\u00e9couvrir&lt;\/button&gt;\n  &lt;\/div&gt;\n&lt;\/div&gt;<\/pre>\n<pre class=\"codepen-code\" data-lang=\"css\">.glass-container {\n  height: 100vh;\n  background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);\n  background-size: 400% 400%;\n  animation: gradientShift 15s ease infinite;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  padding: 20px;\n}\n\n@keyframes gradientShift {\n  0% {\n    background-position: 0% 50%;\n  }\n  50% {\n    background-position: 100% 50%;\n  }\n  100% {\n    background-position: 0% 50%;\n  }\n}\n\n.glass-card {\n  background: rgba(255, 255, 255, 0.15);\n  backdrop-filter: blur(20px);\n  border-radius: 20px;\n  border: 1px solid rgba(255, 255, 255, 0.2);\n  padding: 40px;\n  text-align: center;\n  box-shadow: \n    0 8px 32px 0 rgba(31, 38, 135, 0.37),\n    inset 0 1px 0 0 rgba(255, 255, 255, 0.4);\n  max-width: 400px;\n  color: white;\n  transition: transform 0.3s ease;\n}\n\n.glass-card:hover {\n  transform: translateY(-10px) scale(1.02);\n}\n\n.glass-btn {\n  background: rgba(255, 255, 255, 0.2);\n  backdrop-filter: blur(10px);\n  border: 1px solid rgba(255, 255, 255, 0.3);\n  border-radius: 25px;\n  color: white;\n  padding: 12px 30px;\n  font-size: 16px;\n  cursor: pointer;\n  transition: all 0.3s ease;\n  margin-top: 20px;\n}\n\n.glass-btn:hover {\n  background: rgba(255, 255, 255, 0.3);\n  transform: scale(1.05);\n}<\/pre>\n<pre class=\"codepen-code\" data-lang=\"javascript\">\/\/ Code JavaScript pour interactions avanc\u00e9es<\/pre>\n<\/div>\n<\/div>\n<div class=\"monaco-sandbox\" data-block-id=\"exercise-2\">\n<div class=\"monaco-header\">\n<div class=\"monaco-tabs\">\n<button class=\"monaco-tab active\" data-lang=\"html\">HTML<\/button><br \/>\n<button class=\"monaco-tab\" data-lang=\"css\">CSS<\/button><br \/>\n<button class=\"monaco-tab\" data-lang=\"javascript\">JS<\/button>\n<\/div>\n<div class=\"monaco-actions\">\n<button class=\"monaco-btn monaco-btn-run\">\u25b6 Ex\u00e9cuter<\/button><br \/>\n<button class=\"monaco-btn monaco-btn-reset\">\u21ba Reset<\/button>\n<\/div>\n<\/div>\n<div class=\"monaco-container\">\n<div class=\"monaco-editor-wrapper\">\n<div class=\"monaco-editor-pane active\" data-lang=\"html\"><\/div>\n<div class=\"monaco-editor-pane\" data-lang=\"css\"><\/div>\n<div class=\"monaco-editor-pane\" data-lang=\"javascript\"><\/div>\n<\/div>\n<div class=\"monaco-preview-wrapper\">\n<div class=\"monaco-preview-header\">Result<\/div>\n<\/div>\n<\/div>\n<div class=\"monaco-status\">\n<span class=\"monaco-status-left\">\u25cf Pr\u00eat<\/span><br \/>\n<span class=\"monaco-status-right\">Monaco Editor v0.45<\/span>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"wpa-accordion-item\">\n<button class=\"wpa-accordion-header\" data-wpa-target=\"#accordion-2-4-composants-ui-modernes-item-3\" aria-expanded=\"false\"><span class=\"wpa-accordion-title\"><span class=\"wpa-accordion-number\">03<\/span> Micro-interactions et feedback utilisateur<\/span><span class=\"wpa-accordion-icon\"><\/span><\/button><\/p>\n<div id=\"accordion-2-4-composants-ui-modernes-item-3\" class=\"wpa-accordion-body\">\n<div class=\"wpa-accordion-content\">\n<h4>Conception de micro-interactions significatives<\/h4>\n<p>Les micro-interactions sont les d\u00e9tails subtils qui transforment une interface fonctionnelle en exp\u00e9rience m\u00e9morable. Elles fournissent un feedback imm\u00e9diat aux actions utilisateur, guident la navigation et cr\u00e9ent une sensation de r\u00e9activit\u00e9. Une micro-interaction efficace comprend quatre phases : d\u00e9clencheur (hover, click), r\u00e8gles (que se passe-t-il), feedback visuel (animation, changement d&rsquo;\u00e9tat) et boucles\/modes (\u00e9tats persistants). Les transitions CSS avec des timing-functions appropri\u00e9es (ease-out pour les entr\u00e9es, ease-in pour les sorties) cr\u00e9ent des mouvements naturels. L&rsquo;utilisation strat\u00e9gique de transform: scale(), rotate() et translate() pour les \u00e9tats hover et active am\u00e9liore la perception de l&rsquo;interactivit\u00e9.<\/p>\n<h4>\u00c9tats d&rsquo;interface et transitions fluides<\/h4>\n<p>La gestion des \u00e9tats d&rsquo;interface (normal, hover, active, focus, disabled) n\u00e9cessite une approche coh\u00e9rente et pr\u00e9visible. Chaque \u00e9tat doit avoir une signature visuelle distincte tout en maintenant la coh\u00e9rence de l&rsquo;identit\u00e9 du composant. Les transitions entre \u00e9tats doivent \u00eatre suffisamment rapides pour ne pas ralentir l&rsquo;interaction (100-300ms g\u00e9n\u00e9ralement) mais assez lentes pour \u00eatre per\u00e7ues. La propri\u00e9t\u00e9 transition-property permet de contr\u00f4ler pr\u00e9cis\u00e9ment quelles propri\u00e9t\u00e9s sont anim\u00e9es. L&rsquo;utilisation de transform et opacity pour les animations maintient des performances optimales en \u00e9vitant les reflows du navigateur.<\/p>\n<div class=\"info-box\">\n<p><strong>Point cl\u00e9<\/strong> : Les micro-interactions ne doivent jamais entraver l&rsquo;utilisabilit\u00e9. Elles doivent \u00eatre subtiles, rapides et optionnelles (respecter prefers-reduced-motion).<\/p>\n<\/div>\n<div class=\"tuto-objectif\" style=\"background: #f5f5f5; border-left: 4px solid #667eea; padding: 16px 20px; margin-top: 24px; border-radius: 0 8px 8px 0;\">\n<h3 style=\"color: #667eea; margin: 0 0 8px 0; font-size: 16px;\">\u00c0 retenir<\/h3>\n<p style=\"margin: 0; color: #333;\">Les micro-interactions r\u00e9ussies combinent feedback instantan\u00e9, transitions fluides et respect des pr\u00e9f\u00e9rences utilisateur pour cr\u00e9er une exp\u00e9rience intuitive et engageante.<\/p>\n<\/div>\n<div class=\"tuto-exercise\" style=\"background: #fff3e0; border-left: 4px solid #ff9800; padding: 16px 20px; margin-top: 20px; border-radius: 0 8px 8px 0;\">\n<h4 style=\"color: #ff9800; margin: 0 0 8px 0; font-size: 15px;\">\ud83c\udfaf Mini-exercice : Bouton interactif avec loader morphing<\/h4>\n<p style=\"margin: 0; color: #333; font-size: 14px;\">Cr\u00e9ez un bouton qui se transforme en loader anim\u00e9 au clic, avec des micro-interactions sur hover et des \u00e9tats visuels distincts.<\/p>\n<\/div>\n<div class=\"codepen-block\" data-block-id=\"exercise-3\">\n<p class=\"codepen-block-label\">Code de r\u00e9f\u00e9rence :<\/p>\n<div class=\"codepen-header\">\n<div class=\"codepen-tabs\">\n<button class=\"codepen-tab active\" data-tab=\"html\">HTML<\/button><br \/>\n<button class=\"codepen-tab\" data-tab=\"css\">CSS<\/button><br \/>\n<button class=\"codepen-tab\" data-tab=\"javascript\">JS<\/button>\n<\/div>\n<p><button class=\"codepen-copy-btn\">Copier<\/button>\n<\/div>\n<div class=\"codepen-code-container\">\n<pre class=\"codepen-code active\" data-lang=\"html\">&lt;button class=\"morphing-btn\" id=\"morphBtn\"&gt;\n  &lt;span class=\"btn-text\"&gt;Confirmer&lt;\/span&gt;\n  &lt;span class=\"btn-loader\"&gt;\n    &lt;div class=\"loader-dot\"&gt;&lt;\/div&gt;\n    &lt;div class=\"loader-dot\"&gt;&lt;\/div&gt;\n    &lt;div class=\"loader-dot\"&gt;&lt;\/div&gt;\n  &lt;\/span&gt;\n  &lt;span class=\"btn-success\"&gt;\u2713&lt;\/span&gt;\n&lt;\/button&gt;<\/pre>\n<pre class=\"codepen-code\" data-lang=\"css\">.morphing-btn {\n  position: relative;\n  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n  color: white;\n  border: none;\n  border-radius: 50px;\n  padding: 16px 40px;\n  font-size: 16px;\n  font-weight: 600;\n  cursor: pointer;\n  overflow: hidden;\n  transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1);\n  min-width: 140px;\n  height: 56px;\n}\n\n.morphing-btn:hover {\n  transform: translateY(-2px);\n  box-shadow: 0 10px 25px rgba(102, 126, 234, 0.4);\n}\n\n.morphing-btn:active {\n  transform: translateY(0);\n}\n\n.btn-text, .btn-loader, .btn-success {\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  transform: translate(-50%, -50%);\n  transition: all 0.4s ease;\n}\n\n.btn-loader, .btn-success {\n  opacity: 0;\n  pointer-events: none;\n}\n\n.btn-loader {\n  display: flex;\n  gap: 6px;\n}\n\n.loader-dot {\n  width: 8px;\n  height: 8px;\n  border-radius: 50%;\n  background: white;\n  animation: loader-bounce 1.4s infinite;\n}\n\n.loader-dot:nth-child(2) {\n  animation-delay: 0.2s;\n}\n\n.loader-dot:nth-child(3) {\n  animation-delay: 0.4s;\n}\n\n@keyframes loader-bounce {\n  0%, 80%, 100% {\n    transform: scale(0.8);\n    opacity: 0.5;\n  }\n  40% {\n    transform: scale(1.2);\n    opacity: 1;\n  }\n}\n\n.morphing-btn.is-loading {\n  border-radius: 28px;\n  min-width: 56px;\n  padding: 16px;\n}\n\n.morphing-btn.is-loading .btn-text {\n  opacity: 0;\n  transform: translate(-50%, -50%) scale(0.8);\n}\n\n.morphing-btn.is-loading .btn-loader {\n  opacity: 1;\n}\n\n.morphing-btn.is-success {\n  background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);\n}\n\n.morphing-btn.is-success .btn-loader {\n  opacity: 0;\n}\n\n.morphing-btn.is-success .btn-success {\n  opacity: 1;\n  font-size: 24px;\n}<\/pre>\n<pre class=\"codepen-code\" data-lang=\"javascript\">document.addEventListener('DOMContentLoaded', function() {\n  const btn = document.getElementById('morphBtn');\n  \n  btn.addEventListener('click', function() {\n    if (!btn.classList.contains('is-loading') && !btn.classList.contains('is-success')) {\n      \/\/ Phase loading\n      btn.classList.add('is-loading');\n      \n      \/\/ Simulation d'une action asynchrone\n      setTimeout(() => {\n        btn.classList.remove('is-loading');\n        btn.classList.add('is-success');\n        \n        \/\/ Reset apr\u00e8s 2 secondes\n        setTimeout(() => {\n          btn.classList.remove('is-success');\n        }, 2000);\n      }, 2000);\n    }\n  });\n});<\/pre>\n<\/div>\n<\/div>\n<div class=\"monaco-sandbox\" data-block-id=\"exercise-3\">\n<div class=\"monaco-header\">\n<div class=\"monaco-tabs\">\n<button class=\"monaco-tab active\" data-lang=\"html\">HTML<\/button><br \/>\n<button class=\"monaco-tab\" data-lang=\"css\">CSS<\/button><br \/>\n<button class=\"monaco-tab\" data-lang=\"javascript\">JS<\/button>\n<\/div>\n<div class=\"monaco-actions\">\n<button class=\"monaco-btn monaco-btn-run\">\u25b6 Ex\u00e9cuter<\/button><br \/>\n<button class=\"monaco-btn monaco-btn-reset\">\u21ba Reset<\/button>\n<\/div>\n<\/div>\n<div class=\"monaco-container\">\n<div class=\"monaco-editor-wrapper\">\n<div class=\"monaco-editor-pane active\" data-lang=\"html\"><\/div>\n<div class=\"monaco-editor-pane\" data-lang=\"css\"><\/div>\n<div class=\"monaco-editor-pane\" data-lang=\"javascript\"><\/div>\n<\/div>\n<div class=\"monaco-preview-wrapper\">\n<div class=\"monaco-preview-header\">Result<\/div>\n<\/div>\n<\/div>\n<div class=\"monaco-status\">\n<span class=\"monaco-status-left\">\u25cf Pr\u00eat<\/span><br \/>\n<span class=\"monaco-status-right\">Monaco Editor v0.45<\/span>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"wpa-accordion-item\">\n<button class=\"wpa-accordion-header\" data-wpa-target=\"#accordion-2-4-composants-ui-modernes-item-4\" aria-expanded=\"false\"><span class=\"wpa-accordion-title\"><span class=\"wpa-accordion-number\">04<\/span> Composants UI avanc\u00e9s et layouts modernes<\/span><span class=\"wpa-accordion-icon\"><\/span><\/button><\/p>\n<div id=\"accordion-2-4-composants-ui-modernes-item-4\" class=\"wpa-accordion-body\">\n<div class=\"wpa-accordion-content\">\n<h4>Architecture de composants CSS modulaires<\/h4>\n<p>Les composants UI modernes n\u00e9cessitent une architecture CSS scalable et maintenable. L&rsquo;approche BEM (Block Element Modifier) combin\u00e9e aux custom properties CSS permet de cr\u00e9er des composants r\u00e9utilisables et th\u00e9matisables. Les variables CSS (&#8211;variable-name) centralisent les valeurs de design (couleurs, espacements, rayons de bordure) et facilitent les variations de th\u00e8me. L&rsquo;utilisation de classes d&rsquo;\u00e9tat (.is-active, .is-disabled, .is-expanded) s\u00e9pare la logique visuelle de la structure HTML. Les techniques de composition CSS comme l&rsquo;h\u00e9ritage de propri\u00e9t\u00e9s et la cascade permettent de cr\u00e9er des variations de composants sans dupliquer le code de base.<\/p>\n<h4>Layouts avanc\u00e9s avec CSS Grid et Flexbox<\/h4>\n<p>CSS Grid et Flexbox offrent des possibilit\u00e9s de mise en page sophistiqu\u00e9es pour les composants modernes. Grid excelle dans les layouts bidimensionnels complexes, permettant de cr\u00e9er des interfaces adaptatives avec grid-template-areas et des colonnes\/lignes dynamiques. La propri\u00e9t\u00e9 subgrid (support croissant) permet l&rsquo;alignement parfait des \u00e9l\u00e9ments imbriqu\u00e9s. Flexbox reste id\u00e9al pour les composants unidimensionnels et l&rsquo;alignement pr\u00e9cis des \u00e9l\u00e9ments. Les techniques avanc\u00e9es incluent l&rsquo;utilisation de gap pour les espacements, aspect-ratio pour les proportions et les fonctions min(), max(), clamp() pour des dimensions responsives sophistiqu\u00e9es.<\/p>\n<div class=\"info-box\">\n<p><strong>Point cl\u00e9<\/strong> : Les custom properties CSS h\u00e9ritent en cascade, permettant de cr\u00e9er des th\u00e8mes et variations de composants avec une approche d\u00e9clarative et performante.<\/p>\n<\/div>\n<div class=\"tuto-objectif\" style=\"background: #f5f5f5; border-left: 4px solid #667eea; padding: 16px 20px; margin-top: 24px; border-radius: 0 8px 8px 0;\">\n<h3 style=\"color: #667eea; margin: 0 0 8px 0; font-size: 16px;\">\u00c0 retenir<\/h3>\n<p style=\"margin: 0; color: #333;\">L&rsquo;architecture CSS moderne combine custom properties, layouts avanc\u00e9s et m\u00e9thodologies de nommage pour cr\u00e9er des composants maintenables et \u00e9volutifs.<\/p>\n<\/div>\n<div class=\"tuto-exercise\" style=\"background: #fff3e0; border-left: 4px solid #ff9800; padding: 16px 20px; margin-top: 20px; border-radius: 0 8px 8px 0;\">\n<h4 style=\"color: #ff9800; margin: 0 0 8px 0; font-size: 15px;\">\ud83c\udfaf Mini-exercice : Dashboard layout avec Grid et composants th\u00e9matisables<\/h4>\n<p style=\"margin: 0; color: #333; font-size: 14px;\">Cr\u00e9ez un layout de dashboard responsive utilisant CSS Grid avec des cartes th\u00e9matisables via custom properties et des animations d&rsquo;entr\u00e9e s\u00e9quentielles.<\/p>\n<\/div>\n<div class=\"codepen-block\" data-block-id=\"exercise-4\">\n<p class=\"codepen-block-label\">Code de r\u00e9f\u00e9rence :<\/p>\n<div class=\"codepen-header\">\n<div class=\"codepen-tabs\">\n<button class=\"codepen-tab active\" data-tab=\"html\">HTML<\/button><br \/>\n<button class=\"codepen-tab\" data-tab=\"css\">CSS<\/button><br \/>\n<button class=\"codepen-tab\" data-tab=\"javascript\">JS<\/button>\n<\/div>\n<p><button class=\"codepen-copy-btn\">Copier<\/button>\n<\/div>\n<div class=\"codepen-code-container\">\n<pre class=\"codepen-code active\" data-lang=\"html\">&lt;div class=\"dashboard\" data-theme=\"default\"&gt;\n  &lt;header class=\"dashboard-header\"&gt;\n    &lt;h1&gt;Dashboard UI&lt;\/h1&gt;\n    &lt;div class=\"theme-switcher\"&gt;\n      &lt;button data-theme=\"default\"&gt;Default&lt;\/button&gt;\n      &lt;button data-theme=\"dark\"&gt;Dark&lt;\/button&gt;\n      &lt;button data-theme=\"colorful\"&gt;Colorful&lt;\/button&gt;\n    &lt;\/div&gt;\n  &lt;\/header&gt;\n  \n  &lt;div class=\"dashboard-grid\"&gt;\n    &lt;div class=\"dashboard-card\" style=\"--delay: 0s\"&gt;\n      &lt;h3&gt;Analytics&lt;\/h3&gt;\n      &lt;div class=\"card-metric\"&gt;1,234&lt;\/div&gt;\n      &lt;p&gt;Total Users&lt;\/p&gt;\n    &lt;\/div&gt;\n    \n    &lt;div class=\"dashboard-card\" style=\"--delay: 0.1s\"&gt;\n      &lt;h3&gt;Revenue&lt;\/h3&gt;\n      &lt;div class=\"card-metric\"&gt;\u20ac45,678&lt;\/div&gt;\n      &lt;p&gt;This Month&lt;\/p&gt;\n    &lt;\/div&gt;\n    \n    &lt;div class=\"dashboard-card dashboard-card--wide\" style=\"--delay: 0.2s\"&gt;\n      &lt;h3&gt;Performance&lt;\/h3&gt;\n      &lt;div class=\"performance-bars\"&gt;\n        &lt;div class=\"perf-bar\" style=\"--width: 75%\"&gt;&lt;\/div&gt;\n        &lt;div class=\"perf-bar\" style=\"--width: 60%\"&gt;&lt;\/div&gt;\n        &lt;div class=\"perf-bar\" style=\"--width: 90%\"&gt;&lt;\/div&gt;\n      &lt;\/div&gt;\n    &lt;\/div&gt;\n    \n    &lt;div class=\"dashboard-card\" style=\"--delay: 0.3s\"&gt;\n      &lt;h3&gt;Status&lt;\/h3&gt;\n      &lt;div class=\"status-indicator\"&gt;&lt;\/div&gt;\n      &lt;p&gt;System Online&lt;\/p&gt;\n    &lt;\/div&gt;\n  &lt;\/div&gt;\n&lt;\/div&gt;<\/pre>\n<pre class=\"codepen-code\" data-lang=\"css\">:root {\n  --primary-color: #667eea;\n  --secondary-color: #764ba2;\n  --background: #f8fafc;\n  --card-background: white;\n  --text-primary: #1a202c;\n  --text-secondary: #4a5568;\n  --border-color: #e2e8f0;\n  --shadow: 0 4px 6px rgba(0, 0, 0, 0.05);\n}\n\n[data-theme=\"dark\"] {\n  --primary-color: #9f7aea;\n  --secondary-color: #667eea;\n  --background: #1a202c;\n  --card-background: #2d3748;\n  --text-primary: #f7fafc;\n  --text-secondary: #cbd5e0;\n  --border-color: #4a5568;\n  --shadow: 0 4px 6px rgba(0, 0, 0, 0.3);\n}\n\n[data-theme=\"colorful\"] {\n  --primary-color: #ff6b6b;\n  --secondary-color: #4ecdc4;\n  --background: #ffe66d;\n  --card-background: white;\n  --text-primary: #2c3e50;\n  --text-secondary: #7f8c8d;\n  --border-color: #f39c12;\n  --shadow: 0 8px 25px rgba(255, 107, 107, 0.15);\n}\n\n.dashboard {\n  background: var(--background);\n  min-height: 100vh;\n  padding: 20px;\n  color: var(--text-primary);\n  transition: all 0.4s ease;\n}\n\n.dashboard-header {\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  margin-bottom: 30px;\n}\n\n.theme-switcher button {\n  background: var(--card-background);\n  color: var(--text-primary);\n  border: 1px solid var(--border-color);\n  padding: 8px 16px;\n  margin-left: 8px;\n  border-radius: 6px;\n  cursor: pointer;\n  transition: all 0.2s ease;\n}\n\n.theme-switcher button:hover {\n  background: var(--primary-color);\n  color: white;\n}\n\n.dashboard-grid {\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));\n  gap: 24px;\n  max-width: 1200px;\n}\n\n.dashboard-card {\n  background: var(--card-background);\n  border-radius: 12px;\n  padding: 24px;\n  box-shadow: var(--shadow);\n  border: 1px solid var(--border-color);\n  transition: all 0.3s ease;\n  animation: cardEnter 0.6s ease forwards;\n  animation-delay: var(--delay);\n  opacity: 0;\n  transform: translateY(20px);\n}\n\n@keyframes cardEnter {\n  to {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n\n.dashboard-card:hover {\n  transform: translateY(-4px);\n  box-shadow: 0 12px 25px rgba(0, 0, 0, 0.1);\n}\n\n.dashboard-card--wide {\n  grid-column: span 2;\n}\n\n.card-metric {\n  font-size: 2.5rem;\n  font-weight: bold;\n  color: var(--primary-color);\n  margin: 12px 0;\n}\n\n.performance-bars {\n  display: flex;\n  flex-direction: column;\n  gap: 12px;\n  margin-top: 16px;\n}\n\n.perf-bar {\n  height: 8px;\n  background: var(--border-color);\n  border-radius: 4px;\n  position: relative;\n  overflow: hidden;\n}\n\n.perf-bar::before {\n  content: '';\n  position: absolute;\n  left: 0;\n  top: 0;\n  height: 100%;\n  width: var(--width);\n  background: linear-gradient(90deg, var(--primary-color), var(--secondary-color));\n  border-radius: 4px;\n  animation: barFill 1s ease 0.5s forwards;\n  transform: scaleX(0);\n  transform-origin: left;\n}\n\n@keyframes barFill {\n  to {\n    transform: scaleX(1);\n  }\n}\n\n.status-indicator {\n  width: 16px;\n  height: 16px;\n  border-radius: 50%;\n  background: #48bb78;\n  animation: pulse 2s infinite;\n  margin: 12px 0;\n}\n\n@keyframes pulse {\n  0%, 100% {\n    box-shadow: 0 0 0 0 rgba(72, 187, 120, 0.4);\n  }\n  50% {\n    box-shadow: 0 0 0 10px rgba(72, 187, 120, 0);\n  }\n}<\/pre>\n<pre class=\"codepen-code\" data-lang=\"javascript\">document.addEventListener('DOMContentLoaded', function() {\n  const dashboard = document.querySelector('.dashboard');\n  const themeButtons = document.querySelectorAll('[data-theme]');\n  \n  themeButtons.forEach(button => {\n    button.addEventListener('click', () => {\n      const theme = button.getAttribute('data-theme');\n      dashboard.setAttribute('data-theme', theme);\n      \n      \/\/ R\u00e9animer les cartes\n      const cards = document.querySelectorAll('.dashboard-card');\n      cards.forEach((card, index) => {\n        card.style.animation = 'none';\n        card.offsetHeight; \/\/ Force reflow\n        card.style.animation = `cardEnter 0.4s ease forwards`;\n        card.style.animationDelay = `${index * 0.05}s`;\n      });\n    });\n  });\n});<\/pre>\n<\/div>\n<\/div>\n<div class=\"monaco-sandbox\" data-block-id=\"exercise-4\">\n<div class=\"monaco-header\">\n<div class=\"monaco-tabs\">\n<button class=\"monaco-tab active\" data-lang=\"html\">HTML<\/button><br \/>\n<button class=\"monaco-tab\" data-lang=\"css\">CSS<\/button><br \/>\n<button class=\"monaco-tab\" data-lang=\"javascript\">JS<\/button>\n<\/div>\n<div class=\"monaco-actions\">\n<button class=\"monaco-btn monaco-btn-run\">\u25b6 Ex\u00e9cuter<\/button><br \/>\n<button class=\"monaco-btn monaco-btn-reset\">\u21ba Reset<\/button>\n<\/div>\n<\/div>\n<div class=\"monaco-container\">\n<div class=\"monaco-editor-wrapper\">\n<div class=\"monaco-editor-pane active\" data-lang=\"html\"><\/div>\n<div class=\"monaco-editor-pane\" data-lang=\"css\"><\/div>\n<div class=\"monaco-editor-pane\" data-lang=\"javascript\"><\/div>\n<\/div>\n<div class=\"monaco-preview-wrapper\">\n<div class=\"monaco-preview-header\">Result<\/div>\n<\/div>\n<\/div>\n<div class=\"monaco-status\">\n<span class=\"monaco-status-left\">\u25cf Pr\u00eat<\/span><br \/>\n<span class=\"monaco-status-right\">Monaco Editor v0.45<\/span>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"wpa-accordion-item\">\n<button class=\"wpa-accordion-header\" data-wpa-target=\"#accordion-2-4-composants-ui-modernes-item-5\" aria-expanded=\"false\"><span class=\"wpa-accordion-title\"><span class=\"wpa-accordion-number\">05<\/span> Optimisation et accessibilit\u00e9 des animations<\/span><span class=\"wpa-accordion-icon\"><\/span><\/button><\/p>\n<div id=\"accordion-2-4-composants-ui-modernes-item-5\" class=\"wpa-accordion-body\">\n<div class=\"wpa-accordion-content\">\n<h4>Performance des animations CSS<\/h4>\n<p>L&rsquo;optimisation des animations CSS est cruciale pour maintenir une interface fluide \u00e0 60fps. Les propri\u00e9t\u00e9s transform et opacity sont les seules \u00e0 d\u00e9clencher uniquement la composition, \u00e9vitant le repaint co\u00fbteux. L&rsquo;utilisation de will-change informe le navigateur des animations \u00e0 venir, permettant l&rsquo;optimisation GPU pr\u00e9alable. Cependant, cette propri\u00e9t\u00e9 doit \u00eatre utilis\u00e9e avec parcimonie et supprim\u00e9e apr\u00e8s l&rsquo;animation. Les techniques d&rsquo;optimisation incluent la r\u00e9duction du nombre d&rsquo;\u00e9l\u00e9ments anim\u00e9s simultan\u00e9ment, l&rsquo;utilisation de transform3d() pour forcer l&rsquo;acc\u00e9l\u00e9ration mat\u00e9rielle, et la limitation des animations complexes sur les appareils moins performants via les media queries de performance.<\/p>\n<h4>Accessibilit\u00e9 et respect des pr\u00e9f\u00e9rences utilisateur<\/h4>\n<p>L&rsquo;accessibilit\u00e9 des animations n\u00e9cessite une attention particuli\u00e8re aux utilisateurs sensibles au mouvement. La media query prefers-reduced-motion permet de d\u00e9tecter cette pr\u00e9f\u00e9rence syst\u00e8me et d&rsquo;adapter les animations en cons\u00e9quence. Les alternatives incluent la r\u00e9duction de la dur\u00e9e, l&rsquo;\u00e9limination des mouvements r\u00e9p\u00e9titifs ou la transformation des animations en transitions instantan\u00e9es. L&rsquo;accessibilit\u00e9 clavier doit \u00eatre pr\u00e9serv\u00e9e : les \u00e9l\u00e9ments interactifs anim\u00e9s doivent rester focusables et leurs \u00e9tats focus clairement visibles. Les animations ne doivent jamais masquer d&rsquo;informations critiques ou emp\u00eacher l&rsquo;interaction normale avec l&rsquo;interface.<\/p>\n<div class=\"info-box\">\n<p><strong>Point cl\u00e9<\/strong> : Toujours tester les animations sur des appareils moins performants et impl\u00e9menter prefers-reduced-motion pour une exp\u00e9rience inclusive.<\/p>\n<\/div>\n<div class=\"tuto-objectif\" style=\"background: #f5f5f5; border-left: 4px solid #667eea; padding: 16px 20px; margin-top: 24px; border-radius: 0 8px 8px 0;\">\n<h3 style=\"color: #667eea; margin: 0 0 8px 0; font-size: 16px;\">\u00c0 retenir<\/h3>\n<p style=\"margin: 0; color: #333;\">Les animations performantes et accessibles utilisent les propri\u00e9t\u00e9s optimis\u00e9es, respectent les pr\u00e9f\u00e9rences utilisateur et maintiennent l&rsquo;utilisabilit\u00e9 sur tous les appareils.<\/p>\n<\/div>\n<div class=\"tuto-exercise\" style=\"background: #fff3e0; border-left: 4px solid #ff9800; padding: 16px 20px; margin-top: 20px; border-radius: 0 8px 8px 0;\">\n<h4 style=\"color: #ff9800; margin: 0 0 8px 0; font-size: 15px;\">\ud83c\udfaf Mini-exercice : Syst\u00e8me d&rsquo;animation respectueux des pr\u00e9f\u00e9rences<\/h4>\n<p style=\"margin: 0; color: #333; font-size: 14px;\">Cr\u00e9ez un composant avec animations qui s&rsquo;adapte automatiquement aux pr\u00e9f\u00e9rences de mouvement et inclut des alternatives accessibles.<\/p>\n<\/div>\n<div class=\"codepen-block\" data-block-id=\"exercise-5\">\n<p class=\"codepen-block-label\">Code de r\u00e9f\u00e9rence :<\/p>\n<div class=\"codepen-header\">\n<div class=\"codepen-tabs\">\n<button class=\"codepen-tab active\" data-tab=\"html\">HTML<\/button><br \/>\n<button class=\"codepen-tab\" data-tab=\"css\">CSS<\/button><br \/>\n<button class=\"codepen-tab\" data-tab=\"javascript\">JS<\/button>\n<\/div>\n<p><button class=\"codepen-copy-btn\">Copier<\/button>\n<\/div>\n<div class=\"codepen-code-container\">\n<pre class=\"codepen-code active\" data-lang=\"html\">&lt;div class=\"accessible-demo\"&gt;\n  &lt;h2&gt;Animation Accessibility Demo&lt;\/h2&gt;\n  \n  &lt;div class=\"preference-info\"&gt;\n    &lt;p&gt;Your motion preference: &lt;span id=\"motionPreference\"&gt;Detecting...&lt;\/span&gt;&lt;\/p&gt;\n    &lt;button id=\"toggleMotion\"&gt;Toggle Animation Mode&lt;\/button&gt;\n  &lt;\/div&gt;\n  \n  &lt;div class=\"animated-cards\"&gt;\n    &lt;div class=\"anim-card\" tabindex=\"0\"&gt;\n      &lt;h3&gt;Performance&lt;\/h3&gt;\n      &lt;p&gt;Optimized animations using transform and opacity&lt;\/p&gt;\n      &lt;div class=\"card-icon\"&gt;\u26a1&lt;\/div&gt;\n    &lt;\/div&gt;\n    \n    &lt;div class=\"anim-card\" tabindex=\"0\"&gt;\n      &lt;h3&gt;Accessibility&lt;\/h3&gt;\n      &lt;p&gt;Respects prefers-reduced-motion settings&lt;\/p&gt;\n      &lt;div class=\"card-icon\"&gt;\u267f&lt;\/div&gt;\n    &lt;\/div&gt;\n    \n    &lt;div class=\"anim-card\" tabindex=\"0\"&gt;\n      &lt;h3&gt;Responsive&lt;\/h3&gt;\n      &lt;p&gt;Adapts to different devices and preferences&lt;\/p&gt;\n      &lt;div class=\"card-icon\"&gt;\ud83d\udcf1&lt;\/div&gt;\n    &lt;\/div&gt;\n  &lt;\/div&gt;\n&lt;\/div&gt;<\/pre>\n<pre class=\"codepen-code\" data-lang=\"css\">\/* Variables pour les animations *\/\n:root {\n  --animation-duration: 0.3s;\n  --animation-scale: 1.05;\n  --animation-translate: -8px;\n}\n\n\/* Mode r\u00e9duit pour prefers-reduced-motion *\/\n@media (prefers-reduced-motion: reduce) {\n  :root {\n    --animation-duration: 0.1s;\n    --animation-scale: 1.02;\n    --animation-translate: -2px;\n  }\n  \n  * {\n    animation-duration: 0.01ms !important;\n    animation-iteration-count: 1 !important;\n    transition-duration: 0.01ms !important;\n  }\n}\n\n.accessible-demo {\n  max-width: 1000px;\n  margin: 0 auto;\n  padding: 20px;\n  font-family: 'Segoe UI', sans-serif;\n}\n\n.preference-info {\n  background: #f0f4f8;\n  padding: 20px;\n  border-radius: 8px;\n  margin-bottom: 30px;\n  text-align: center;\n}\n\n#motionPreference {\n  font-weight: bold;\n  color: #667eea;\n}\n\n#toggleMotion {\n  background: #667eea;\n  color: white;\n  border: none;\n  padding: 10px 20px;\n  border-radius: 6px;\n  cursor: pointer;\n  margin-top: 10px;\n  transition: background-color var(--animation-duration) ease;\n}\n\n#toggleMotion:hover {\n  background: #5a67d8;\n}\n\n#toggleMotion:focus {\n  outline: 2px solid #667eea;\n  outline-offset: 2px;\n}\n\n.animated-cards {\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));\n  gap: 24px;\n}\n\n.anim-card {\n  background: white;\n  border-radius: 12px;\n  padding: 24px;\n  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);\n  border: 2px solid transparent;\n  transition: all var(--animation-duration) cubic-bezier(0.4, 0, 0.2, 1);\n  position: relative;\n  cursor: pointer;\n  \/* Optimisation GPU *\/\n  will-change: transform;\n}\n\n.anim-card:hover {\n  transform: translateY(var(--animation-translate)) scale(var(--animation-scale));\n  box-shadow: 0 12px 25px rgba(0, 0, 0, 0.15);\n}\n\n.anim-card:focus {\n  outline: none;\n  border-color: #667eea;\n  transform: translateY(var(--animation-translate)) scale(var(--animation-scale));\n}\n\n.card-icon {\n  position: absolute;\n  top: 20px;\n  right: 20px;\n  font-size: 24px;\n  opacity: 0.7;\n  transition: all var(--animation-duration) ease;\n}\n\n.anim-card:hover .card-icon,\n.anim-card:focus .card-icon {\n  opacity: 1;\n  transform: scale(1.2);\n}\n\n\/* Mode animation r\u00e9duite personnalis\u00e9 *\/\n.reduce-motion .anim-card {\n  --animation-duration: 0.1s;\n  --animation-scale: 1.01;\n  --animation-translate: -1px;\n}\n\n.reduce-motion .anim-card:hover,\n.reduce-motion .anim-card:focus {\n  background: #f7fafc;\n}\n\n\/* Animations d'entr\u00e9e avec staggering *\/\n.anim-card {\n  animation: cardFadeIn 0.6s ease forwards;\n  opacity: 0;\n  transform: translateY(20px);\n}\n\n.anim-card:nth-child(1) { animation-delay: 0.1s; }\n.anim-card:nth-child(2) { animation-delay: 0.2s; }\n.anim-card:nth-child(3) { animation-delay: 0.3s; }\n\n@keyframes cardFadeIn {\n  to {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n\n\/* Suppression des animations en mode r\u00e9duit *\/\n@media (prefers-reduced-motion: reduce) {\n  .anim-card {\n    animation: none;\n    opacity: 1;\n    transform: none;\n  }\n}\n\n\/* Indicateur visuel pour les animations *\/\n.animation-indicator {\n  position: fixed;\n  top: 10px;\n  right: 10px;\n  padding: 8px 12px;\n  background: rgba(0, 0, 0, 0.8);\n  color: white;\n  border-radius: 4px;\n  font-size: 12px;\n  z-index: 1000;\n}<\/pre>\n<pre class=\"codepen-code\" data-lang=\"javascript\">document.addEventListener('DOMContentLoaded', function() {\n  const motionPreferenceSpan = document.getElementById('motionPreference');\n  const toggleMotionBtn = document.getElementById('toggleMotion');\n  const demoContainer = document.querySelector('.accessible-demo');\n  \n  \/\/ D\u00e9tecter la pr\u00e9f\u00e9rence de mouvement\n  function checkMotionPreference() {\n    const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n    return prefersReducedMotion;\n  }\n  \n  \/\/ Mettre \u00e0 jour l'affichage des pr\u00e9f\u00e9rences\n  function updatePreferenceDisplay() {\n    const isReduced = checkMotionPreference() || demoContainer.classList.contains('reduce-motion');\n    motionPreferenceSpan.textContent = isReduced ? 'Reduced Motion' : 'Full Animation';\n    motionPreferenceSpan.style.color = isReduced ? '#e53e3e' : '#38a169';\n  }\n  \n  \/\/ Toggle manuel du mode animation\n  toggleMotionBtn.addEventListener('click', function() {\n    demoContainer.classList.toggle('reduce-motion');\n    updatePreferenceDisplay();\n    \n    \/\/ Feedback visuel\n    this.textContent = demoContainer.classList.contains('reduce-motion') ? \n      'Enable Full Animations' : 'Reduce Animations';\n  });\n  \n  \/\/ \u00c9couter les changements de pr\u00e9f\u00e9rence syst\u00e8me\n  const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');\n  mediaQuery.addEventListener('change', updatePreferenceDisplay);\n  \n  \/\/ Gestion de l'accessibilit\u00e9 clavier\n  const cards = document.querySelectorAll('.anim-card');\n  cards.forEach(card => {\n    card.addEventListener('keydown', function(e) {\n      if (e.key === 'Enter' || e.key === ' ') {\n        e.preventDefault();\n        this.click();\n      }\n    });\n    \n    card.addEventListener('click', function() {\n      \/\/ Animation de feedback au clic\n      this.style.transform = 'scale(0.95)';\n      setTimeout(() => {\n        this.style.transform = '';\n      }, 150);\n    });\n  });\n  \n  \/\/ Optimisation will-change\n  cards.forEach(card => {\n    card.addEventListener('mouseenter', () => {\n      card.style.willChange = 'transform, box-shadow';\n    });\n    \n    card.addEventListener('mouseleave', () => {\n      card.style.willChange = 'auto';\n    });\n  });\n  \n  \/\/ Initialisation\n  updatePreferenceDisplay();\n  \n  \/\/ Cr\u00e9er un indicateur d'animation\n  const indicator = document.createElement('div');\n  indicator.className = 'animation-indicator';\n  indicator.textContent = 'GPU Accelerated';\n  document.body.appendChild(indicator);\n});<\/pre>\n<\/div>\n<\/div>\n<div class=\"monaco-sandbox\" data-block-id=\"exercise-5\">\n<div class=\"monaco-header\">\n<div class=\"monaco-tabs\">\n<button class=\"monaco-tab active\" data-lang=\"html\">HTML<\/button><br \/>\n<button class=\"monaco-tab\" data-lang=\"css\">CSS<\/button><br \/>\n<button class=\"monaco-tab\" data-lang=\"javascript\">JS<\/button>\n<\/div>\n<div class=\"monaco-actions\">\n<button class=\"monaco-btn monaco-btn-run\">\u25b6 Ex\u00e9cuter<\/button><br \/>\n<button class=\"monaco-btn monaco-btn-reset\">\u21ba Reset<\/button>\n<\/div>\n<\/div>\n<div class=\"monaco-container\">\n<div class=\"monaco-editor-wrapper\">\n<div class=\"monaco-editor-pane active\" data-lang=\"html\"><\/div>\n<div class=\"monaco-editor-pane\" data-lang=\"css\"><\/div>\n<div class=\"monaco-editor-pane\" data-lang=\"javascript\"><\/div>\n<\/div>\n<div class=\"monaco-preview-wrapper\">\n<div class=\"monaco-preview-header\">Result<\/div>\n<\/div>\n<\/div>\n<div class=\"monaco-status\">\n<span class=\"monaco-status-left\">\u25cf Pr\u00eat<\/span><br \/>\n<span class=\"monaco-status-right\">Monaco Editor v0.45<\/span>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h2>R\u00e9capitulatif<\/h2>\n<div class=\"tuto-recap\" style=\"background: #f5f5f5; border-left: 4px solid #9c27b0; padding: 16px 20px; border-radius: 0 8px 8px 0;\">\n<h3 style=\"color: #9c27b0; margin: 0 0 12px 0; font-size: 16px;\">Points essentiels \u00e0 retenir<\/h3>\n<ul style=\"margin: 0; padding-left: 20px; color: #333;\">\n<li><strong>Animations CSS avanc\u00e9es<\/strong> : Les propri\u00e9t\u00e9s transform et @keyframes permettent de cr\u00e9er des effets visuels sophistiqu\u00e9s avec des performances optimales gr\u00e2ce \u00e0 l&rsquo;acc\u00e9l\u00e9ration GPU<\/li>\n<li><strong>Effets visuels modernes<\/strong> : Le glassmorphism avec backdrop-filter et les gradients anim\u00e9s cr\u00e9ent des interfaces contemporaines et visuellement attrayantes<\/li>\n<li><strong>Micro-interactions<\/strong> : Les transitions subtiles et le feedback visuel am\u00e9liorent l&rsquo;exp\u00e9rience utilisateur en cr\u00e9ant des interfaces r\u00e9actives et intuitives<\/li>\n<li><strong>Architecture modulaire<\/strong> : Les custom properties CSS et les m\u00e9thodologies de nommage permettent de cr\u00e9er des composants r\u00e9utilisables et th\u00e9matisables<\/li>\n<li><strong>Accessibilit\u00e9 et performance<\/strong> : Le respect de prefers-reduced-motion et l&rsquo;optimisation des animations garantissent une exp\u00e9rience inclusive sur tous les appareils<\/li>\n<\/ul>\n<\/div>\n<h2>Sources<\/h2>\n<div class=\"sources-box\" style=\"background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%); border: 1px solid #cbd5e1; border-radius: 12px; padding: 16px; margin-bottom: 24px;\">\n<p style=\"color: #64748b; margin: 0 0 12px 0; font-size: 13px;\">Pour approfondir vos connaissances :<\/p>\n<ul style=\"margin: 0; padding-left: 0; list-style: none;\">\n<li style=\"margin-bottom: 8px;\">\n<a href=\"https:\/\/developer.mozilla.org\/fr\/docs\/Web\/CSS\/CSS_Animations\" target=\"_blank\" rel=\"noopener noreferrer\" style=\"display: flex; align-items: center; gap: 10px; padding: 10px 14px; background: white; border-radius: 8px; text-decoration: none; color: #1e293b; border: 1px solid #e2e8f0;\"><br \/>\n<span style=\"color: #94a3b8;\">\ud83d\udd17<\/span><br \/>\n<span style=\"flex: 1; font-weight: 500; color: #0f172a;\">MDN &#8211; Animations CSS avanc\u00e9es et bonnes pratiques<\/span><br \/>\n<span style=\"color: #94a3b8;\">\u2192<\/span><br \/>\n<\/a>\n<\/li>\n<li style=\"margin-bottom: 0;\">\n<a href=\"https:\/\/css-tricks.com\/almanac\/properties\/a\/animation\/\" target=\"_blank\" rel=\"noopener noreferrer\" style=\"display: flex; align-items: center; gap: 10px; padding: 10px 14px; background: white; border-radius: 8px; text-decoration: none; color: #1e293b; border: 1px solid #e2e8f0;\"><br \/>\n<span style=\"color: #94a3b8;\">\ud83d\udd17<\/span><br \/>\n<span style=\"flex: 1; font-weight: 500; color: #0f172a;\">CSS-Tricks &#8211; Guide complet des animations et micro-interactions<\/span><br \/>\n<span style=\"color: #94a3b8;\">\u2192<\/span><br \/>\n<\/a>\n<\/li>\n<\/ul>\n<\/div>\n<h2>Validez vos connaissances<\/h2>\n<p>Testez votre compr\u00e9hension avec ce quiz de 10 questions :<\/p>\n<p>[<\/p>\n<h2>Validez vos connaissances<\/h2>\n<p>Testez votre compr\u00e9hension avec ce quiz de 10 questions :<\/p>\n<div id=\"quiz-block-1\" class=\"quiz-container\" data-quiz-json=\"https:\/\/lmspro.fr\/wp-content\/plugins\/generate-article-endpoint\/quiz-data\/en\/quiz-2-4-composants-ui-modernes.json\" aria-label=\"Interactive Quiz\"><div class=\"quiz-loading\" role=\"status\" aria-live=\"polite\"><span class=\"quiz-sr-only\">Loading quiz...<\/span><\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>2.4 Modern UI Components Explore your creativity to develop advanced CSS animations and create engaging modern UI components. In this lesson, we&#039;ll discover how to design dynamic user interfaces that combine modern aesthetics with advanced functionality using the latest CSS techniques. Module: Module 1: Technical Web Fundamentals Level\u2026 <a href=\"https:\/\/lmspro.fr\/en\/composants-ui-modernes-2\/\" class=\"more-link\">Read More<span class=\"screen-reader-text\"> \u00ab\u00a0Composants UI modernes\u00a0\u00bb<\/span> &raquo;<\/a><\/p>","protected":false},"author":1,"featured_media":563,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[168,38],"tags":[34,25,26,132,27,28,133,2],"class_list":["post-562","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-composants-ui","category-module-3-ux-ui-produit","tag-accessibilite","tag-animation","tag-css","tag-fondamentaux-web","tag-html","tag-javascript","tag-js","tag-ux"],"_links":{"self":[{"href":"https:\/\/lmspro.fr\/en\/wp-json\/wp\/v2\/posts\/562","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lmspro.fr\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lmspro.fr\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lmspro.fr\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lmspro.fr\/en\/wp-json\/wp\/v2\/comments?post=562"}],"version-history":[{"count":2,"href":"https:\/\/lmspro.fr\/en\/wp-json\/wp\/v2\/posts\/562\/revisions"}],"predecessor-version":[{"id":633,"href":"https:\/\/lmspro.fr\/en\/wp-json\/wp\/v2\/posts\/562\/revisions\/633"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/lmspro.fr\/en\/wp-json\/wp\/v2\/media\/563"}],"wp:attachment":[{"href":"https:\/\/lmspro.fr\/en\/wp-json\/wp\/v2\/media?parent=562"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lmspro.fr\/en\/wp-json\/wp\/v2\/categories?post=562"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lmspro.fr\/en\/wp-json\/wp\/v2\/tags?post=562"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}