Astro : composants et layouts
Un composant .astro
Section intitulée « Un composant .astro »src/components/Carte.astro :
---interface Props { titre: string; url: string; tags?: string[];}const { titre, url, tags = [] } = Astro.props;---
<article class="carte"> <h2> <a href={url}>{titre}</a> </h2> {tags.length > 0 && ( <ul> {tags.map((tag) => ( <li>{tag}</li> ))} </ul> )} <slot /></article>
<style> .carte { border: 1px solid #ccc; padding: 1rem; border-radius: 8px; }</style>Utilisation :
---import Carte from '../components/Carte.astro';---
<Carte titre="MD Editor" url="https://exemple.com" tags={['markdown', 'éditeur']}> <p>Contenu passé dans le slot.</p></Carte>| Élément | Rôle |
|---|---|
Frontmatter --- |
Code exécuté à la compilation : imports, données, props |
| Gabarit | HTML avec expressions {…} |
Astro.props |
Propriétés reçues |
<slot /> |
Contenu enfant |
<style> |
Styles limités au composant |
---const articles = [ { id: 1, titre: 'A' }, { id: 2, titre: 'B' },];const connecte = true;---
<ul> {articles.map((a) => ( <li key={a.id}>{a.titre}</li> ))}</ul>{connecte ? <p>Bonjour</p> : <p>Connexion</p>}<p class:list={['base', { actif: connecte }]}>Classes conditionnelles</p><div set:html={'<strong>HTML brut</strong>'} /><Fragment> <span>sans élément parent</span></Fragment>Slots nommés
Section intitulée « Slots nommés »<div class="modale"> <header> <slot name="titre">Titre par défaut</slot> </header> <slot /> <footer> <slot name="pied" /> </footer></div><Modale> <h2 slot="titre">Confirmer</h2> <p>Corps de la modale.</p> <button slot="pied">OK</button></Modale><style>dans un composant est limité à ce composant (Astro ajoute un attribut de portée).<style is:global>ou:global(sélecteur)pour sortir de cette portée.- Une feuille globale s’importe dans le layout :
import '../styles/global.css';. - Variables CSS depuis le frontmatter :
<style define:vars={{ couleur }}>.
---const couleur = 'rebeccapurple';---
<p class="titre">Texte</p><style define:vars={{ couleur }}> .titre { color: var(--couleur); }</style>Pour Tailwind : voir Tailwind : installation.
Scripts dans le navigateur
Section intitulée « Scripts dans le navigateur »Une balise <script> d’un composant .astro s’exécute dans le navigateur, est regroupée, dédupliquée et peut importer des modules :
<button id="theme">Changer de thème</button>
<script> document.getElementById('theme')?.addEventListener('click', () => { const racine = document.documentElement; racine.dataset.theme = racine.dataset.theme === 'dark' ? 'light' : 'dark'; });</script><script is:inline> conserve le script tel quel, sans traitement (utile pour un petit script exécuté avant l’affichage, comme l’initialisation du thème).
Un layout est un composant qui enveloppe les pages.
src/layouts/Base.astro :
---import '../styles/global.css';
interface Props { titre: string; description?: string;}const { titre, description = 'Description par défaut' } = Astro.props;const canonique = new URL(Astro.url.pathname, Astro.site);---
<!doctype html><html lang="fr"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>{titre}</title> <meta name="description" content={description} /> <link rel="canonical" href={canonique} /> <slot name="head" /> </head> <body> <header> <a href="/">Accueil</a> </header> <main> <slot /> </main> <footer>© {new Date().getFullYear()}</footer> </body></html>---import Base from '../layouts/Base.astro';---
<Base titre="À propos" description="Page de présentation"> <h1>À propos</h1></Base>Pour des fichiers Markdown, indiquer le layout dans le frontmatter (layout: ../layouts/Article.astro) ou, avec les collections, l’appeler depuis la page qui affiche le contenu (voir Contenu et collections).
---import { Image } from 'astro:assets';import photo from '../assets/photo.jpg';---
<Image src={photo} alt="Description de la photo" width={800} />Image produit des formats optimisés (WebP, AVIF), les dimensions et le chargement différé. Les images dans public/ ne sont pas optimisées. Toujours renseigner alt.
Icônes et polices
Section intitulée « Icônes et polices »Pour une police auto-hébergée, placer les fichiers dans public/fonts/ ou utiliser un paquet @fontsource/... et l’importer dans le layout. Précharger la police principale :
<link rel="preload" href="/fonts/police.woff2" as="font" type="font/woff2" crossorigin/>Dépannage
Section intitulée « Dépannage »| Symptôme | Piste |
|---|---|
| Un style de composant ne s’applique pas à un élément enfant | Portée locale : :global() ou classe passée en prop |
Astro.props vide |
Propriété non transmise ; vérifier la casse |
document is not defined |
Code navigateur dans le frontmatter : le déplacer dans un <script> |
Image : Could not find requested image |
Chemin d’import incorrect ; fichier absent de src/ |
Balise <script> exécutée une seule fois |
Comportement attendu (dédupliquée) |
Contenu de <slot /> absent |
Élément enfant non passé, ou nom de slot incorrect |
Ubuntu 24.04 et 26.04 : différences à connaître
Section intitulée « Ubuntu 24.04 et 26.04 : différences à connaître »Aucune.