Aller au contenu

HTML et styles personnalisés

On peut insérer du HTML arbitraire dans une page, et le styler de quatre façons, de la plus ponctuelle à la plus réutilisable :

Niveau Technique Portée Idéal pour
1 Attribut style="…" Un élément Un réglage isolé
2 Bloc <style> dans la page La page entière Un rendu spécial sur une seule page
3 Classe dans src/styles/custom.css Tout le site Un style réutilisé sur plusieurs pages
4 Composant .astro Chaque utilisation du composant Un bloc complexe et paramétrable

Tous les exemples ci-dessous sont rendus en direct : cette page est elle-même un fichier .mdx.

En MDX, le HTML est interprété comme du JSX, plus strict que le HTML classique. Une erreur arrête le build, avec un message indiquant la ligne et la colonne fautives.

Règle ❌ Échoue ✅ Fonctionne
Toute balise doit être fermée <br>, <img src="…"> <br />, <img src="…" />
Pas de commentaires HTML <!-- note --> {/* note */}
{ et } sont du JavaScript : le CSS d’un <style> doit être entouré de {`…`} <style>.a { color: red }</style> <style>{`.a { color: red }`}</style>
Du Markdown dans une balise doit être entouré de lignes vides — voir les exemples ci-dessous

Avec Astro, on garde les attributs HTML habituels : class (et non className comme en React), for, et style sous forme de texte.

<div style="padding: 1rem; border: 2px dashed var(--sl-color-orange); border-radius: 0.5rem;">
Un bloc avec une **bordure orange en pointillés**. Les lignes vides autour de ce texte
permettent d'y écrire du Markdown.
</div>

Un bloc avec une bordure orange en pointillés. Les lignes vides autour de ce texte permettent d’y écrire du Markdown.

Simple et immédiat, mais à éviter dès que le même style se répète : il faudrait le recopier partout.

On déclare des classes CSS dans la page, puis on les utilise sur autant d’éléments que nécessaire :

<style>{`
.demo-cartes { display: grid; grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); gap: 1rem; }
.demo-carte {
padding: 1.25rem; border-radius: 1rem; text-align: center;
color: white; font-weight: 700;
box-shadow: 0 8px 20px -8px rgba(0, 0, 0, 0.5);
transition: transform 0.2s;
}
.demo-carte:hover { transform: translateY(-4px) rotate(-1deg); }
.demo-carte span { display: block; font-size: 2.5rem; }
.demo-carte.un { background: linear-gradient(135deg, #6d28d9, #db2777); }
.demo-carte.deux { background: linear-gradient(135deg, #0369a1, #0d9488); }
.demo-carte.trois { background: linear-gradient(135deg, #c2410c, #ca8a04); }
`}</style>
<div class="demo-cartes not-content">
<div class="demo-carte un"><span>1</span>Écrire</div>
<div class="demo-carte deux"><span>2</span>Compiler</div>
<div class="demo-carte trois"><span>3</span>Publier</div>
</div>
1Écrire
2Compiler
3Publier

Starlight met automatiquement en forme le contenu des pages : espacement entre les blocs, style des titres, des listes, des liens… Pour un bloc au rendu très particulier, ces règles peuvent gêner, par exemple en ajoutant une marge au-dessus de chaque carte de la grille.

Ajouter la classe not-content à un élément le soustrait à cette mise en forme, lui et tout son contenu. C’est ce qui est fait sur la grille ci-dessus.

