
🌐 Aussi en: English · Deutsch · Español
☝️ Pour tous ceux qui lisent ceci sur leur téléphone : jusqu’à cette semaine, la page d’accueil vous montrait la même poignée d’articles quatre fois de suite (un bandeau défilant, un carrousel, une boîte à onglets, une liste « tendances », une grille « à la une ») avant que la vraie liste ne commence. Désormais, vous avez les cinq articles les plus récents, l’un après l’autre, et c’est tout. Sur ordinateur, rien n’a changé. Si vous n’avez rien remarqué : parfait, c’était le but. 📱
Tous les thèmes sont superbes dans leur démo sur un écran de 27 pouces. Le mien (MoreNews) a une page d’accueil chargée, façon magazine : un bandeau d’actualités défilant, un carrousel « Main News », une boîte à onglets Latest / Popular / Update, une colonne « Trending Now », des « Featured Posts » et, tout en bas, « You may have missed ». Sur ordinateur, ces blocs se placent côte à côte et ressemblent à un journal. Sur téléphone, le thème empile chaque bloc sous le suivant. Pour un blog qui publie quelques articles par semaine, cela veut dire une chose : les cinq mêmes articles, encore et encore, sur plusieurs hauteurs d’écran, avant même que la vraie liste commence.
Même méthode que d’habitude : je prends les décisions, mon co-admin IA (Claude) a fait les captures d’écran, écrit le CSS, lancé les mesures et cherché pourquoi la première mesure était moins bonne au lieu d’être meilleure.

