Fermer

mars 9, 2020

Il est à nouveau important de régler la hauteur et la largeur des images


À propos de l'auteur

Barry Pollard est développeur de logiciels et auteur du livre Manning HTTP / 2 en action . Il pense que le Web est incroyable mais veut le rendre encore meilleur.
En savoir plus
Barry

Grâce à certains changements récents dans les navigateurs, il vaut maintenant la peine de définir les attributs width et height sur vos images pour éviter les changements de mise en page et améliorer l'expérience de votre site

Les défenseurs des performances Web ont souvent conseillé d'ajouter des dimensions à vos images pour de meilleures performances afin de permettre à la page d'être disposée avec l'espace approprié pour l'image, avant que l'image elle-même ne soit téléchargée. Cela évite un changement de mise en page lorsque l'image est téléchargée – quelque chose que Chrome a récemment commencé à mesurer dans la nouvelle métrique de mise en page cumulative .

Eh bien, un sale, petit, secret – pas si connu en dehors de la défenseurs de la performance Web – c'est que, jusqu'à récemment, cela n'a pas fait de différence dans beaucoup de cas, comme nous le verrons ci-dessous. Cependant, l'ajout d'attributs largeur et hauteur à votre balisage est redevenu utile après quelques changements récents dans le monde CSS et l'adoption rapide de ces changements par le site Web le plus populaire.

Lecture recommandée

La propriété CSS contient vous permet d'expliquer votre mise en page au navigateur, afin d'optimiser les performances. Cependant, cela comporte certains effets secondaires en termes de mise en page. En savoir plus →

Pourquoi ajouter de la largeur et de la hauteur était un bon conseil

Prenez par exemple cette page simple:

Votre titre

Paragraphe d'introduction.

Lorem ipsum dolor sit amet, consectetur… [19659014] Cela peut s'afficher en deux étapes, d'abord lorsque le code HTML est téléchargé, puis ensuite une fois que l'image est téléchargée. Avec le code ci-dessus, cela ferait sauter le contenu principal une fois l'image téléchargée et l'espace nécessaire pour l'afficher peut être calculé:

 Un exemple de mise en page avec un titre et deux paragraphes, où le deuxième paragraphe doit se déplacer
Décalage de la mise en page après le chargement de l'image. ( Grand aperçu )

Les changements de disposition sont très perturbateurs pour l'utilisateur, surtout si vous avez déjà commencé à lire l'article et que vous êtes soudainement renversé par une secousse de mouvement, et vous devez retrouver votre place. Cela met également du travail supplémentaire sur le navigateur pour recalculer la mise en page lorsque chaque image arrive sur Internet. Sur une page complexe avec beaucoup d'images, cela peut placer une charge considérable sur l'appareil à un moment où il y a probablement beaucoup de meilleures choses à gérer!

La façon traditionnelle d'éviter cela était de fournir une largeur Les attributs et height dans le balisage donc même lorsque le navigateur a juste le HTML, il est toujours capable d'allouer la quantité appropriée d'espace. Donc, si nous changeons l'exemple ci-dessus comme suit:

Votre titre

Paragraphe d'introduction.

Lorem ipsum dolor sit amet, consectetur…

Ensuite, le rendu se produit comme ci-dessous, où l'espace approprié est mis de côté pour l'image à son arrivée, et il n'y a pas de décalage discordant du texte lors du téléchargement de l'image:

 Un exemple de maquette de mise en page avec un titre, un paragraphe, un espace pour une image puis un deuxième paragraphe, où le le texte ne se décale pas lors du chargement de l'image.
Le texte ne doit pas se déplacer si les dimensions de l'image sont fournies afin que l'espace approprié puisse être alloué. ( Grand aperçu )

