Pour prédire une image candidate adaptative, résolvez sizes en une largeur CSS, multipliez-la par le ratio de pixels de l’appareil, puis comparez cette cible à srcset. Vérifiez ensuite l’URL sélectionnée : les navigateurs gardent une marge de manœuvre pour le choix final.

Ce guide s’adresse aux personnes qui vérifient une page Web qu’elles ont créée dans Chrome sur un Mac. Vous calculerez les candidates probables, testerez une page locale contenant des formes abstraites originales et distinguerez une déclaration de taille trompeuse du comportement normal de sélection du navigateur.

Que communiquent sizes, srcset et le DPR au navigateur ?

Avec les descripteurs de largeur, srcset répertorie les ressources disponibles et leurs largeurs intrinsèques en pixels. Un descripteur tel que 800w doit décrire une image qui fait réellement 800 pixels de large. Gardez les descripteurs de largeur et les descripteurs de densité tels que 2x dans des ensembles de sources distincts ; les mélanger dans un même srcset n’est pas valide. La référence MDN sur l’élément image décrit ces exigences.

sizes fournit la largeur d’affichage prévue pour la sélection de la ressource. Le navigateur évalue les conditions dans l’ordre et utilise la première entrée correspondante. Placez la valeur de repli inconditionnelle en dernier. Les tailles de source acceptent des longueurs comme 480px, 50vw et calc(100vw - 32px) ; les valeurs en pourcentage comme 50% ne sont pas des largeurs d’emplacement valides. Utiliser des images adaptatives en HTML

Le CSS détermine les dimensions affichées. Considérez votre CSS et votre liste explicite sizes comme deux descriptions que vous devez garder cohérentes : l’une détermine la mise en page, tandis que l’autre guide la sélection de la ressource. Modifier uniquement sizes ne met pas en œuvre la mise en page correspondante. Norme HTML : attributs sizes

Le DPR décrit le rapport entre les pixels physiques et les pixels CSS. Lisez window.devicePixelRatio au lieu de supposer une valeur à partir du modèle de Mac ou du nom de l’écran. Le zoom de la page peut modifier cette valeur, tout comme le déplacement d’une fenêtre d’un écran à un autre. Le zoom par pincement ne modifie pas le DPR. MDN : Window.devicePixelRatio

Comment calculer la candidate probable ?

Pour une taille de source résolue S, une largeur de ressource W et un DPR D, utilisez ces deux calculs équivalents :

Largeur cible de la ressource = S × D
Densité effective de la candidate = W ÷ S

Le modèle de traitement HTML normalise les descripteurs de largeur en divisant la largeur de chaque candidate par la taille de source. MDN explique également la prédiction pratique : multiplier l’indication de taille par le DPR. Norme HTML : normalisation des densités de source, MDN : HTMLImageElement.sizes

Pour obtenir une estimation pratique, choisissez la plus petite candidate dont la largeur est égale ou supérieure à la cible. Si toutes les candidates sont inférieures à la cible, indiquez la plus grande disponible et consignez l’écart. Cette règle de prédiction explicite sera appliquée aux exercices ci-dessous. La norme HTML laisse le choix final à l’implémentation ; elle n’exige pas que tous les navigateurs suivent cette règle d’arrondi. Norme HTML : sélection d’une source d’image

Considérez cette liste de tailles de source, associée aux candidates 480w, 800w, 1200w et 1440w :

(max-width: 600px) calc(100vw - 32px),
(max-width: 1200px) calc(50vw - 32px),
568px

100vw représente la largeur de la fenêtre d’affichage et 50vw la moitié de cette largeur. Ces unités se rapportent à la fenêtre d’affichage, pas au conteneur parent de l’image. Valeurs et unités CSS : longueurs en pourcentage de la fenêtre d’affichage

Le tableau suivant présente des calculs illustratifs, et non des résultats relevés dans un navigateur. La dernière colonne applique la règle de prédiction indiquée.

