Aller au contenu
duxt

ProseImg

Une image : consciente du thème, adaptative et agrandissable.

Chaque image d'une page Markdown.

Ce qu'elle ajoute

Deux variantes. Une capture d'un éditeur sombre sur une page blanche — ou l'inverse — est la laideur la plus courante d'une documentation, et CSS ne peut pas la corriger parce que ce sont les pixels qui sont faux, pas le cadre. Une page peut nommer un second fichier :

![La barre latérale](/shots/sidebar.png){dark="/shots/sidebar-dark.png"}

Deux requêtes, pas un fichier. L'image dans la page et celle du dialogue d'agrandissement demandent des largeurs différentes : un téléphone ne télécharge donc plus l'original de 2400 px pour le dessiner dans une colonne de 48rem. Ce sont deux srcset produits par @nuxt/image ; ni l'un ni l'autre n'est un fichier que quelqu'un doit préparer.

Cliquer pour agrandir, sauf si l'image demande le contraire :

![Un schéma](/diagram.svg){zoom="false"}

Une image agrandissable porte un petit indicateur dans son coin, en permanence plutôt qu'au survol — un curseur n'existe pas sur un appareil tactile et reste invisible sur une capture de la page. L'image est un bouton : Tab l'atteint avec un anneau visible, Entrée et Espace ouvrent le dialogue, Échap le ferme et rend le focus. Avec zoom="false", pas d'indicateur, pas d'anneau et rien où tabuler.

Un fond pour une image transparente. Un schéma dont le trait est pensé pour une surface claire disparaît sur une page sombre. Indiquez une couleur par thème — n'importe quelle couleur CSS, var(--card) compris :

![Un schéma](/diagram.svg){background="#fafafa" dark-background="#171717"}

Des couleurs plutôt que des classes, volontairement : la feuille de style de la couche est construite à partir de ses propres composants, jamais du Markdown, si bien qu'une classe dark:bg-… écrite dans une page n'aurait aucun CSS derrière elle.

La visionneuse occupe tout l'écran au-dessus de la page floutée. Ses commandes — zoom arrière, le niveau de zoom (qui le réinitialise), zoom avant, ouvrir l'original dans un nouvel onglet, fermer — flottent sur une ligne au-dessus de l'image et le texte alternatif se place en dessous, si bien qu'aucun ne la masque. La molette zoome autour du curseur et le pincement autour des doigts ; un clic sur l'image zoome à 200 % à cet endroit et un second revient ; +, - et 0 font de même au clavier. Une image zoomée se fait glisser pour la déplacer et charge le fichier original pour rester nette. Un clic autour ferme la visionneuse.

API

Props

PropTypeDéfautNotes
srcstring—Tel qu'écrit
altstring—Tel qu'écrit
darkstring—Un second fichier, servi sous le thème sombre
zoombooleantruefalse laisse l'image inerte
widthnumber—Facultatif ; voir Dimensions plus bas
heightnumber—Facultatif ; voir Dimensions plus bas
sizesstring—Remplace la politique de la page ; voir Tailles
backgroundstring—Une couleur CSS derrière une image transparente, dans la page et la visionneuse
dark-backgroundstring—La même sous le thème sombre ; se replie sur background

Tailles

Le thème sait une chose que @nuxt/image ne peut pas savoir : la largeur de la boîte dans laquelle il dessine une image. C'est tout ce qu'il configure.

  • Dans la page — sm:95vw md:768px. Sous md, l'article vaut la fenêtre moins ses marges ; à partir de md, il est plafonné à max-w-3xl quel que soit l'écran, si bien que la largeur demandée cesse de croître au lieu de grimper sur un écran 4K.
  • Dans le dialogue — sm:96vw md:96vw lg:96vw xl:1264px, suivant la fenêtre jusqu'au plafond propre au dialogue, min(96vw, 80rem).

Les deux ne nomment que les points de rupture que @nuxt/image fournit déjà : qui redéfinit image.screens garde sa définition. La couche ne déclare aucun screens à elle.

