Slide 1

Slide 1 text

Layout Shifts Tu fais du Web et tu connais pas les ? Nan mais... 📞

Slide 2

Slide 2 text

Hello ! Je suis Raphaël... raphaël goetter

Slide 3

Slide 3 text

Depuis 2003 Un forum, des tutos, un service d'emploi Opensource et gratuit 30000 visiteurs / jour 50000 membres sur le forum .com Communauté d'apprentissage

Slide 4

Slide 4 text

.fr Depuis 2006 On fait des sites web performants et accessibles On dispense des formations On est une petite équipe d'une 10aine de personnes On a un peu l’accent alsacien Agence web, organisme de formation

Slide 5

Slide 5 text

big Merci ! Merci à Eroan pour son partage de connaissances et conseils avisés sur ce sujet https://agencewebperformance.fr/

Slide 6

Slide 6 text

À L'AFFICHE

Slide 7

Slide 7 text

Layout Shifts “ Instabilités graphiques au chargement de la page qui dégradent l'expérience utilisateur. OK, alors c'est quoi des ?

Slide 8

Slide 8 text

Layout Shifts OK, alors c'est quoi des ? source : https://web.dev/optimize-cls/

Slide 9

Slide 9 text

https://web.dev/cls/ Mouais c'est pas clair tout ça, tu me montres ? spoiler alert : le design de la page va changer au moment de l'interaction avec le visiteur

Slide 10

Slide 10 text

Le Cumulative Layout Shift fait partie des Core Web Vitals. Google a annoncé utiliser les Core Web Vitals comme signal de ranking dès 2021. 🤯 Pourquoi c'est important ?

Slide 11

Slide 11 text

“ Ce sujet à lui seul couvre les thèmes : UX, HTML, CSS, Performance... et SEO Cumulative Layout Shifts

Slide 12

Slide 12 text

Outils Commençons par s'équiper pour détecter les Layout Shifts

Slide 13

Slide 13 text

Outils en ligne (de notre ami Google) https://pagespeed.web.dev/ (le plus complet à ce jour) https://www.webpagetest.org/

Slide 14

Slide 14 text

Outils en local (opensource, multibrowsers) Lighthouse (toi-même tu connais) Chrome DevTools (extension Firefox et Edge) SpeedVitals (extension Chrome) Web Vitals

Slide 15

Slide 15 text

Bon, du coup, comment on évite ces Layout Shifts ? Réserver l'espace pour les publicités ou les iframes Diminuer le nombre de contenus injectés dynamiquement Construire des pages en préférant des zones de tailles fixes, non déterminées par leur contenu Indiquer largeur et hauteur des images et vidéos Précharger les polices pour éviter les comportements FOIT ou FOUT Concevoir des animations performantes

Slide 16

Slide 16 text

Layout Shifts dûs à la mise en page 1

Slide 17

Slide 17 text

cas concret trois colonnes (avec Grid Layout) source : https://http203-playlist.netlify.app/videos/avoiding-layout-shift-by-putting-the-css-in-charge/

Slide 18

Slide 18 text

.container { display: grid; grid-template-columns: 1fr 1fr 1fr; } 1 2 3 4 méthode 1 .container { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; } 1 2 3 4 5 méthode 2

Slide 19

Slide 19 text

méthode 1 grid-template-columns .container { display: grid; grid-template-columns: 1fr 1fr 1fr; } 1 2 3 4 je suis le temps qui passe... layout shift

Slide 20

Slide 20 text

méthode 2 grid-auto-flow .container { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; } 1 2 3 4 5 je suis le temps qui passe... layout shift layout shift layout shift layout shift

Slide 21

Slide 21 text

"auto" min-content max-content fit-content 1fr flex-shrink flex-grow stretch min-width: auto width: auto valeur connue par le navigateur que lorsque tous les contenus (texte, polices, images, médias) sont chargés et dimensionnés

Slide 22

Slide 22 text

