Skeleton screen : définition, CSS et choix face au spinner

Skeleton screen : définition, intérêt pour l'expérience utilisateur, mise en place en CSS pas à pas et critères pour le préférer à un spinner sur votre site.

Maquette de page en cours de chargement avec des blocs gris, exemple de skeleton screen

Qu'est-ce qu'un skeleton screen ?

Un skeleton screen est un écran de chargement qui montre la structure de la page avant son contenu : des rectangles et des cercles gris prennent la place des titres, des photos, des prix ou des avatars. L'utilisateur voit tout de suite à quoi ressemblera la page, et chaque bloc est remplacé par la vraie donnée dès qu'elle arrive. En français, on parle aussi d'écran squelette ou de squelette de chargement.

Le principe a été popularisé vers 2013 par le designer Luke Wroblewski, qui défendait l'idée d'éviter les indicateurs de chargement génériques sur mobile. Depuis, les skeleton screens sont devenus courants sur les réseaux sociaux, les sites e-commerce, les plateformes vidéo et les applications métier. Le terme anglais skeleton screen ui désigne le même composant d'interface.

Ce qui le distingue d'un spinner

Un spinner, c'est l'icône qui tourne au milieu d'un écran vide. Il dit seulement « ça charge », sans rien montrer d'autre. Le skeleton, lui, montre déjà la mise en page : le cerveau commence à lire la structure, repère où sera le titre et où sera le bouton. L'attente reste la même, mais elle paraît plus courte parce que l'on voit l'interface se construire.

À quoi sert un skeleton screen pour l'expérience utilisateur ?

Le but n'est pas d'accélérer le site. Un skeleton screen ne raccourcit pas le temps de réponse du serveur. Il agit sur la perception : ce que le visiteur ressent pendant ces quelques secondes. Pour une PME, cette différence compte, car un visiteur qui croit que la page est cassée repart chez un concurrent.

Réduire le temps d'attente perçu

Les travaux de Jakob Nielsen sur les temps de réponse donnent un repère utile : autour d'une seconde, l'utilisateur sent l'attente mais garde le fil, et au-delà de dix secondes il décroche. Entre les deux, tout ce qui montre que le site avance aide à le retenir. Le skeleton screen loading remplit ce rôle : il occupe l'œil et annonce un résultat précis plutôt qu'une promesse vague.

Éviter la page blanche et les sauts de mise en page

Une page blanche fait douter : le lien est-il mort, la connexion a-t-elle sauté ? Avec un squelette, il se passe quelque chose à l'écran dès le premier instant. Et si les blocs gris ont les mêmes dimensions que le contenu final, rien ne bouge quand les données arrivent. C'est un vrai gain pour le CLS, l'indicateur de stabilité visuelle suivi dans les Core Web Vitals de Google.

Garder le visiteur dans le parcours

Sur une fiche produit, un tableau de bord ou une page de résultats, le skeleton montre tout de suite où se trouveront les éléments importants : prix, bouton d'achat, filtres. Le visiteur sait où regarder avant même que tout soit chargé. Ce confort joue sur le taux de rebond, surtout sur mobile, où les connexions sont plus lentes et plus irrégulières.

Comment mettre en place un skeleton screen en CSS

Pas besoin de bibliothèque pour un premier skeleton : un peu de HTML et quelques règles CSS suffisent. La logique est toujours la même. On affiche des blocs neutres pendant que le JavaScript récupère les données, souvent via une API, puis on les remplace par le vrai contenu.

Étape 1 : reproduire la structure avec des blocs vides