Une image qui n'est pas aussi large que la colonne de texte — un logo, un badge, un schéma en marge — le dit :

![Le badge](/badge.png){sizes="sm:50vw md:200px"}

sizes est la syntaxe propre de @nuxt/image et n'atteint que l'image de la page. Le dialogue garde sa politique : une politique qui décrit la colonne de texte ne peut pas décrire un dialogue.

Dimensions

width et height sont facultatifs et le restent — la plupart des pages les omettent, et les exiger casserait toutes celles déjà écrites.

Donnez-les tout de même quand vous le pouvez. Ce sont elles qui permettent au navigateur de réserver la boîte avant l'arrivée du fichier ; sans elles, l'image n'a pas de rapport intrinsèque tant qu'elle n'est pas chargée, et le texte en dessous bouge quand elle l'est. Le composant conserve le rapport de la paire qu'on lui donne et n'invente rien quand on ne lui en donne aucune : il n'y a ni rapport par défaut ni recadrage, car un mauvais rapport est pire qu'un saut.

Une image plus petite que la colonne est laissée à sa propre taille plutôt qu'étirée.

Formats

SVG et GIF animé passent sans être touchés, dans la page comme dans le dialogue, sans aucun srcset. Un vecteur n'a pas de pixels à rééchantillonner — en demander un de 608 px de large matricialise un fichier qui était net à toutes les tailles — et un GIF passé dans une chaîne de matricialisation revient réduit à sa première image.

C'est ce que fait le composant, pas une affirmation sur les fournisseurs : certains laissent ces formats passer, d'autres non, et une couche de documentation ne peut pas savoir lequel son consommateur a configuré. Les sources adaptatives concernent les formats matriciels pour lesquels l'agrandissement existe — PNG, JPEG, WebP, AVIF.

Fournisseurs

La couche ne définit aucune clé image. Quel service transforme une image appartient au consommateur, comme sources : un fournisseur choisi par la couche est un fournisseur que chaque consommateur doit défaire, et il décide d'un compte et d'une facture autant que d'une URL. Configurez @nuxt/image comme dans n'importe quelle application Nuxt ; le composant ne lui remet que deux chaînes sizes.

Laissé à lui-même, @nuxt/image choisit seul, et les trois cas que rencontre un site de documentation sont :

  • Un serveur Node. ipx transforme à la demande sous /_ipx/…. Il lui faut sharp, une liaison native, que la sortie Node embarque déjà.
  • Un site généré (nuxt generate). ipxStatic écrit chaque variante au moment de la construction. Plus rien ne tourne ensuite, et la sortie grossit des variantes — le marché qu'un site entièrement statique passe de toute façon.
  • Un runtime en périphérie — Cloudflare Workers, et tout ce qui n'est ni Node ni statique. Aucun transformateur ne tourne et les images sont servies telles qu'elles ont été versionnées. Un site prérendu sur un tel runtime ne doit pas être configuré sur ipx : c'est une liaison native et elle ne peut pas y tourner du tout. Tournez-vous vers un fournisseur CDN si les transformations sont souhaitées.

Les variantes du dialogue sont générées lors d'une construction statique alors même que le dialogue est fermé au rendu de la page — le composant les déclare lui-même au crawler de prérendu. Rien n'est téléchargé tant que le dialogue n'est pas ouvert.

Une image avec zoom="false" n'en reçoit aucune. Il n'y a pas de dialogue à ouvrir, donc chaque fichier à la taille du dialogue écrit pour elle serait une sortie que personne ne peut jamais demander.

Notes

La variante sombre est nommée explicitement plutôt que devinée par convention. Dériver -dark d'un nom de fichier signifie qu'un fichier manquant devient une image cassée, et l'auteur ne l'apprend jamais.

Une image issue d'une source clonée depuis un autre dépôt n'a pas de route à elle : Content télécharge l'arbre dans .data/content/, et rien ne copie ses ressources dans public/. Les chemins de ces exemples sont absolus vers le public/ du site consommateur, qui est l'endroit où une image de documentation doit vivre aujourd'hui.

Cette page vous a-t-elle été utile ?