Même en ignorant l'impact gênant pour l'utilisateur du contenu qui saute (ce que vous ne devriez pas faire!), L'impact sur le processeur peut également être assez important. La capture d'écran ci-dessous montre les calculs de performances effectués par Chrome sur un site sur lequel je travaille et qui possède une galerie d'environ 100 images. Le côté gauche montre les calculs lorsque largeur et hauteur sont fournis, et à droite quand ils ne le sont pas.

 Deux captures d'écran des outils Chrome Dev montrant différents temps de disposition de 75 ms à 450 ms à gauche et 124 ms à 2709 ms à droite
Calculs de performances avec et sans dimensions. ( Grand aperçu )

Comme vous pouvez le voir, l'impact est considérable - en particulier sur les appareils bas de gamme et la faible vitesse du réseau, où les images arrivent séparément. Cela augmente considérablement le temps de chargement.

Comment CSS interagit avec les largeurs et les hauteurs des éléments

Les largeurs et les hauteurs d'une image peuvent provoquer des problèmes lorsque vous essayez de les modifier à l'aide de CSS. Par exemple, si vous souhaitez limiter vos images à une certaine largeur, vous pouvez utiliser le CSS suivant:

 img {
  largeur max: 100%;
} 

Ceci remplacera la largeur de l'image et la contraindra si nécessaire, mais si vous avez explicitement défini la hauteur sur la balise d'image, nous ne remplaçons pas cela ( seulement la largeur) et vous vous retrouverez avec une image étirée ou écrasée, car nous n'avons plus conservé le rapport d'aspect de l'image:

 Un exemple de maquette de mise en page avec une image vraiment étirée. [19659016] Les conflits de dimensions d'image entre HTML et CSS peuvent créer des images étirées (ou écrasées!). (<a href= Grand aperçu )

Ceci est en fait très facilement corrigé en ajoutant une ligne height: auto au CSS afin que l'attribut height du HTML soit également remplacé:

 img {
  largeur max: 100%;
  hauteur: auto;
} 

Cependant, je trouve que cela surprend toujours les gens et les amène parfois à ne pas spécifier les dimensions de l'image dans le HTML. Sans aucune dimension d'image, vous pouvez vous en sortir en spécifiant simplement largeur maximale: 200 pixels dans le CSS sans avoir à spécifier hauteur: auto et le navigateur déterminera automatiquement la hauteur elle-même -

Donc, une fois que nous avons ajouté les dimensions et que l'astuce hauteur: auto nous obtenons le meilleur des deux mondes, non? Pas de changements de mise en page, mais aussi la possibilité de redimensionner les images en utilisant CSS? Eh bien, jusqu'à très récemment, vous pourriez avoir été surpris de découvrir que la réponse était en fait: non ( j'étais - c'est pourquoi j'ai décidé d'écrire cet article).

Par exemple, prenez le code ci-dessous:

Votre titre

Paragraphe d'introduction.

Lorem ipsum dolor sit amet, consectetur…

Cela aurait entraîné cette charge:

 Un autre exemple de maquette de mise en page avec un titre et deux paragraphes, où le deuxième paragraphe doit être déplacé vers le bas pour faire de la place à une image.
Des changements de disposition se produisent lorsque hauteur: auto est utilisé en CSS. ( Grand aperçu )

Attendez, que se passe-t-il ici? Nous revenons au premier problème. Je pensais avoir dit qu'en spécifiant les dimensions de l'image dans le HTML, vous pouviez éviter ce problème de décalage de mise en page? Eh bien, c'est là que cela devient intéressant et mènera au point principal de cet article.

Le problème est que, à moins que vous ne donniez explicitement largeur et hauteur valeurs CSS à vos images - et qui veut se limiter comme ça dans un monde réactif où vous voulez que l'image se développe ou se rétrécisse pour remplir l'espace disponible - alors CSS aura besoin des dimensions du fichier image lui-même pour comprendre le auto partie des dimensions. Il a ignoré les attributs largeur et hauteur définis dans le HTML.