On part de la carte ou de la ligne de liste finale, et on remplace chaque élément par une div vide de même taille. Pour une carte produit, cela donne en général une image, une ligne de titre, une ligne plus courte pour le prix et un rectangle pour le bouton. Le conteneur reçoit l'attribut aria-busy à true pour signaler aux lecteurs d'écran que la zone est en cours de chargement.

  • Un bloc .skeleton-image avec un ratio fixe, par exemple aspect-ratio: 4 / 3, pour réserver la place de la photo.
  • Un bloc .skeleton-line de la largeur du titre, puis une seconde ligne à environ 60 % de largeur pour imiter un texte qui finit plus tôt.
  • Un bloc .skeleton-button aux dimensions exactes du futur bouton.
  • Un cercle .skeleton-avatar avec border-radius: 50 % si la carte affiche une photo de profil.

Étape 2 : donner le style de base

Tous les blocs partagent une classe commune, .skeleton, avec une couleur de fond gris clair, des coins légèrement arrondis et une hauteur fixe pour les lignes de texte. Les dimensions doivent coller à la typographie réelle : si le titre fait 20 pixels de haut avec son interligne, la ligne grise aussi. C'est ce détail qui évite le saut au moment de l'affichage.

  • background-color: #e5e7eb pour un gris neutre sur fond blanc, à adapter au thème sombre si le site en a un.
  • border-radius: 4px pour adoucir les angles sans faire penser à un bouton.
  • height: 1em sur les lignes, avec une marge égale à l'interligne du texte final.
  • color: transparent et user-select: none pour qu'aucun texte provisoire ne soit visible ni sélectionnable.

Étape 3 : ajouter l'animation shimmer

