Sessei, marque de mode féminine

2025

Sessei

Refonte partielle et optimisation continue du thème Shopify · Thème Shopify optimisé (image, vidéo, chargement)

Contexte

Sessei avait un thème Shopify existant, mais pas pensé pour la vitesse : images dupliquées entre background-image et balise img, lecteurs vidéo tiers (YouTube, Vimeo) lourds et peu fiables sur Safari, chargement qui n’ordonnait rien par priorité.

Plutôt qu’une réécriture complète, j’ai refait 50 à 60 % du thème dans un format minimaliste, par petites itérations depuis plus d’un an : hero en srcset avec la bonne image au bon moment, galerie produit qui charge la première photo en priorité et le reste en différé, vidéos en balise native HTML5 avec Intersection Observer plutôt qu’un player YouTube embarqué, CSS et polices ordonnées selon ce qui bloque le rendu et ce qui peut attendre.

Résultat : LCP à 908 ms, INP P75 à 56 ms.

Objectifs & livrables

Éliminer le double chargement d’image

Une seule image, la bonne taille, chargée une fois : srcset plutôt que background-image et img cumulés.

Prioriser la première image produit

Packshot immédiat, galerie complétée en différé.

Sortir des lecteurs vidéo tiers

Vidéo native HTML5, lue seulement à l’entrée dans l’écran.

Ordonner ce qui bloque le rendu

CSS critique inline, polices en swap, scripts différés.

Sous le capot

Trois règles appliquées partout dans le thème : la bonne ressource au bon moment (eager seulement pour ce qui est dans le viewport), le navigateur qui choisit (srcset, HLS/MP4, jamais un fichier unique « au cas où »), et le natif d’abord (img, video, Intersection Observer plutôt qu’une librairie de plus).

Performancesrcset

01 / 05

Hero : une image, la bonne, tout de suite

Problème

L’image de hero, souvent l’élément LCP, était chargée deux fois (en background-image et en img), et servie en une seule taille quel que soit l’écran.

Approche

Passage au filtre Liquid image_tag avec un vrai srcset : paliers jusqu’à 3840 px sur desktop, jusqu’à 1780 px sur mobile, sans télécharger la version 4K sur un téléphone. L’image visible passe en loading="eager" et fetchpriority="high", uniquement elle. Si une image mobile dédiée existe, la version desktop passe en lazy sur petit écran, et inversement. Le navigateur choisit la bonne largeur, plutôt qu’un JPEG unique trop lourd envoyé à tout le monde.

Hero : une image, la bonne, tout de suite

PerformancePDP

02 / 05

Fiche produit : la première photo d’abord

Problème

Faire attendre le visiteur que toute la galerie produit soit chargée avant de voir la première photo.

Approche

La première image de la galerie charge immédiatement en priorité haute ; les suivantes passent en lazy et en priorité basse, avec un srcset jusqu’à 3600 px. Les vidéos produit passent en HTML5 avec preload="metadata", pour charger la miniature et la durée plutôt que le fichier entier. Le visiteur voit le packshot tout de suite, le carrousel se complète ensuite.

Fiche produit : la première photo d’abord

VidéoPerformance

03 / 05

Vidéo native plutôt que lecteur tiers

Problème

Les iframes YouTube ou Vimeo alourdissent la page (scripts, cookies, tracking) et posent régulièrement des soucis sur Safari et iOS.

Approche

Une section vidéo 16/9 construite sur la balise vidéo native de Shopify (HLS et MP4, le navigateur choisit), sans player tiers. Lecture en muted, playsinline et loop pour permettre l’autoplay sur Safari et iPhone, preload="metadata" pour ne pas télécharger le fichier complet au chargement de la page. Un Intersection Observer déclenche la lecture à l’entrée dans l’écran et la coupe à la sortie : la bande passante n’est utilisée que quand la vidéo est vraiment regardée.

Vidéo native plutôt que lecteur tiers

MobilePerformance

04 / 05

Mobile : ne pas envoyer ce qu’on ne montre pas

Problème

Sur une grille à trois colonnes, tout le contenu desktop n’a pas besoin d’exister sur mobile, ni au même poids.

Approche

Images desktop et mobile distinctes, aux tailles adaptées, plutôt qu’une seule image redimensionnée en CSS. Les colonnes masquées sur mobile ne sont pas affichées, tout ce qui est hors du premier écran passe en lazy, et les attributs width et height limitent le décalage de mise en page (CLS).

Mobile : ne pas envoyer ce qu’on ne montre pas

CSSPerformance

05 / 05

Priorités CSS, JS et polices

Problème

Un budget de chargement limité, dépensé sans ordre de priorité entre ce qui doit s’afficher immédiatement et ce qui peut attendre.

Approche

En priorité : preconnect vers les CDN Shopify, preload de theme.css, theme.js et lazysizes, CSS critique inline pour le header et la première section visible, polices en WOFF2 avec font-display: swap pour que le texte s’affiche tout de suite. En différé : scripts en defer (Alpine, thème, Swiper), lazysizes en async, CSS non critique chargé via le pattern media="print" puis basculé en all. Côté code, Tailwind préfixé plutôt que des feuilles monolithiques empilées à chaque section, et Alpine.js pour le menu plutôt qu’une couche jQuery de plus.

Priorités CSS, JS et polices

Décisions

Pourquoi ces choix techniques

Non, 50 à 60 % environ, dans un format minimaliste, par petites itérations plutôt qu’une réécriture complète d’un coup.

Suite

Un thème mode qui charge trop lentement ?

Pas besoin de tout réécrire : la bonne ressource au bon moment change déjà beaucoup.