Les couleurs écrites en dur (#fff, black…) ne s’adaptent pas au thème choisi par le lecteur. Pour qu’un bloc reste lisible dans les deux, on utilise les variables CSS de Starlight, dont la valeur change avec le thème :

Variable Usage
--sl-color-text Couleur du texte courant
--sl-color-bg Fond de la page
--sl-color-accent, -low, -high Couleur principale du site : normale, atténuée (fonds), renforcée (textes)
--sl-color-gray-1 … --sl-color-gray-7 Nuances de gris, du plus contrasté au plus discret
--sl-color-green, -orange, -red, -blue, -purple (+ -low, -high) Couleurs sémantiques
--sl-text-sm, --sl-text-lg, --sl-text-2xl… Tailles de police

Couleurs en dur
Fond blanc fixe : détonne en thème sombre.

Variables Starlight
S’adapte au thème : essayez le sélecteur en haut de page.

Pour réutiliser un style sur plusieurs pages, on le déclare une fois dans une feuille de style chargée sur tout le site. Elle est déclarée dans astro.config.mjs avec l’option customCss: ['./src/styles/custom.css']. Voici son contenu actuel :

src/styles/custom.css
/*
* Styles personnalisés, chargés sur toutes les pages (option `customCss` de Starlight).
* Les variables --sl-color-* suivent automatiquement le thème clair / sombre.
*/
/* Section mise en avant, réutilisable dans n'importe quelle page via class="section-vedette" */
.section-vedette {
padding: 1.5rem 2rem;
border-radius: 1rem;
background: linear-gradient(135deg, var(--sl-color-accent-low), transparent 70%);
border-left: 6px solid var(--sl-color-accent);
}
.section-vedette h3 {
margin-top: 0;
color: var(--sl-color-accent-high);
}
/* Images du contenu (captures d'écran notamment) : cadre discret pour les détacher du fond */
.sl-markdown-content img {
border: 1px solid var(--sl-color-hairline);
border-radius: 0.5rem;
}

Il suffit ensuite d’utiliser la classe, y compris dans un fichier .md :

<div class="section-vedette">
### Section mise en avant
Ce style est défini une seule fois dans `custom.css`, et utilisable sur toutes les pages.
</div>

Ce style est défini une seule fois dans custom.css, et utilisable sur toutes les pages.

Quand un bloc a une structure (titre, contenu, variantes…), on en fait un composant. Un fichier .astro réunit le HTML, des paramètres (props) et un style automatiquement isolé : Astro réécrit les sélecteurs pour qu’ils ne s’appliquent qu’à ce composant, sans risque de déborder sur le reste de la page.

src/components/Encadre.astro
---
/*
* Encadré personnalisé, utilisable en MDX :
* import Encadre from '../../../components/Encadre.astro';
* <Encadre titre="Titre" couleur="purple">Contenu en **Markdown**</Encadre>
*/
interface Props {
titre: string;
couleur?: 'accent' | 'green' | 'orange' | 'red' | 'blue' | 'purple';
}
const { titre, couleur = 'accent' } = Astro.props;
---
<section class="encadre" style={`--couleur: var(--sl-color-${couleur}); --fond: var(--sl-color-${couleur}-low);`}>
<p class="titre">{titre}</p>
<div class="contenu"><slot /></div>
</section>
<style>
/* Style « scopé » : Astro le limite automatiquement à ce composant */
.encadre {
position: relative;
padding: 2.25rem 1.5rem 1.25rem;
margin-top: 2rem;
border: 2px solid var(--couleur);
border-radius: 0.75rem;
background: var(--fond);
}
.titre {
position: absolute;
top: -0.9rem;
left: 1rem;
margin: 0;
padding: 0.1rem 0.75rem;
border-radius: 999px;
background: var(--couleur);
color: var(--sl-color-black);
font-weight: 700;
font-size: var(--sl-text-sm);
}
.contenu > :global(:first-child) {
margin-top: 0;
}
</style>

Utilisation dans une page .mdx :

import Encadre from '../../../components/Encadre.astro';
<Encadre titre="Bon à savoir">
Le contenu d'un composant peut contenir du **Markdown**.
</Encadre>
<Encadre titre="Attention" couleur="orange">
Le paramètre `couleur` change l'apparence.
</Encadre>

Bon à savoir

Le contenu d’un composant peut contenir du Markdown.

Attention

Le paramètre couleur change l’apparence.

Nouveau

Et ainsi de suite, avec une seule définition à maintenir.

Technique Fonctionne en .md Confort dans le CMS
style="…" ✅ Bloc HTML brut, peu lisible pour un rédacteur
<style> dans la page ✅ Idem, et risque de casser la page
Classe de custom.css ✅ Acceptable : un simple <div class="…">
Composant .astro ❌ (MDX seulement) Possible via des composants d’éditeur personnalisés, à configurer