Leçon 11 / 15

Utiliser le composant Image

20 min Next.js — pages, layout et rendu serveur Gratuit

Objectif : Afficher les images locales du catalogue avec next/image et renseigner les propriétés requises pour leur rendu accessible et optimisé.

Une carte de randonnée sans visuel donne peu d’indices sur le paysage que vous allez découvrir. Vous avez déjà placé les fichiers dans public/images ; il reste à les afficher sans perdre les bénéfices du composant d’image de Next.js. Dans cette leçon, vous ajoutez un visuel à chaque itinéraire et vous le rendez disponible sur la liste comme sur sa page de détail.

Associer les images aux itinéraires

Dans la leçon « Préparer les fichiers image », vous avez repéré les adresses publiques /images/foret.jpg et /images/montagne.jpg. Ajoutez à chaque objet d’itinéraire le chemin de son fichier, une description destinée aux technologies d’assistance, puis la largeur et la hauteur réelles du fichier. Les dimensions doivent correspondre aux images présentes dans votre dossier : les valeurs ci-dessous supposent des fichiers de 1200 × 800 pixels.

Afficher les images sur la page d’accueil

Le composant Image de next/image prend en charge l’affichage des images dans une application Next.js. Pour un fichier local référencé par son chemin public, fournissez src, alt, width et height. Le texte de alt décrit le contenu utile de l’image ; ne recopiez pas simplement le nom du fichier.

app/page.tsxTexte
import Image from "next/image";
import Link from "next/link";

const itineraires = [
  {
    slug: "foret",
    nom: "La forêt des brumes",
    resume: "Un parcours ombragé au cœur des arbres.",
    image: "/images/foret.jpg",
    descriptionImage: "Sentier de randonnée traversant une forêt",
    largeur: 1200,
    hauteur: 800
  },
  {
    slug: "montagne",
    nom: "Le belvédère des cimes",
    resume: "Une montée vers un panorama de montagne.",
    image: "/images/montagne.jpg",
    descriptionImage: "Paysage de montagne visible depuis un sentier",
    largeur: 1200,
    hauteur: 800
  }
];

export default function Accueil() {
  return (
    <>
      <section className="sentier-introduction">
        <h1>Randonnées à découvrir</h1>
        <p>Choisissez un itinéraire selon vos envies.</p>
      </section>
      <section className="sentier-grille" aria-label="Itinéraires disponibles">
        {itineraires.map((itineraire) => (
          <article className="sentier-carte" key={itineraire.slug}>
            <Link className="sentier-lien" href={`/itineraires/${itineraire.slug}`}>
              <Image
                className="sentier-image"
                src={itineraire.image}
                alt={itineraire.descriptionImage}
                width={itineraire.largeur}
                height={itineraire.hauteur}
              />
              <h2>{itineraire.nom}</h2>
            </Link>
            <p>{itineraire.resume}</p>
          </article>
        ))}
      </section>
    </>
  );
}

L’import de Image est distinct de celui de Link : le premier affiche le visuel, le second conserve la navigation vers la fiche. Les propriétés d’image sont lues dans l’objet en cours de parcours, ce qui associe chaque fichier à son itinéraire. Le chemin commence par / parce que les ressources de public sont accessibles depuis la racine du site.

Afficher le visuel sur une page de détail

La page de détail utilise les mêmes informations d’image : elle doit donc contenir les mêmes objets d’itinéraire et les mêmes valeurs. L’exemple ci-dessous conserve la recherche par slug et l’appel à notFound() lorsque la route ne correspond à aucun itinéraire. Il complète le rendu existant en affichant l’image sélectionnée avant les informations de randonnée.

app/itineraires/[slug]/page.tsxTexte
import Image from "next/image";
import Link from "next/link";
import { notFound } from "next/navigation";

const itineraires = [
  {
    slug: "foret",
    nom: "La forêt des brumes",
    description: "Un parcours ombragé au cœur des arbres.",
    image: "/images/foret.jpg",
    descriptionImage: "Sentier de randonnée traversant une forêt",
    largeur: 1200,
    hauteur: 800,
    distance: "6 km",
    duree: "2 h"
  },
  {
    slug: "montagne",
    nom: "Le belvédère des cimes",
    description: "Une montée vers un panorama de montagne.",
    image: "/images/montagne.jpg",
    descriptionImage: "Paysage de montagne visible depuis un sentier",
    largeur: 1200,
    hauteur: 800,
    distance: "9 km",
    duree: "4 h"
  }
];

type PageProps = {
  params: { slug: string };
};

export default function Page({ params }: PageProps) {
  const itineraire = itineraires.find((element) => element.slug === params.slug);

  if (!itineraire) {
    notFound();
  }

  return (
    <article className="sentier-carte">
      <Image
        className="sentier-image"
        src={itineraire.image}
        alt={itineraire.descriptionImage}
        width={itineraire.largeur}
        height={itineraire.hauteur}
      />
      <div className="sentier-details">
        <h1>{itineraire.nom}</h1>
        <p>{itineraire.description}</p>
        <p>Distance : {itineraire.distance}</p>
        <p>Durée : {itineraire.duree}</p>
      </div>
      <Link className="sentier-retour" href="/">Retour au catalogue</Link>
    </article>
  );
}

Vérifier le résultat

Enregistrez les deux fichiers, puis consultez la page d’accueil et chacune des routes de détail. Vous devez voir la photo associée à chaque randonnée, tandis que le titre et le lien restent présents. Si un visuel manque, vérifiez d’abord l’orthographe du chemin, la casse du nom de fichier et sa présence dans public/images ; vérifiez ensuite que les champs src, alt, width et height sont transmis à Image.

À retenir

  • Importez le composant avec `import Image from "next/image"`.
  • Pour une image locale, fournissez son chemin public avec `src` et ses dimensions intrinsèques avec `width` et `height`.
  • Rédigez un `alt` descriptif qui correspond au contenu réel du visuel.
  • Utilisez les mêmes informations d’image sur la carte et sur la page de détail.

Dans la prochaine leçon, vous contrôlerez le rendu des images dans leur conteneur, sans modifier les données qui les décrivent.

Envie d'aller plus loin ?

Les cours Enovatic sont gratuits et le resteront. Si vous cherchez un accompagnement encadré, nos formations professionnelles sont animées par les mêmes formateurs.