La plupart des skeletons ont un reflet lumineux qui balaie les blocs de gauche à droite : c'est l'effet shimmer. Il montre que le chargement continue. On l'obtient avec un dégradé linéaire en arrière-plan et une animation qui déplace sa position. Une autre option, plus sobre, fait varier l'opacité entre 1 et 0,6 : on parle alors d'effet pulse.

  • background: linear-gradient(90deg, #e5e7eb 25 %, #f3f4f6 50 %, #e5e7eb 75 %) sur la classe .skeleton.
  • background-size: 200 % 100 % pour que le reflet ait de la place pour se déplacer.
  • Une règle @keyframes shimmer qui fait passer background-position de 200 % 0 à -200 % 0.
  • animation: shimmer 1.5s ease-in-out infinite pour un mouvement lent, qui ne fatigue pas les yeux.

Étape 4 : respecter l'accessibilité

Une animation en boucle peut gêner les personnes sensibles au mouvement. La requête média prefers-reduced-motion: reduce permet de couper le shimmer et de garder un simple fond gris pour ces visiteurs. Côté lecteurs d'écran, on masque les blocs décoratifs avec aria-hidden et on ajoute un texte caché du type « Chargement des produits ». Ces réglages vont dans le sens du référentiel d'accessibilité RGAA.

Étape 5 : remplacer le squelette par le contenu

Quand la réponse arrive, le script retire la classe .skeleton, injecte les données et passe aria-busy à false. Un fondu très court, de l'ordre de 150 à 200 millisecondes, rend la transition plus douce. Sur les frameworks comme React, Vue ou Svelte, on crée en général un composant squelette par type de bloc : il suffit ensuite de l'afficher tant que la requête n'est pas terminée.

Skeleton screen ou spinner : lequel choisir ?

Aucun des deux n'est meilleur dans l'absolu. Tout dépend de deux questions : sait-on à quoi ressemblera le résultat, et combien de temps l'utilisateur devra-t-il attendre ? Une bonne interface emploie souvent les deux, chacun à sa place.

Quand préférer le skeleton screen

  • Le contenu a une forme prévisible : liste d'articles, grille de produits, fil d'actualité, fiche client.
  • La page entière ou une grande zone se charge en même temps, par exemple à l'ouverture d'un tableau de bord.
  • Le chargement dure de une à quelques secondes, assez pour être remarqué mais pas assez pour justifier une barre de progression.
  • Le visiteur arrive pour la première fois sur la page et doit comprendre vite comment elle est organisée.

Quand le spinner reste le bon choix

  • L'action est déclenchée par un bouton : envoi d'un formulaire, ajout au panier, validation d'un paiement. Un petit spinner dans le bouton suffit.
  • La forme du résultat est inconnue, comme une recherche qui peut renvoyer une ligne ou cent.
  • La zone concernée est minuscule, par exemple un compteur ou un badge.
  • L'attente est longue et mesurable, comme l'envoi d'un fichier : une barre de progression avec un pourcentage informe mieux que les deux.

Et sous une seconde ?

Pour une réponse quasi instantanée, le mieux est souvent de ne rien afficher. Un squelette qui clignote 150 millisecondes donne une impression de lenteur qui n'existe pas. On peut retarder son apparition de quelques centaines de millisecondes : si les données arrivent avant, l'utilisateur ne le voit jamais.

Les erreurs courantes avec les skeleton screens

Bien conçu, le skeleton passe inaperçu. Raté, il agace plus qu'un spinner. Voici les erreurs que l'on retrouve le plus souvent lors d'audits d'interface.

Un squelette qui ne ressemble pas à la page

Si le squelette montre trois lignes et que le contenu final en affiche huit, la page saute au chargement et l'effet est perdu. Le squelette doit suivre la maquette réelle, idéalement à partir du même wireframe. Il vaut mieux un squelette simple et juste qu'un squelette détaillé et faux.

Masquer un problème de performance

Un skeleton rend l'attente plus supportable, pas le site plus rapide. Si une page met six secondes à s'afficher, il faut d'abord travailler les causes : requêtes trop lourdes, images non compressées, hébergement sous-dimensionné, scripts tiers. Le squelette vient ensuite, comme une finition, pas comme un pansement.

Oublier les cas d'erreur et de liste vide

Que se passe-t-il si l'API ne répond pas ? Un squelette qui scintille sans fin est pire qu'un message clair. Prévoyez un délai maximal, puis un état d'erreur avec un bouton « Réessayer ». Même chose pour une recherche sans résultat : le squelette doit laisser place à un message explicite, pas à un vide.

Utiliser le skeleton partout

Mettre un squelette sur chaque bouton, chaque menu et chaque petit chiffre rend l'interface tremblotante. Gardez-le pour les zones de contenu principales. Pour les pages vitrines dont le texte est généré côté serveur, il est souvent inutile : le HTML arrive déjà rempli. La distinction entre front end et back end aide à savoir où le chargement se fait vraiment.

Une animation trop rapide ou trop contrastée

Un shimmer qui défile vite ou un gris trop foncé attire l'œil au mauvais endroit. Le squelette doit rester discret : faible contraste, mouvement lent, couleurs proches du fond. C'est un élément d'UX et d'UI qui se remarque surtout quand il est mal fait.

Si vous préparez un nouveau site ou une application métier, ces états de chargement se pensent dès la maquette, pas après la mise en ligne. C'est ce que nous faisons pour chaque projet de création de site internet : chaque écran a son état chargé, son état en cours, son état vide et son état d'erreur.

Questions fréquentes

C'est un écran de chargement qui affiche la structure de la page sous forme de blocs gris avant l'arrivée du contenu réel. Il indique à l'utilisateur où vont apparaître les éléments et rend l'attente plus courte en apparence. On l'appelle aussi écran squelette ou squelette de chargement.

Créez des div vides aux dimensions du contenu final, donnez-leur une classe commune avec un fond gris clair et des coins arrondis, puis ajoutez une animation @keyframes qui déplace un dégradé linéaire pour l'effet shimmer. Coupez l'animation avec prefers-reduced-motion et retirez la classe dès que les données sont affichées.

Le spinner indique seulement qu'un chargement est en cours, sans rien montrer de la page. Le skeleton screen montre déjà la mise en page et réserve la place du contenu, ce qui limite les sauts visuels. On réserve le spinner aux actions courtes ou au contenu imprévisible, et le skeleton aux zones de contenu dont on connaît la forme.

À lire aussi. Sur le même thème.