Flexbox Grid Layout Conçu pour s'adapter aux contenus. = Plus sensible aux Layout Shifts Flexbox est designé pour être fluide par défaut. Conçu pour englober les contenus. = Moins sensible aux Layout Shifts 💪 Grid Layout est designé pour être rigide par défaut. , float, inline-block, ... 💩

Slide 23

Slide 23 text

QUIZ ! alors c'est quoi le mieux ?

Slide 24

Slide 24 text

.container { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; } 1 2 3 4 5 .container { display: grid; grid-template-columns: 1fr 1fr 1fr; } 1 2 3 4 1 2 on vient d'en parler il y a 5min, faut suivre un peu...

Slide 25

Slide 25 text

.flex-item { flex-grow: 1; } 1 2 3 .flex-item { flex: 1; } 1 2 3 1 2 = flex-grow: 1 & flex-basis: 0 = flex-grow: 1 & flex-basis: auto

Slide 26

Slide 26 text

.flex-item { flex: 1; } 1 2 3 .flex-item { flex: 1 0 0; } 1 2 3 1 2 = flex-grow: 1 & flex-shrink: 1

Slide 27

Slide 27 text

.flex-item { flex: 1; } 1 2 3 .flex-item { flex: 1; min-width: 0; } 1 2 3 4 1 2 par défaut min-width vaut "auto" sur un flex item

Slide 28

Slide 28 text

.container { display: grid; grid-template-columns: 1fr 1fr; } 1 2 3 4 .container { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); } 1 2 3 4 1 2 taille mini = min-content

Slide 29

Slide 29 text

.container { display: grid; grid-template-columns: repeat(auto-fill, 100px); } 1 2 3 4 .container { display: grid; grid-template-columns: repeat(auto-fit, 100px); } 1 2 3 4 1 2 auto-fit supprime les colonnes inutiles quand elles sont vides de contenu

Slide 30

Slide 30 text

Utilisez Grid Layout en priorité tant que possible, et Flexbox si nécessaire. Tentez de limiter les valeurs automatiques, dépendantes du contenu. Si vous utilisez un framework, jetez un oeil sous le capot Conclusion Layout Shifts dûs à la mise en page par ex. dans Bootstrap un élément en .col-6 vaudra flex: 0 0 auto; width: 50%;

Slide 31

Slide 31 text

Charger CSS de manière asynchrone (via JS) La propriété order Les propriétés row-reverse / column-reverse Les propriétés flex, flex-grow, flex-shrink (déjà vu) La valeur space-between (et semblables) si le nombre d'éléments est variable Bonus track CSS les trucs CSS qui génèrent des Layout Shifts source : https://www.codecada.com/serp/16/how-css-flexbox-model-can-cause-cummulative-layout-shifts

Slide 32

Slide 32 text

Grid Layout

Slide 33

Slide 33 text

Layout Shifts dûs aux animations 2

Slide 34

Slide 34 text

img { margin-left: 0; transition: 0.5s; } img:hover { margin-left: 100px; } ooh la jolie transition !

Slide 35

Slide 35 text

img { margin-left: 0; transition: 0.5s; } img:hover { margin-left: 100px; } ooh la jolie transition ! @keyframes pika { to { position: absolute; left: 100px; } } img:hover { animation: pika 0.5s; } ooh la belle animation ! 👎

Slide 36

Slide 36 text

animation et perfs L'étape "Render tree" fait le tri entre les informations de contenu (HTML), de styles (CSS) et de scripts (JS). Il écarte les éléments invisibles (meta, scripts, mais aussi display: none, etc.) et ne conserve que ce qui sera affiché. L'étape "Layout" (ou Reflow) calcule la taille exacte et la position de chaque élément du Render tree. L'étape "Paint" (ou Repaint) dessine pixel par pixel chaque couleur sur la page. L'étape "Compositing" sépare la page en plusieurs calques indépendants afin d'être traités de manière autonome.

Slide 37

Slide 37 text