Largeur de la fenêtre d’affichage, px CSS DPR Taille de source résolue, px CSS Largeur cible de la ressource, px Candidate prédite
600 1 568 568 800w
600 2 568 1,136 1200w
601 2 268,5 537 800w
1,000 1 468 468 480w
1,000 2 468 936 1200w
1,400 2 568 1,136 1200w
1,400 3 568 1,704 1440w, inférieure à la cible

Le passage de 600 à 601 pixels CSS est particulièrement utile à tester. À 600, la première condition fournit un emplacement presque aussi large que la fenêtre. À 601, la deuxième condition fournit un emplacement beaucoup plus étroit. Une fenêtre plus large produit donc une image cible plus petite. Cela découle directement du contrat de mise en page défini ici.

Pour une fenêtre de 1 000 pixels et un DPR de 2, la taille de source est de 468 pixels CSS. Les quatre candidates ont des densités effectives d’environ 1.03x, 1.71x, 2.56x et 3.08x. Selon notre règle de prédiction, 1200w est la première candidate qui dépasse la densité cible de 2x.

Comment créer un test local complet ?

Utilisez un Mac sur lequel Chrome et Python 3.8 ou une version ultérieure sont installés. Enregistrez le programme complet ci-dessous sous le nom responsive_demo.py dans un éditeur de texte brut. Il génère quatre fichiers PNG contenant le même rectangle et le même cercle, crée une page correspondante et démarre un serveur local. Tous les fichiers générés sont placés dans un nouveau répertoire temporaire, afin de ne pas écraser les fichiers existants.

La page utilise volontairement une image chargée sans différé et des tailles de source explicites. Ses largeurs CSS correspondent aux trois branches utilisées dans le tableau de calcul. Le serveur utilise ThreadingHTTPServer et le gestionnaire de requêtes basé sur un répertoire, tels qu’ils sont documentés par Python. Python : http.server

from functools import partial
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
import struct
import tempfile
import zlib


def chunk(kind, data):
    return (
        struct.pack("!I", len(data)) + kind + data
        + struct.pack("!I", zlib.crc32(kind + data))
    )


