Table des matières
Qu’est-ce que le blocage du rendu ? Qu’est-ce que le First Contentful Paint (FCP) ?
Comment fonctionne le rendu
Une page web est, très concrètement, un code HTML interprété par un navigateur (Chrome, Safari, Edge etc, voire des trucs plus obscurs type Vivaldi ou Brave).
Le navigateur lit le code ligne par ligne, construit le DOM, et calcule chaque pixel qu’il doit afficher à l’écran. Cette opération s’appelle le rendu graphique, ou pipeline de rendu, pour les puristes.
Le rendu implique d’avoir chargé les fichiers nécessaires à l’affichage, tous les assets critiques : HTML, CSS, JS, fonts, images, bref tout le bazar.
Par exemple, si le HTML dit qu’il y a un logo à afficher, il faut charger cette image (ou au moins son placeholder). Si le HTML dit qu’un titre H1 a un style CSS, il faut télécharger le fichier CSS qui contient ce style, le parser, et l’appliquer.
Or, chaque opération – télécharger chaque fichier, le parser, puis en tenir compte et calculer le rendu – prend du temps. Parfois un chouïa, parfois une éternité numérique si le serveur rame ou si la page est mal opti.
Le First Contentful Paint, affichage du premier élément graphique
Le concept de First Contentful Paint (FCP) est une mesure de Google, une métrique de perf front-end. Elle fait partie des Core Web Vitals, qui ont un impact direct sur le référencement SEO et sur l’expérience utilisateur (UX, pour les intimes).
First Contentful Paint signifie « affichage du premier élément » visible, c’est-à-dire le premier bout de contenu réel : texte, image, icône, fond, etc.
Par exemple, si le navigateur reçoit d’abord le logo et peut l’afficher, le temps de chargement de ce logo déterminera le FCP. Si c’est un gros PNG pas compressé, ton FCP va douiller sévère.
Dans la liste des tâches nécessaires au rendu du premier élément, le navigateur peut rencontrer des lenteurs, des files d’attente réseau, des scripts qui bloquent tout le thread principal. On parle alors de blocage de rendu (render-blocking resources, en VO).
Les facteurs de blocage du rendu
Les facteurs de blocage du rendu graphique peuvent être :
- des scripts JS qui n’ont pas encore été chargés (ou qui s’exécutent en mode bulldozer sur le thread principal)
- des feuilles de style CSS qui n’ont pas encore été chargées, ou trop nombreuses, ou pas concaténées
- une police web n’a pas encore été chargée, surtout quand elle est auto-hébergée ou tirée de Google Fonts sans préchargement
- des ressources non-critiques se chargent d’abord, ralentissant le chargement de ressources critiques pour le rendu (classique : sliders, pubs, scripts de tracking)
- un temps de réponse du serveur lent ralentit le rendu (TTFB à la ramasse, base MySQL en PLS, etc.)
- des fichiers non-optimisés mettent du temps à charger : images monstrueuses, CSS gigantesque, JS obèse
- des scripts tiers mettent du temps à répondre : pixels Facebook, Analytics, chat en ligne, A/B testing, tout le zoo habituel
Chacun de ces problèmes nécessite de mettre en oeuvre une ou plusieurs solutions. C’est une tâche complexe qui implique un savoir-faire expert, un peu de deboggage, et parfois beaucoup de jurons devant PageSpeed Insights.
Si vous ne vous sentez pas capable de régler vous-même les problèmes de blocage du rendu, je peux le faire pour vous :
Service d’optimisation des performances
Éliminer les ressources qui bloquent le rendu : à chaque problème sa solution
On va voir maintenant que chaque problème de blocage du rendu a sa ou ses solutions. Il n’y a pas de magie, juste des bons patterns de perf web.
Mais ça vaut le coup de les mettre en oeuvre. En passant des heures à optimiser mes sites, à tester, casser, réparer, re-tester, j’ai obtenu des résultats très nets :