CPU GPU Render tree + Layout display margin padding width, height position top, right, bottom, left border-width Paint color background-color background-image box-shadow, text-shadow clip-path border-color filter Composite transform translate, rotate, scale opacity will-change

Slide 38

Slide 38 text

img { margin-left: 0; transition: 0.5s; } img:hover { margin-left: 100px; } Transition avec Layout + Paint Transition Composite img { translate: 0; transition: translate 0.5s; } img:hover { translate: 100px; } 👎 👍 img { margin-left: 0; transition: 0.5s; will-change: margin-left; } img:hover { margin-left: 100px; } ou bien :

Slide 39

Slide 39 text

Solution 1 : Animer de préférence les propriétés dites "composites" (transform, translate, opacity) Solution 2 : si la solution 1 n'est pas envisageable, appliquer la propriété will-change Conclusion Layout Shift dûs aux transitions et animations

Slide 40

Slide 40 text

Layout Shifts dûs aux médias 3

Slide 41

Slide 41 text

Lorem Elsass...

1 2 Lorem Elsass Ipsum mitt picon bière munster du ftomi! Ponchour bisame. Bibbeleskaas jetz rossbolla sech choucroute un schwanz geburtstàg, Chinette dû, ìch bier deppfele schiesser. Flammekueche de knèkes Seppele gal! a hopla geburtstàg, alles fraü Chulia Roberts oder knäckes dûû blottkopf. Noch bredele schissabibala, yeuh e schmutz. largeur du parent : 200px 1 on dirait bien que l'image n'est pas encore chargée... suspense... il semble que je souhaite afficher une image...

Slide 42

Slide 42 text

1 Lorem Elsass Ipsum mitt picon bière munster du ftomi! Ponchour bisame. Bibbeleskaas jetz rossbolla sech choucroute un schwanz geburtstàg, Chinette dû, ìch bier deppfele schiesser. Flammekueche de knèkes Seppele gal! a hopla geburtstàg, alles fraü Chulia Roberts oder knäckes dûû blottkopf. Noch bredele schissabibala, yeuh e schmutz. image 200 x 100px largeur du parent : 200px l'image est chargée, elle crée un Layout Shift (pas bien !) 1

Slide 43

Slide 43 text

1 Lorem Elsass Ipsum mitt picon bière munster du ftomi! Ponchour bisame. Bibbeleskaas jetz rossbolla sech choucroute un schwanz geburtstàg, Chinette dû, ìch bier deppfele schiesser. Flammekueche de knèkes Seppele gal! a hopla geburtstàg, alles fraü Chulia Roberts oder knäckes dûû blottkopf. Noch bredele schissabibala, yeuh e schmutz. largeur du parent : 200px l'espace est réservé avant même que l'image ne soit chargée 2

Slide 44

Slide 44 text

1 Lorem Elsass Ipsum mitt picon bière munster du ftomi! Ponchour bisame. Bibbeleskaas jetz rossbolla sech choucroute un schwanz geburtstàg, Chinette dû, ìch bier deppfele schiesser. Flammekueche de knèkes Seppele gal! a hopla geburtstàg, alles fraü Chulia Roberts oder knäckes dûû blottkopf. Noch bredele schissabibala, yeuh e schmutz. image 200 x 100px largeur du parent : 200px et hop, pas de Layout Shift ! 2 bah c'est bien beau mais moi je fais du Responsive et ma taille d'image au départ est variable, mettons 2000x1000 tiens !

Slide 45

Slide 45 text

1 image 2000 x 1000px largeur du parent : 200px bah forcément ça déborde ! 3

Slide 46

Slide 46 text

1 largeur du parent : 200px 3 img { max-width: 100%; } 1 2 3 tu es bien taquin ! ça rentre en largeur mais c'est tout déformé verticalement

Slide 47

Slide 47 text