def make_png(width):
    height = width // 2
    rows = []
    for y in range(height):
        row = bytearray()
        for x in range(width):
            color = (242, 244, 248)
            if width // 8 <= x < width // 2 and height // 4 <= y < 3 * height // 4:
                color = (70, 100, 160)
            if (x - 3 * width // 4) ** 2 + (y - height // 2) ** 2 < (height // 5) ** 2:
                color = (220, 160, 60)
            row.extend(color)
        rows.append(b"\x00" + row)
    header = struct.pack("!IIBBBBB", width, height, 8, 2, 0, 0, 0)
    return (
        b"\x89PNG\r\n\x1a\n"
        + chunk(b"IHDR", header)
        + chunk(b"IDAT", zlib.compress(b"".join(rows)))
        + chunk(b"IEND", b"")
    )


page = '''<!doctype html>
<html lang="en">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Shape A candidate test</title>
<style>
  body { margin: 0; padding: 16px; font-family: sans-serif; }
  #shape { display: block; width: calc(100vw - 32px); height: auto; }
  @media (min-width: 600.01px) {
    #shape { width: calc(50vw - 32px); }
  }
  @media (min-width: 1200.01px) {
    #shape { width: 568px; }
  }
</style>
<p>Shape A: rectangle and circle</p>
<img id="shape" src="shape-a-800.png" width="1440" height="720"
     alt="Blue rectangle and amber circle on a pale background"
     srcset="shape-a-480.png 480w, shape-a-800.png 800w,
             shape-a-1200.png 1200w, shape-a-1440.png 1440w"
     sizes="(max-width: 600px) calc(100vw - 32px),
            (max-width: 1200px) calc(50vw - 32px), 568px">
</html>
'''

root = Path(tempfile.mkdtemp(prefix="responsive-shapes-"))
for width in (480, 800, 1200, 1440):
    (root / f"shape-a-{width}.png").write_bytes(make_png(width))
(root / "index.html").write_text(page, encoding="utf-8")
handler = partial(SimpleHTTPRequestHandler, directory=str(root))
with ThreadingHTTPServer(("127.0.0.1", 0), handler) as server:
    print(f"Files: {root}", flush=True)
    print(f"Open http://127.0.0.1:{server.server_port}/", flush=True)
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        pass

Dans Terminal, accédez au dossier où vous avez enregistré le programme, puis exécutez :

python3 responsive_demo.py

Ouvrez dans Chrome l’adresse locale affichée par le programme. Laissez Terminal ouvert pendant le test ; appuyez sur Control+C dans Terminal lorsque vous avez terminé. Le programme demande un port disponible : utilisez donc l’adresse affichée au lieu de supposer un numéro de port fixe.

Les seuils CSS utilisent 600.01px et 1200.01px pour les largeurs entières de la fenêtre d’affichage du test sur ordinateur. Testez les valeurs entières exactes du tableau. Lorsque vous adaptez l’exemple à une mise en page de production, faites correspondre les points de rupture réels de votre CSS aux conditions de taille de source, y compris pour les largeurs fractionnaires.

Comment vérifier la sélection dans Chrome sur un Mac ?

Faites un clic droit sur la forme et choisissez Inspecter pour ouvrir DevTools avec son élément image sélectionné. Chrome indique que cette méthode permet d’inspecter directement un élément et les styles qui lui sont appliqués. Ouvrir Chrome DevTools

  1. Cliquez sur Basculer la barre d’outils d’appareil et choisissez Responsive sous Dimensions.
  2. Réglez la largeur de la fenêtre d’affichage sur 1000.
  3. Dans le menu Plus d’options de la barre d’outils, choisissez Ajouter un ratio de pixels de l’appareil, puis sélectionnez le DPR 2.
  4. Si nécessaire, choisissez Plus d’options, puis Ajouter un type d’appareil et sélectionnez Ordinateur.
  5. Ouvrez Réseau, activez Désactiver le cache, puis rechargez la page avec DevTools ouvert.
  6. Recherchez l’image demandée en filtrant sur shape-a.

Chrome décrit les contrôles de la fenêtre d’affichage, du DPR et du type d’appareil dans son guide du mode appareil, et le contrôle du cache dans sa référence sur les fonctionnalités réseau.

Une fois la page chargée, exécutez cet extrait de diagnostic complet dans la Console de DevTools :

(() => {
  const image = document.getElementById("shape");
  if (!image) throw new Error("The Shape A image was not found.");

  const viewport = window.innerWidth;
  const slot = window.matchMedia("(max-width: 600px)").matches
    ? viewport - 32
    : window.matchMedia("(max-width: 1200px)").matches
      ? viewport / 2 - 32
      : 568;

  console.table({
    viewportCSSPixels: viewport,
    devicePixelRatio: window.devicePixelRatio,
    declaredSlotCSSPixels: slot,
    renderedWidthCSSPixels: image.getBoundingClientRect().width,
    targetResourcePixels: slot * window.devicePixelRatio,
    selectedURL: image.currentSrc,
    naturalWidthCSSPixels: image.naturalWidth
  });
})();

Cet extrait calcule l’emplacement déclaré spécifiquement pour cette démonstration ; ce n’est pas un analyseur général de sizes. Comparez l’emplacement déclaré à la largeur affichée, puis comparez le nom du fichier sélectionné au tableau de prédiction.

currentSrc indique l’URL complète sélectionnée par le navigateur. Cela ne prouve pas que la ressource a été chargée correctement : examinez également la requête de l’image et le résultat affiché. Lire src ne révélerait que l’attribut de repli dans cet exemple. MDN : HTMLImageElement.currentSrc

Évitez d’interpréter naturalWidth comme la largeur encodée du PNG. Il s’agit d’une largeur corrigée selon la densité, exprimée en pixels CSS. Pour cet exemple contrôlé, les dimensions et le nom du fichier généré indiquent la largeur de sa ressource. MDN : HTMLImageElement.naturalWidth

Répétez le test à 600 et 601 pixels CSS, en rechargeant la page pour chaque cas. Consignez la largeur de la fenêtre d’affichage, le DPR indiqué, la taille de l’emplacement, le nom du fichier sélectionné et la réussite ou l’échec de la requête. Ces relevés permettent de distinguer un résultat reproductible après un chargement complet d’une suite de choix effectués pendant le redimensionnement d’une page déjà chargée.

Que vérifier si la prédiction diffère ?

Vérifiez les paramètres avant de modifier la liste des candidates :

  1. Vérifiez la famille de descripteurs. Avec des descripteurs de densité tels que 1x et 2x, n’appliquez pas le calcul des descripteurs de largeur via sizes.
  2. Vérifiez la première condition correspondante. Une condition correspondante située plus tôt a priorité sur les entrées suivantes.
  3. Comparez les largeurs déclarée et affichée. Une déclaration 100vw peut surestimer un emplacement dont le CSS limite la largeur à une colonne étroite.
  4. Lisez le DPR réel. Vérifiez-le de nouveau après un zoom de page ou un changement d’écran.
  5. Comparez des rechargements contrôlés. Conservez la même fenêtre d’affichage, le même DPR et les mêmes conditions de chargement lors des tests répétés.
  6. Vérifiez la disponibilité de la ressource. Une URL sélectionnée et une image affichée avec succès sont deux observations distinctes.

Des tailles de source explicites manquantes ou inutilisables peuvent amener l’analyseur HTML à utiliser sa valeur par défaut 100vw. Cela peut expliquer une cible étonnamment grande pour une image étroite. Fournissez une liste de tailles de source précise au lieu de supposer que le navigateur déduira de votre CSS la largeur de colonne prévue. Norme HTML : analyse d’un attribut sizes

Si une page utilise un élément picture, déterminez quelle branche de source s’applique avant de calculer les densités. La sélection de la source précède le choix parmi les candidates de cette branche ; les recadrages différents relèvent de ce mécanisme de direction artistique. Utiliser des images adaptatives en HTML

Quelles limites de prise en charge affectent cette méthode ?

MDN indique que la propriété sizes est largement prise en charge par les navigateurs, mais cela ne signifie pas que tous les mots-clés plus récents le sont autant. Les conditions explicites utilisées ici permettent un test simple sans dépendre du dimensionnement automatique. MDN : HTMLImageElement.sizes

sizes="auto" est valide pour les images chargées de manière différée et permet à la sélection de tenir compte de leur largeur dans la mise en page. Si vous l’utilisez, conservez des tailles de repli explicites après auto pour les navigateurs qui ne prennent pas ce mot-clé en charge, et fournissez les dimensions de l’image. Ne l’insérez pas dans cet exemple de chargement immédiat sans modifier ces prérequis. La référence MDN sur l’élément image

Les contrôles d’appareil de Chrome permettent de tester le comportement de Chrome dans des conditions émulées. Ils ne démontrent pas les choix de candidates de Safari ou de Firefox. Chrome précise également que le mode appareil est une approximation : testez donc directement dans un autre navigateur si son comportement vous importe. Chrome DevTools : limites du mode appareil

Une prédiction utile se termine par un relevé vérifiable : l’ensemble de sources applicable, la taille de source résolue, le DPR indiqué, la cible calculée et le currentSrc observé. Lorsque ces paramètres correspondent à la mise en page définie, vous pouvez expliquer clairement le choix de la ressource et déterminer si la prochaine modification concerne le CSS, sizes ou les largeurs d’image disponibles.

Sources