🧹 La solution : une media query, six sélecteurs
Pas d’extension, pas de thème enfant, pas de modèle surchargé. Juste quelques lignes de CSS dans le « CSS additionnel » de WordPress, qui est stocké dans la base de données et non dans le dossier du thème : une mise à jour du thème ne peut donc pas l’effacer.
@media screen and (max-width: 1024px) {
body.home .banner-exclusive-posts-wrapper,
body.home .aft-main-banner-section,
body.home .af-main-banner-featured-posts,
body.home .above-footer-widget-section,
body.home #secondary .widget:has(.wp-block-latest-posts),
body.home #secondary .widget:has(.wp-block-archives-list) { display: none !important; }
}- Pourquoi 1024 px ? C’est précisément là que MoreNews passe ses colonnes de bannière en pleine largeur et commence à les empiler. Au-dessus, les tablettes en mode paysage reçoivent la mise en page normale pour ordinateur, qui y fonctionne très bien.
- Pourquoi
body.home? Seule la page d’accueil (et ses pages 2, 3, …) est concernée. Les articles individuels gardent leur barre latérale et le bloc « You may have missed ». - Pourquoi
:has()pour la barre latérale ? Les identifiants de widget comme#block-3changent dès que quelqu’un réorganise la barre latérale. « Le widget qui contient un bloc Latest Posts », lui, ne change pas. Tous les navigateurs actuels prennent en charge:has(). - Ce qui reste sur téléphone : les cinq articles les plus récents (« Les pages du site doivent afficher au plus » est réglé sur 5 dans WordPress), la pagination, la recherche et les catégories.
Et comme ce blog est géré avec Ansible, le CSS n’est pas seulement dans la base de données : le playbook l’écrit à chaque exécution. Si quelqu’un « fait le ménage » dans l’outil de personnalisation, l’exécution suivante le remet en place.
📉 Coup de théâtre : la page est devenue plus lente
Moins d’éléments sur la page, donc forcément plus rapide, non ? Lighthouse (mobile, trois passages à chaque fois) n’était pas d’accord. Le score de performance est passé de 93–95 à 91, et le temps jusqu’à l’affichage du plus grand élément (LCP) est monté de 2,6 s à 3,4 s.
La raison est une belle leçon sur le fonctionnement du LCP. Avant, le plus grand élément de l’écran du téléphone était l’image du carrousel, et une petite extension « must-use » que j’avais écrite deux jours plus tôt veillait à ce que cette image se charge immédiatement et en priorité haute. Maintenant, le carrousel est masqué, et le plus grand élément est l’image du premier article de la liste. Le thème marque chaque image avec loading="lazy" (« charge-la plus tard, quand elle va apparaître à l’écran »), y compris celle-ci. Le navigateur a donc attendu 2,1 secondes avant même de la demander. Pendant ce temps, mon extension continuait consciencieusement à prioriser l’image d’un carrousel que personne ne pouvait voir.
Correction numéro un : sur la page d’accueil, l’extension donne maintenant « charger tout de suite, priorité haute » à la première image de la liste principale d’articles (la fonction in_the_loop() de WordPress distingue la liste de la bannière, car la bannière est générée avant le début de la boucle). La première image de la bannière n’obtient plus que « charger tout de suite », sans priorité renforcée, pour les visiteurs sur ordinateur qui la voient toujours.
🕵️ L’attribut que WordPress a discrètement avalé
Après la correction numéro un, l’image se chargeait immédiatement, mais l’attribut fetchpriority="high" n’apparaissait tout simplement pas dans le HTML. En appelant le même code depuis la ligne de commande, il était là. Sur la page en ligne, non.
Le coupable : le thème affiche chaque image d’article via wp_kses_post(), le filtre HTML de WordPress. Sa liste d’attributs autorisés pour <img> ne contient pas fetchpriority, l’attribut était donc supprimé sans bruit. Aucun avertissement, aucune entrée de journal. Ce qui signifie aussi que « l’optimisation des performances » de deux jours plus tôt n’avait jamais fonctionné qu’à moitié. Un petit filtre qui ajoute fetchpriority aux attributs autorisés, et il arrive enfin jusqu’au navigateur.
📊 Les chiffres
| Lighthouse, mobile | Avant | Seulement masqué | Final |
|---|---|---|---|
| Score de performance | 93–95 | 91 | 95–96 |
| Largest Contentful Paint | 2,6 s | 3,4 s | 2,7 s |
| Total Blocking Time | 150–200 ms | 44 ms | 30–50 ms |
| Données transférées | 731 Ko | 569 Ko | 569 Ko |
| Attente avant la demande de l’image LCP | – | 2,1 s | 0,7 s |
| Score ordinateur | 100 | 100 | 100 |
Alors, combien plus rapide ? Honnêtement : la grande image s’affiche à peu près aussi vite qu’avant. Avec la connexion de test volontairement lente de Lighthouse, l’essentiel de ces 2,7 secondes correspond à la réponse du serveur (0,6 s) et au téléchargement de l’image elle-même. Ce qui a vraiment changé : 22 % de données en moins, car les blocs masqués ne chargent jamais leurs images, et environ quatre fois moins de temps de blocage JavaScript, donc la page réagit plus vite quand vous touchez l’écran ou faites défiler. Et surtout : vous lisez le dernier article sans faire défiler, au lieu de trois écrans plus bas.
🖼️ Des images plus petites pour les téléphones ? Ça n’en vaut pas la peine
L’idée suivante, évidente : servir des images plus petites aux téléphones. J’ai vérifié, et j’ai décidé que non.
- Téléphones et ordinateurs reçoivent actuellement le même fichier : un AVIF de 768 px de large, généralement de 30 à 70 Ko. L’optimiseur d’images ne crée qu’une seule taille pour ses versions AVIF ; la version WebP de secours pour les anciens navigateurs existe déjà en quatre tailles.
- Un téléphone de 412 « pixels CSS » de large a une densité d’environ 2,6, soit à peu près 1 070 pixels réels. Pour une image nette sur toute la largeur, il lui faut au moins autant de pixels que la colonne sur ordinateur. 768 px, c’est déjà un peu en dessous, et cela n’a l’air correct que parce que l’AVIF est si efficace.
- Seuls les vieux téléphones à faible densité en profiteraient. Dans le meilleur des cas, peut-être 20 à 30 Ko par image, environ 100 Ko sur toute la page d’accueil. Cela ne justifie pas des tailles d’image supplémentaires sur le disque et encore plus de pièces mobiles.
Le vrai goulot d’étranglement n’a jamais été la taille des images. C’est qu’on avait dit à l’image la plus importante d’attendre.
🤦 Bonus : je me suis banni moi-même (encore)
Pour la capture « avant », nous avons généré une copie enregistrée de l’ancienne page d’accueil. Cette copie pointait encore vers des fichiers CSS et JavaScript minifiés que l’extension d’optimisation avait supprimés quelques minutes plus tôt en vidant son cache. Un chargement de page, une rafale de « 404 Not Found » en quelques secondes, et fail2ban a fait exactement ce pour quoi il a été conçu : il a pris mon adresse IP personnelle pour un scanner et l’a bloquée, pour le web comme pour SSH. Fonctionnement conforme. Légèrement gênant. Thé et patience ont été appliqués. ☕
🎨 Quel thème, et que se passe-t-il si j’en change un jour ?
Ce blog utilise MoreNews d’AF themes, un thème magazine classique (pas un thème de blocs). C’est important, car la plupart de ce que j’ai fait ci-dessus en dépend. Si je change de thème un jour, voici ce qui suit et ce qui ne suit pas :
| Modification | Survit à un changement de thème ? | Pourquoi |
|---|---|---|
| « 5 articles par page » | ✅ Oui | Un réglage de WordPress (Réglages → Lecture), pas du thème. |
L’autorisation de fetchpriority | ✅ Oui | Se trouve dans une extension « must-use », indépendante du thème. Sans danger si le nouveau thème n’en a pas besoin. |
| « La première image de la liste se charge en premier » | ✅ En grande partie | N’utilise que des fonctions standard de WordPress (in_the_loop(), la classe standard wp-post-image). Fonctionne avec tout thème qui affiche les images mises en avant dans la liste des articles. |
| Préchargement des polices | ❌ Non | Pointe vers les fichiers de police du dossier MoreNews. Un nouveau thème a d’autres polices : adapter les chemins ou supprimer. |
| Masquer les blocs de bannière | ❌ Non | Les noms de classe comme .aft-main-banner-section n’existent que dans MoreNews. Un nouveau thème a ses propres blocs avec ses propres noms. |
| Masquer Recent Posts / Archive | ⚠️ En partie | Les classes de bloc viennent du cœur de WordPress et restent identiques. #secondary comme identifiant de barre latérale est courant, mais pas garanti. |
| Le « CSS additionnel » lui-même | ❌ Pas automatiquement | WordPress le stocke par thème. Après un changement, le nouveau thème démarre avec un champ vide (l’ancien CSS reste conservé pour MoreNews). |
L’idée se transpose donc telle quelle : décider de ce dont un visiteur sur téléphone a vraiment besoin, mesurer, faire charger l’image la plus importante en premier. Les sélecteurs, eux, sont à réécrire. Cela prend peut-être dix minutes avec les outils de développement du navigateur : passer en vue téléphone, clic droit sur le bloc indésirable, relever son nom de classe.
Et avec un thème de blocs moderne, pas besoin de CSS du tout : dans l’éditeur de site, on retire simplement ces blocs du modèle de la page d’accueil. C’est même mieux que display: none, car un bloc masqué fait toujours partie du HTML que le navigateur télécharge, alors qu’un bloc supprimé n’est jamais envoyé.
📂 Où se trouve le code
Les deux modifications font partie du rôle Ansible qui gère ce blog, dans roles/blog_wordpress/tasks/main.yml : la tâche « Set custom CSS » pour la mise en page mobile, et « Deploy performance hints mu-plugin » pour la priorité des images et l’autorisation de fetchpriority.