img { max-width: 100%; height: auto; } 1 2 3 4 Lorem Elsass Ipsum mitt picon bière munster du ftomi! Ponchour bisame. Bibbeleskaas jetz rossbolla sech choucroute un schwanz geburtstàg, Chinette dû, ìch bier deppfele schiesser. Flammekueche de knèkes Seppele gal! a hopla geburtstàg, alles fraü Chulia Roberts oder knäckes dûû blottkopf. Noch bredele schissabibala, yeuh e schmutz. largeur du parent : 200px l'espace est réservé avant même que l'image ne soit chargée 4 1

Slide 48

Slide 48 text

img { max-width: 100%; height: auto; } 1 2 3 4 1 Lorem Elsass Ipsum mitt picon bière munster du ftomi! Ponchour bisame. Bibbeleskaas jetz rossbolla sech choucroute un schwanz geburtstàg, Chinette dû, ìch bier deppfele schiesser. Flammekueche de knèkes Seppele gal! a hopla geburtstàg, alles fraü Chulia Roberts oder knäckes dûû blottkopf. Noch bredele schissabibala, yeuh e schmutz. image 2000 x 1000px largeur du parent : 200px et hop, pas de Layout Shift ! 4 height: auto permet au navigateur d'appliquer le ratio de l'image quelle que soit sa largeur d'affichage ! width et height indiquent au navigateur le ratio de l'image

Slide 49

Slide 49 text

1 Lorem Elsass Ipsum mitt picon bière munster du ftomi! Ponchour bisame. Bibbeleskaas jetz rossbolla sech choucroute un schwanz geburtstàg, Chinette dû, ìch bier deppfele schiesser. Flammekueche de knèkes Seppele gal! a hopla geburtstàg, alles fraü Chulia Roberts oder knäckes dûû blottkopf. Noch bredele schissabibala, yeuh e schmutz. largeur du parent : 200px 4 img { max-width: 100%; height: auto; background: gray; } 1 2 3 4 5 chouette astuce ! la couleur de fond de l'image s'applique même quand l'image n'est pas chargée, couvrant la surface de l'image grâce à son ratio connu du navigateur

Slide 50

Slide 50 text

Indiquer les dimensions (width et height) dans le HTML pour que le navigateur puisse calculer le ratio. Utiliser des formats d'images modernes (webp, avif) max-width: 100% pour que l'image s'adapte en largeur à son conteneur. height: auto pour que le navigateur applique le ratio systématiquement background-color sur l'image pour indiquer visuellement l'espace qui sera occupé quand elle sera chargée (placeholder). Conclusion Layout Shift dûs aux médias

Slide 51

Slide 51 text

Les images ne sont chargées que si JS est prêt Les images ont des hauteurs différentes Bonus track Les carousels 💩 ressource : https://bordermedia.org/2021/12/owl-carousel-cls-cumulative-layout-shift-fix/ Causes de Layout Shifts : min-height sur l'ensemble du carousel height fixe et identique sur les images propriété aspect-ratio Solutions :

Slide 52

Slide 52 text

Layout Shift dûs aux Polices 4

Slide 53

Slide 53 text

No content

Slide 54

Slide 54 text

formats de fichiers modernes

Slide 55

Slide 55 text

@font-face { font-family: kiwi; src: url("/fonts/kiwi.woff2") format("woff2"); } 💪 supporté par 96% de navigateurs

Slide 56

Slide 56 text

font-display

Slide 57

Slide 57 text

body { font-family: SuperPolice, arial, sans-serif; } 1 2 3 @font-face { font-family: SuperPolice; src: url("superfont.woff2") format("woff2"); } 1 2 3 4 5 font-display: swap; transparent arial SuperPolice

Slide 58

Slide 58 text

police alternative "en attendant" police invisible "en attendant" swap block

Slide 59

Slide 59 text

auto font-display: auto; @font-face { 1 font-family: kiwi; 2 src: url("kiwi.woff2"); 3 4 } 5 Valeur par défaut. Le navigateur décide de sa stratégie d'affichage : FOUT, FOIT, autre, bref il fait sa vie quand utiliser "auto" ? Jamais ? A priori aucun intérêt d'avoir des comportements différents selon les navigateurs.