L'implication de tout cela est que la spécification de largeur et hauteur les attributs sur les images n'étaient souvent pas vraiment utiles dans beaucoup de cas. Oui, lorsqu'une image est affichée en taille réelle, sans que CSS ne modifie les dimensions, il est utile de résoudre le problème de décalage de mise en page. Cependant, lorsque vous utilisez CSS comme ci-dessous pour vous assurer que les images ne dépassent pas leur espace disponible, vous rencontrez des problèmes dès que la largeur disponible devient inférieure à la taille réelle de l'image.

 img {
  largeur max: 100%;
  hauteur: auto;
} 

Cela affecte toutes les pages où nous limitons la taille de l'image de manière réactive - c'est-à-dire les appareils mobiles à petit écran. Ce sont probablement les utilisateurs mêmes qui souffrent de contraintes réseau et d'une puissance de traitement limitée qui souffriront le plus des changements de configuration! Bien sûr, nous devrions idéalement fournir des images de taille appropriée pour la taille de l'écran, mais vous ne pouvez pas couvrir toutes les tailles d'appareils, si souvent les images auront besoin d'une redimensionnement par le navigateur, en particulier sur mobile.

De nombreux sites Web ne prend pas la peine de spécifier largeur s et hauteur s sur leurs balises . Cela pourrait être dû au fait qu'ils ne savaient pas que c'était utile, ou parce qu'ils étaient trop conscients de ce dont nous parlions ici et savaient que ce n'était pas vraiment utile dans de nombreux cas. Quelle que soit la raison, ce n'est souvent pas le cas. (Comment pouvons-nous même évangéliser en faisant l'effort de les utiliser compte tenu de ce que je viens de décrire?) Même l'outil d'audit populaire Lighthouse ne signale pas lorsque vous ne le faites pas (bien qu'à la lumière de certains des choses dont nous allons parler, qui est à nouveau en discussion ).

Contourner le problème

Les limites des images réactives sont connues depuis longtemps et de nombreuses solutions de contournement, y compris le soi-disant hack padding-bottom ont été créés pour contourner le problème. Cela utilise le fait que les pourcentages de rembourrage (y compris fond de rembourrage ) sont toujours basés sur la largeur du conteneur (pour assurer un rembourrage cohérent même si la hauteur et la largeur diffèrent). Ce fait peut donc être utilisé pour créer un conteneur dont la hauteur est définie en fonction d'un rapport de la largeur. Par exemple pour, supposons que nous ayons une image avec un rapport d'aspect de 16: 9, le code CSS suivant créera l'espace de taille appropriée pour l'image:

 .img-container {
  position: relative;
  rembourrage en bas: 56,25%; / * Rapport 16: 9 * /
  hauteur: 0;
  débordement caché;
}

.img-container img {
  position: absolue;
  en haut: 0;
  gauche: 0;
  largeur: 100%;
  hauteur: 100%;
} 

Les trois principaux inconvénients de cette technique sont les suivants:

  1. Elle nécessite un ratio codé en dur pour être calculé ( 56,25% - 9 ÷ 16 - dans cet exemple), donc potentiellement nécessite un CSS personnalisé pour chaque image différente.
  2. Le code CSS n'est pas exactement facile à retenir - l'oubli ou la suppression d'une seule ligne du code CSS ci-dessus va tout casser. Sans parler de cette technique, toutes les images doivent être enveloppées dans un élément conteneur supplémentaire.
  3. Il s'agit d'une technique plus avancée que tous les développeurs Web ne connaissent pas ou n'utilisent pas.

Et, soyons honnêtes - c'est un peu pirater! Donc, nous devrions vraiment résoudre ce problème correctement, n'est-ce pas?

Résolution du problème de redimensionnement

Le problème a été abordé à partir de plusieurs directions différentes par un certain nombre d'organismes de normalisation différents.

Le groupe de travail CSS ( CSS WG) a proposé la propriété d'aspect dont Rachel avait déjà parlé . Cela résoudrait le problème de complexité (problème 2) une fois qu'il serait disponible, et simplifierait le code ci-dessus pour ceci:

 img {
  largeur: 100%;
  hauteur: auto;
  rapport hauteur / largeur: 16/9;
} 

Beaucoup mieux! Ceci est particulièrement utile pour la vidéo où nous avons généralement un nombre défini de rapports d'aspect couramment utilisés, afin que nous puissions créer quelques classes comme ci-dessus pour chaque taille. C'est peut-être moins utile pour les images où les dimensions sont beaucoup moins standardisées, car cela ne résout pas le problème 1 (code CSS personnalisé requis par image), ni le problème 3 (les développeurs de sites Web devront se rappeler de le régler). C'est donc un pas en avant, mais pas une solution complète.

Par ailleurs, le Web Incubator Community Group (WICG) - un groupe de développeurs de navigateurs et d'autres parties intéressées qui peuvent expérimenter des technologies pour voir s'ils fonctionnent avant la normalisation formelle - a également créé une proposition pour y remédier . Ils ont proposé l'attribut intrinsicsize qui ressemblerait à ceci:

   

Comme il s'agit d'un attribut HTML, il peut être défini par image (résolution du problème 1 ), et est relativement facile à coder (résolution du problème 2), mais il était encore susceptible de souffrir de problèmes d'adoption (problème 3) à moins qu'il ne devienne très connu avec une forte poussée de l'ensemble de la communauté.

Nous avons déjà un méthode courante et bien connue pour régler la largeur et la hauteur sur les éléments (même s'ils ne sont pas utilisés autant qu'ils le devraient!) donc tout ce qui est nouveau, autre que cela va souffrir du problème de l'adoption. Et c'est là que la réponse (maintenant apparemment évidente!) S'est présentée.

Jen Simmons a proposé cette solution élégante et simple qu'elle avait trouvée, avec fantasai :

 

Plutôt que de coder en dur le rapport d'aspect il utilise la fonction CSS attr pour créer le rapport d'aspect approprié en fonction de la largeur de l'image et hauteur attributs fournis par le HTML. La fonction attr existe depuis un certain temps, mais sa portée est très limitée - elle est prise en charge pour le contenu par tous les navigateurs mais pas pour cas d'utilisation plus large de tout autre attribut comme largeur et hauteur ce qui est nécessaire ici.

Si attr a pu ] à utiliser pour les attributs bien connus largeur et hauteur des éléments img il pourrait alors être utilisé pour calculer automatiquement l'aspect - comme ci-dessus. Cela résoudrait le problème 1 (aucun rapport d'aspect codé en dur ne doit être défini dans le HTML ou le CSS), le problème 2 (très simple à ajouter) et, comme nous le verrons, il existe une réponse très simple au problème 3 (adoption

Fondamentalement, cette solution signifie que si les quatre conditions suivantes sont remplies, les dimensions correctes de l'image peuvent être calculées sans avoir à attendre que les images soient téléchargées, et donc sans avoir besoin de modifier la disposition du contenu:

  • hauteur est définie sur l'élément en HTML
  • largeur est définie sur l'élément en HTML
  • hauteur (ou largeur ) est définie dans le CSS - y compris en utilisant des valeurs de pourcentage comme largeur max: 100%;
  • largeur (ou hauteur ) est défini sur auto dans le CSS.

Si l'un de ces paramètres n'était pas défini, le calcul ne serait pas possible, échouerait et serait ignoré et devrait attendre que l'image soit en panne.

Donc, une fois que les navigateurs prennent en charge l'utilisation de la largeur HTML et hauteur pour calculer le rapport d'aspect nous pouvons résoudre notre problème très simplement sans changement de pratiquez le HTML et une ligne de code CSS! Comme mentionné ci-dessus, c'est également quelque chose que de nombreux développeurs Web ont peut-être déjà supposé se produire de toute façon.

Stimuler l'adoption de cette solution

Comme il ne s'agit que d'un attribut CSS, la proposition contient une autre tournure - elle pourrait être ajoutée à la feuille de style d'agent utilisateur utilisée par les navigateurs ne nécessiterait même pas aucune modification des développeurs Web pour en bénéficier.

La feuille de style d'agent utilisateur est l'endroit où les définitions CSS par défaut sont définies (par exemple, ce que taille de police l'élément h1 utilise), qui peut être remplacé par votre propre CSS si vous le souhaitez. En ajoutant le rapport d'aspect ci-dessus, nous n'avons pas besoin de favoriser l'adoption - nous l'activons essentiellement pour tous les sites qui remplissent les quatre conditions ci-dessus!

Cependant, cela ne dépendent de la fonction attr ayant accès aux attributs HTML width et height ainsi qu'à la propriété CSS d'aspect-ratio à venir terminé - ni l'un ni l'autre n'est encore arrivé. Au lieu de cela, comme solution plus facile, les navigateurs pourraient implémenter la logique équivalente en profondeur dans le rendu du code plutôt que de l'exposer via la feuille de style de l'agent utilisateur, mais l'effet est le même. Cette approche de mise en œuvre alternative a même été suggérée dans le cadre de la proposition .

Firefox est allé de l'avant et l'a fait à titre expérimental puis l'a activé par défaut pour Firefox 71 . Une fois que cela a été publié, votre site pourrait bien être devenu plus rapide gratuitement - merci Mozilla! Peut-être qu'à l'avenir, ils déplaceront ceci vers la méthode de feuille de style user-agent, mais pour l'instant, c'est suffisant (et peut-être plus performant?).

Compatibilité descendante

Lors de l'introduction d'un changement de comportement, il y a toujours un souci de compatibilité descendante et cette fonctionnalité n'était pas différente. En théorie, tant que les quatre attributs ont été correctement définis, il ne devrait y avoir aucune rupture avec cela.

Cependant, lorsque Firefox l'a initialement expérimenté, ils ont découvert des problèmes pour ceux qui définissaient la largeur et hauteur incorrecte dans leur code HTML. Alors qu'auparavant ces valeurs incorrectes étaient ignorées si le CSS les dépassait, elles étaient maintenant utilisées lorsque auto était défini et les images n'étaient pas affichées correctement et conduisaient à des images écrasées ou étirées. Vous pouvez maintenant affirmer que les développeurs Web ne devraient pas définir ces valeurs de manière incorrecte et, dans certains cas, ils seraient déjà cassés même sans ce changement (le cas ci-dessus lorsque vous n'avez pas défini la hauteur de : auto ), mais quand même, casser des sites n'est jamais une bonne chose. C'est aussi quelque chose que le Web essaie très fort d'éviter - et est surtout très bon pour l'éviter (c'est l'une de mes choses préférées sur le Web en tant que plate-forme).

La solution à ce problème, cependant, était relativement simple: que le rapport hauteur / largeur réel de l'image remplace tout rapport hauteur / largeur calculé par CSS. De cette façon, le rapport d'aspect calculé (incorrectement) peut être utilisé pour la mise en page initiale, mais peut ensuite être recalculé lorsque l'image est téléchargée, de sorte que l'image s'affiche comme elle l'était auparavant. Cela provoque un changement de mise en page (puisque l'espace incorrect a été alloué initialement) mais cela se produisait avant de toute façon, donc ce n'est pas pire. En fait, c'est souvent beaucoup mieux car un rapport d'aspect incorrect sera souvent plus proche de la vérité qu'un rapport d'aspect nul.

Déploiement vers d'autres navigateurs

Après l'expérimentation réussie de Firefox, Chrome a également décidé de mettre en œuvre this (utilisant à nouveau la méthode de mise en page codée pour l'instant plutôt que la feuille de style d'agent utilisateur par défaut), et l'a déployé par défaut dans Chrome 79 . Cela a également pris en charge les autres navigateurs à base de chrome (Edge, Opera et Brave, par exemple). Plus récemment, en janvier 2020, Apple l'a ajouté à l'édition Tech Preview de Safari ce qui signifie qu'il devrait bientôt arriver dans la version de production de Safari, et avec cela, le dernier des principaux navigateurs aura

Limitations

Il y a quelques limitations à connaître avec cette fonctionnalité, y compris des problèmes avec:

  • Direction artistique
  • Chargement paresseux
  • Non-images

Direction artistique

Le correctif fonctionne très bien pour calculer le rapport hauteur / largeur basé sur une largeur fixe et hauteur mais qu'en est-il quand ces changements? Ceci est connu sous le nom de direction artistique et un exemple est illustré ci-dessous:

 Deux exemples de maquettes de mise en page avec le premier étant une mise en page de bureau utilisant une image de style bannière large et le second, mobile, mise en page une image carrée.
«Direction artistique» utilise différentes photographies en fonction de l'espace disponible. ( Grand aperçu )

Dans ce cas, nous utilisons une image large pour ordinateur de bureau, puis une image carrée et recadrée pour mobile. Les images réactives peuvent être implémentées à l'aide des attributs srcset sur un élément :

  

ou avec l'élément comme celui-ci:

  
  
  
  

Actuellement, ces deux éléments permettent uniquement de définir la largeur et la hauteur une fois sur l'élément principal de secours et non sur les variantes individuelles . L'ajout de ceux-ci a été proposé mais jusque-là, c'est actuellement une limitation de la solution, et l'utilisation d'images de différentes dimensions connaîtra toujours un changement de disposition.

Lazy Loading

Cette fonctionnalité serait parfaitement adapté pour une utilisation avec chargement paresseux. Idéalement, toutes les images chargées paresseusement sont chargées hors écran lorsque vous faites défiler la page avant que l'image chargée paresseuse entre dans la fenêtre, mais ce n'est souvent pas le cas en fonction de la vitesse à laquelle l'utilisateur défile et du réseau, donc avoir l'image une zone correctement définie éviterait au moins le changement de disposition après le chargement. De plus, même lorsque le chargement se fait hors écran, les changements de disposition peuvent être coûteux en termes de temps CPU, comme nous l'avons montré ci-dessus.

Cependant, les techniques de chargement paresseux peuvent impliquer de ne pas utiliser d'élément ou au moins un sans src (pour empêcher le navigateur de télécharger l'image par défaut). Par conséquent, il est possible qu'il ne puisse pas bénéficier de cette récente modification selon la façon dont votre navigateur gère l'élément utilisé ou les éléments src -less . Bien que si la version CSS de cette solution devienne disponible, les développeurs de sites Web auront un plus grand contrôle sur la spécification du rapport d'aspect eux-mêmes.

Le chargement paresseux natif a été récemment publié par l'équipe Chrome et il a depuis été ajouté à la spécification HTML . D'autres navigateurs cherchent également à le prendre en charge avec Firefox qui l'obtiendra également bientôt et Safari, espérons-le pas trop tard . Cela utilise l'élément avec un src avec une syntaxe comme celle-ci (y compris lorsqu'il est utilisé dans le cadre de l'élément ):

  

Parfait! Eh bien, malheureusement, j'ai découvert que cette solution de hauteur et de largeur n'est pas compatible avec la fonctionnalité native de chargement différé récemment publiée, comme peut être vu sur cette page de test . J'ai soulevé un bogue pour ce problème et j'espère que l'équipe Chrome le corrigera bientôt.

Non-Images

Actuellement, les navigateurs qui l'ont implémenté n'ont fait que pour le [19659006]mais il serait également utile pour les éléments