Scripts JavaScript bloquants
Souvent, une page charge plusieurs script JS, parfois des dizaines, voire des centaines de Ko, même pour une page ultra simple. Plus il y a de widgets, d’animations, de sliders, de popups, plus la page charge de scripts.
Ce chargement retarde forcément le rendu du premier élément affichable. Et ce, alors même que dans la plupart des cas, le rendu n’en a nullement besoin pour l’écran au-dessus de la ligne de flottaison.
La solution consiste donc à retarder, reporter ou différer le chargement des scripts qui ne sont pas nécessaires dans les premières secondes de l’affichage d’une page. C’est du lazy-load de JS, en gros.
Concrètement, le navigateur va lire le HTML, voir que ces fichiers JS sont appelés mais avec une instruction de les appeler à la fin du chargement. Il va donc mettre leur chargement de côté et s’occuper de ce qui est urgent d’abord : le contenu lisible, le design minimal, les interactions vitales.
Pour mettre en oeuvre cette solution, de nombreux outils sont possibles :
- perso, j’utilise LiteSpeed et ses options pour mettre tel et tel scripts en chargement async ou defer, histoire de contrôler finement la timeline de chargement
- on peut faire la même chose avec d’autres outils comme WP Rocket, Perfmatters, Asset CleanUp, Autoptimize, Async Javascript, bref tout l’écosystème d’optimisation WordPress orienté Core Web Vitals
Attention : des scripts vitaux pour le rendu doivent être chargés illico, donc exclus de tout async ou defer. Exemple : jQuery. Par définition si vous lui dites de se charger à la fin ou n’importe quand, d’autres scripts basés sur lui vont causer une erreur « Undefined » dans la console. Et là, plus de menu, plus de slider, plus rien : mode site cassé.
Comment choisir entre async et defer ?
L’attribut async est correct pour tous les scripts tiers. Ex : Google Analytics ou Matomo peuvent attendre que la page soit rendue, ils ne sont pas critiques pour le FCP ni pour le LCP, juste pour vos stats.
L’attribut defer est approprié pour les scripts du thème et des plugins qui changent quelque chose sur les pages du site, mais seulement une fois que le HTML est déjà parsé. C’est le bon compromis : script important, mais pas bloquant.
| Attribut | Quand l’utiliser | Impact |
|---|---|---|
| async | Scripts indépendants (stats, pubs, pixels marketing) | Exécution immédiate, ordre non garanti |
| defer | Scripts dépendants ou critiques (DOM complet) | Exécution après le HTML, ordre garanti |
Scripts tiers
Sur WordPress et ailleurs, les plugins sont une joie… et une plaie. Ils nous facilitent la vie… et pourrissent les performances d’un site si on en abuse, surtout au niveau du FCP et du LCP.
Chaque plugin va ajouter ses fichiers CSS et JS sur toutes les pages du site. Parfois, juste pour afficher un avis client sur des pages produit, rendre un bouton plus joli, ajouter un compteur ou une pop-up débile, etc.
Une solution consiste donc à s’en passer autant que possible. Car, un site plus joli, plus riche, mais moins vu à cause de performances lamentables, ça n’a guère d’intérêt. Un site qui rame ne convertit pas, point barre.
Par exemple, j’ai supprimé le plugin TrustIndex qui me permettait d’afficher des avis client Google. Ces avis sont utiles ! Mais, pas au prix de la performance de toutes mes pages. J’ai donc viré ce widget, et l’ai remplacé par une image, une copie d’écran de mes avis clients. Cette image optimisée ne se charge que sur les pages produit.
Ainsi, j’ai nettoyé mes sites. J’ai empêché le parasitage généralisé causé par trop de plugins. En bonus, l’admin est plus légère et les risques de conflits JS ont diminué (toujours bon à prendre).
Feuilles de style CSS bloquantes
Le First Contentful Paint concerne forcément un élément qui s’affiche dès le premier écran. Sur mobile, ou sur ordinateur, ou même sur une tablette un peu antique.
Si, pour l’afficher, on doit attendre que 10 fichiers CSS qui stylent le reste de la page soient chargés, on perd un temps fou. Le navigateur reste bloqué à construire le CSSOM alors qu’il pourrait déjà afficher du contenu lisible.
Critical CSS
Donc, la meilleure solution est d’adopter un système de critical CSS. Ces systèmes vont :
- Identifier les styles CSS « critiques », c’est-à-dire essentiels, sur une page donnée, ou un type de page (article, catégorie, produit… page d’accueil, panier, etc.)
- Créer un fichier contenant uniquement ce CSS critique, et le charger en priorité, avant le reste du thème
- Mettre tout le reste dans un autre fichier CSS, qui ne sera chargé qu’après le rendu, parfois via media ou preload
- On obtient ainsi un excellent FCP, en optimisant le LCP et d’autres Core Web Vitals au passage (et souvent un meilleur score PageSpeed mobile)
On peut aussi « inline », c’est-à-dire intégrer du CSS critique directement dans le code de la page, dans le <head>, pour éviter une requête HTTP supplémentaire.
Mais attention : cette technique + un plugin d’opti peuvent entrer en concurrence. Et faire doublon. Résultat : styles chargés deux fois, CSS boursouflé, bugs visuels chelous.
Pour implémenter cette technique, j’utilise là aussi LiteSpeed. Divers autres plugins d’opti proposent cette fonctionnalité, parfois automatique, parfois page par page.
Minifier et concaténer le CSS
Avec ou sans critical CSS, on gagnera toujours du temps en rendant les fichiers plus petits. C’est ce qu’on fait
- en les minifiant (on supprime tous les caractères inutiles, on gagne une réduction de quelques %, parfois plus si le fichier est crade)
- en les concaténant (on sert un seul fichier CSS, au lieu d’en envoyer plein ; mais si le serveur envoie tout en HTTP/3 cette technique aura l’effet inverse, donc à tester selon l’infra, pas à appliquer en mode dogmatique)
Police web bloquantes
Si le FCP concerne un texte, par exemple le H1 de la page, le chargement de la police web peut en bloquer le rendu. Et parfois on se retrouve avec le fameux « flash of invisible text » (FOIT) ou « flash of unstyled text » (FOUT).
Dans la chronologie du chargement :
- le navigateur lit le HTML, voit un texte, voit qu’il appelle un style CSS qui nécessite une police de caractère
- il charge alors cette police
- et pendant ce temps, il est bloqué
Pour optimiser cela, on peut :
- Utiliser des formats de police optimisés comme WOFF2. Ce format est tout simplement plus compact donc plus rapide à charger que du TTF ou OTF, parfait pour les perfs front-end.
- Précharger les polices importantes avec la directive <link rel= »preload »>. L’option est parfois proposée par le thème. Sinon, par des plugins d’optimisation. Elle dit au navigateur, dès qu’il lit le <head> du code HTML, d’aller charger cette police. Il devrait l’avoir reçue dès qu’il lit le H1.
- Activer les options de font-display: swap; pour afficher un texte temporaire avec une police système (ex, Arial, Times New Roman etc). Cette technique risque cependant d’augmenter le CLS. Car, la taille de la police et la place qu’elle prend dans l’écran vont forcément changer au moment du changement de police.
Une technique d’opti simple pour éviter les soucis, consiste à utiliser une police système sur le site. Tous les navigateurs l’ont déjà. Donc aucun chargement. C’est moins « brandé », mais côté FCP/LCP, c’est un cheat code.
Serveur lent et ressources non-optimisées
Les temps de réponse lents du serveur ou des fichiers volumineux augmentent le temps de chargement initial. Le blocage du rendu peut donc s’expliquer en partie par la lenteur du serveur, un hébergeur bas de gamme ou une config PHP foireuse.
Les solutions possibles sont :
- Implémenter un CDN pour les ressources statiques (images, CSS, JS). Un CDN va charger vos fichiers depuis d’autres serveurs, déchargeant le vôtre, et rapprochant les assets des utilisateurs géographiquement.
- Activer la compression Gzip ou Brotli. Ces algorithmes réduisent beaucoup la taille de tous les fichiers, ce qui booste aussi le TTFB ressenti.
- Sur WordPress, désactiver l’autoload inutile de nombreux plugins dans la table Options, histoire de ne pas charger 800 options débiles à chaque requête.
Cache navigateur
Ce problème n’est par définition jamais diagnostiqué par PageSpeed Insights. Pourtant, il existe et est lié à celui du LCP et du FCP. Sur un vrai humain avec un vrai navigateur, ça change tout.
En effet, chaque visite du bot de PageSpeed est considérée comme nouvelle, sans historique, donc il ne saurait être question de cache navigateur. Cependant, l’absence de cache navigateur peut ralentir le rendu pour vos utilisateurs réels, surtout sur mobile en 4G un peu claquée.
Le cache navigateur est une sorte de mémoire. Cette mémoire stocke les fichiers et infos reçues d’une page web, côté client, pour ne pas tout re-télécharger à chaque clic.
Par exemple, si vous visitez une page, votre navigateur stocke le logo, des fichiers CSS et JS, etc. Si vous visitez une autre page, ces ressources n’ont plus à être chargées depuis le serveur. Elles sont déjà présentes en cache. Ainsi, l’affichage de la deuxième page vue est toujours plus rapide que celui de la première page vue.
Mais chaque site contrôle ce qu’il dit aux navigateurs de mettre en cache. Sinon, par défaut, les navigateurs adoptent des règles de cache très prudentes et peu efficaces, histoire de ne pas servir du contenu obsolète.
Donc pour être clair :
| Moment | Avec cache | Sans cache |
|---|---|---|
| 1ère page vue | Téléchargement initial des ressources (HTML, CSS, JS, images). | Téléchargement initial des ressources (HTML, CSS, JS, images). |
| 2ème page vue | Les ressources statiques sont récupérées depuis le cache. Seulement le HTML ou les données dynamiques sont rechargés. | Toutes les ressources sont téléchargées à nouveau, même si elles n’ont pas changé. |
La solution consiste à configurer correctement des directives de cache HTTP appropriées pour les fichiers statiques. Cette config se fera dans le fichier .htaccess, qui est interprété chaque fois qu’un navigateur demande une page.
C’est compliqué à faire à la main, surtout si on n’est pas à l’aise avec la config Apache ou Nginx. Mais on a de bons plugins d’optimisation pour ça.
Par exemple, ShortPixel peut s’occuper d’ajouter les bonnes instructions de cache-control et expire à votre fichier .htaccess.
Ou, LiteSpeed fera la même chose avec tous les types de fichier, en gérant au passage le cache serveur et le cache navigateur, ce qui est plutôt très, très confortable.
Besoin d’aide pour optimiser votre FCP ?
J’ai conscience du fait que mes explications, pourtant simplifiées, peuvent sembler difficiles à comprendre. Ou, pas assez détaillées. L’opti est un domaine très complexe, difficile à expliquer, surtout quand on mélange front-end, back-end, réseau et SEO technique dans le même shaker.
Si vous êtes informaticien-ne, ça devrait aller, vous saurez quoi faire, vous irez gratter dans l’onglet Réseau de DevTools et ajuster tout ça.
Mais si vous gérez votre site en amateur-e, tout ça est du charabia. Donc, peut-être préférez-vous déléguer ce boulot compliqué ? Franchement, c’est normal, tout le monde n’a pas envie de passer ses soirées dans PageSpeed et Lighthouse.
Je peux optimiser vos Core Web Vitals pour vous :
Service d’optimisation des performances
De sorte que vos notes commenceront à ressembler à ça (ce sont les stats de boutique-wp.fr d’après Google Search Console, après des semaines passées à tout optimiser… j’ai bien ramé mais à la fin je suis tombé sur l’île du paradis !)