Slide 60

Slide 60 text

block font-display: block; @font-face { 1 font-family: kiwi; 2 src: url("kiwi.woff2"); 3 4 } 5 Bloquage volontaire de la police durant 3s. Le contenu est alors invisible, c'est le FOIT. quand utiliser "block" ? Adapté pour les fontes d'icônes, pour éviter les caractères exotiques quand la police n'est pas encore chargée.

Slide 61

Slide 61 text

No content

Slide 62

Slide 62 text

swap font-display: swap; @font-face { 1 font-family: kiwi; 2 src: url("kiwi.woff2"); 3 4 } 5 Affichage immédiat de la police alternative, puis remplacement quand la police est chargée. C'est le FOUT. quand utiliser "swap" ? Adapté pour tous les contenus textuels mais déclenche forcément un Layout Shift.

Slide 63

Slide 63 text

fallback font-display: fallback; @font-face { 1 font-family: kiwi; 2 src: url("kiwi.woff2"); 3 4 } 5 Comportement un peu passe-partout. On cumule FOIT puis FOUT. quand utiliser "fallback" ?

Slide 64

Slide 64 text

optional font-display: optional; @font-face { 1 font-family: kiwi; 2 src: url("kiwi.woff2"); 3 4 } 5 La police n'est affichée que si elle est immédiatement disponible (déjà dans le cache par exemple). BONUS : elle sera affichée sur la page suivante. quand utiliser "optional" ? Parfait si la police n'est pas absolument nécessaire ou si elle est pré-chargée. Ne crée pas de Layout Shift. 💪

Slide 65

Slide 65 text

font-display compatibilité https://caniuse.com/css-font-rendering-controls

Slide 66

Slide 66 text

Police alternative ajustée

Slide 67

Slide 67 text

https://screenspan.net/fallback (merci à pour la découverte) @nhoizey

Slide 68

Slide 68 text

@font-face { font-family: 'Adjusted FredokaOne-Regular'; src: url(FredokaOne-Regular.woff2) format('woff2'); size-adjust: 98%; ascent-override: 72%; descent-override: 5%; line-gap-override: 41%; font-display: swap; } h1 { font-family: 'Adjusted FredokaOne-Regular', 'Arial'; } 1 2 3 4 5 6 7 8 9 10 11 12 13 Police principale ajustée

Slide 69

Slide 69 text

size-adjust compatibilité https://caniuse.com/mdn-css_at-rules_font-face_size-adjust

Slide 70

Slide 70 text

Préchargement

Slide 71

Slide 71 text

Préchargement avec rel=preload https://web.dev/fetch-priority/ Prévu pour plein de ressources : surtout fonts et images, mais aussi style, script, audio, vidéo, embed, object, etc

Slide 72

Slide 72 text

sans rel="preload" HTML CSS font 1 font 2 FOUT / FOIT je suis le temps qui passe...

Slide 73

Slide 73 text

avec rel="preload" HTML CSS font 1 font 2 FOUT / FOIT je suis le temps qui passe...

Slide 74

Slide 74 text

Compresser les fichiers (.woff2) Choisir font-display: optional Éviter les icon-fonts Ajustez les polices alternatives Précharger les polices critiques Héberger les polices sur son propre domaine Conclusion Layout Shifts des polices web

Slide 75

Slide 75 text

Ressources

Slide 76

Slide 76 text

Optimizing Web Vitals using Lighthouse https://web.dev/optimize-vitals-lighthouse/

Slide 77

Slide 77 text

CLS et impact sur le SEO https://fr.oncrawl.com/seo-technique/quest-ce-que-le-cumulative-layout-shift/

Slide 78

Slide 78 text

CLS et WordPress https://wp-rocket.me/how-to-improve-cls-on-wordpress/

Slide 79

Slide 79 text

Merci ! Slides sur speakerdeck.com/goetter