Retour au blogArticle

Ionic v8 / CSS

Ionic CSS : personnaliser un composant sans casser le Shadow DOM

Variables CSS, Shadow Parts, slots et classes locales : les bons réflexes pour styliser une interface Ionic Angular sans empiler des surcharges fragiles.

Interface Ionic personnalisée proprement avec variables CSS, slots et Shadow Parts sans casser le Shadow DOM

Tu modifies le CSS d’un composant Ionic, tu relances ton application, et rien ne change. Ce n’est pas forcément une erreur de ta part. Dans Ionic, certains composants utilisent le Shadow DOM, des variables CSS, des slots et des Shadow Parts.

Si tu essaies de styliser Ionic comme une page HTML classique, tu risques vite d’ajouter du CSS global fragile, des sélecteurs trop agressifs ou des contournements qui casseront au prochain changement de composant.

Variables CSS Ionic

Le premier point d’entrée pour modifier couleurs, bordures, espacements et états visuels sans forcer l’intérieur du composant.

Shadow Parts

Les parties internes que Ionic expose volontairement avec ::part() quand une variable ne suffit pas.

Slots Ionic

Le bon moyen de placer icônes, badges, boutons ou actions dans un composant sans reconstruire sa structure à la main.

Classes locales

Une classe ciblée dans le SCSS du composant garde le style lisible et limite les effets de bord sur le reste de l’application.

Faire auditer une interface Ionic difficile à styliser

Pourquoi ton CSS ne s’applique pas toujours dans Ionic

Dans une application Ionic Angular, les composants comme ion-button, ion-item, ion-card, ion-toolbar ou ion-modal ne sont pas toujours structurés comme de simples balises HTML.

Certains composants encapsulent une partie de leur rendu interne. C’est ce qui explique pourquoi un sélecteur CSS classique ne touche pas toujours l’élément que tu veux modifier.

Exemple trompeur

ion-button {
  background: red;
}

Le bouton ne devient pas forcément rouge, parce que la couleur visible est souvent pilotée par une variable CSS Ionic ou une partie interne exposée par le composant.

Le piège du CSS global trop agressif

Quand le CSS ne fonctionne pas, la mauvaise réaction consiste souvent à forcer avec des sélecteurs globaux, des règles très larges ou des !important partout.

À éviter

ion-button * {
  background: red !important;
}

Pourquoi c’est fragile

Ce type de règle peut casser d’autres boutons, les états actifs, les modes iOS/MD, le contraste, l’accessibilité ou le comportement responsive. Dans Ionic v8, il vaut mieux utiliser les points d’entrée prévus par le composant.

Les variables CSS Ionic

Les variables CSS sont souvent la première solution à tester. Ionic expose de nombreuses variables pour personnaliser les couleurs, les bordures, les espacements, les arrière-plans ou les états visuels des composants.

SCSS local

.primary-action {
  --background: #1f6feb;
  --background-hover: #1a5fd0;
  --color: #ffffff;
  --border-radius: 14px;
  --padding-top: 14px;
  --padding-bottom: 14px;
}

Template Ionic Angular

<ion-button class="primary-action" expand="block">
  Continuer
</ion-button>

Ici, on ne force pas l’intérieur du bouton. On utilise les variables prévues par Ionic, ce qui reste plus stable et plus compatible avec Ionic v8.

Quand utiliser ::part()

Certains composants Ionic exposent des Shadow Parts. Ce sont des parties internes que Ionic autorise explicitement à styliser quand les variables CSS ne couvrent pas le besoin.

Template

<ion-item class="customer-item" lines="none">
  <ion-label>
    <h2>Commande à préparer</h2>
    <p>Retrait prévu aujourd'hui</p>
  </ion-label>
</ion-item>

SCSS local

.customer-item {
  --background: #ffffff;
  --border-radius: 16px;
  --padding-start: 16px;
  --inner-padding-end: 16px;
  margin-bottom: 12px;
}

.customer-item::part(native) {
  box-shadow: 0 8px 24px rgba(15, 23, 42, 0.08);
}

La règle ::part(native) cible une partie exposée par ion-item. C’est très différent d’un sélecteur agressif qui essaie de traverser toute la structure interne.

Quand utiliser les slots Ionic

Les slots permettent de placer du contenu au bon endroit dans un composant Ionic. Dans un ion-item, slot="start" et slot="end" positionnent naturellement une icône, un bouton ou un badge.

Template avec slots

<ion-item class="task-item" lines="none">
  <ion-icon name="cube-outline" slot="start" aria-hidden="true"></ion-icon>

  <ion-label>
    <h2>Stock à vérifier</h2>
    <p>3 produits demandent une mise à jour</p>
  </ion-label>

  <ion-badge slot="end" color="warning">3</ion-badge>
</ion-item>

Ici, il n’est pas nécessaire de recréer une ligne complète avec des div. Ionic sait déjà organiser ce type de disposition et conserver un comportement mobile cohérent.

Trois méthodes propres pour personnaliser Ionic v8 avec variables CSS, Shadow Parts et slots

Classes locales plutôt que surcharge globale

Si un style concerne uniquement une carte, un bouton ou une liste dans une page précise, il doit rester local autant que possible.

Composant Ionic conservé

<ion-card class="dashboard-card">
  <ion-card-header>
    <ion-card-title>Demandes à traiter</ion-card-title>
    <ion-card-subtitle>Suivi du jour</ion-card-subtitle>
  </ion-card-header>

  <ion-card-content>
    8 demandes nécessitent une action.
  </ion-card-content>
</ion-card>

SCSS du composant

.dashboard-card {
  --background: #ffffff;
  border-radius: 20px;
  box-shadow: 0 10px 30px rgba(15, 23, 42, 0.08);
}

.dashboard-card ion-card-title {
  font-size: 1.1rem;
  font-weight: 700;
}

Bon périmètre

Une classe comme dashboard-card dit clairement où le style s’applique et évite de toucher toutes les cartes de l’application.

Maintenance plus simple

Le style reste lisible dans le fichier SCSS du composant, sans transformer global.scss en zone de corrections permanentes.

Exemple complet : liste Ionic personnalisée proprement

Voici un exemple d’interface Ionic v8 avec une liste de demandes. Les composants Ionic sont conservés, les slots structurent la ligne et les syntaxes Angular modernes restent en place.

Template Angular moderne

<ion-content class="ion-padding requests-page">
  @if (requests.length > 0) {
    <ion-list class="requests-list">
      @for (request of requests; track request.id) {
        <ion-item class="request-item" lines="none">
          <ion-icon name="document-text-outline" slot="start" aria-hidden="true"></ion-icon>

          <ion-label>
            <h2>{{ request.title }}</h2>
            <p>{{ request.description }}</p>
          </ion-label>

          <ion-badge slot="end" [color]="request.urgent ? 'danger' : 'medium'">
            {{ request.status }}
          </ion-badge>
        </ion-item>
      }
    </ion-list>
  } @else {
    <ion-card class="empty-card">
      <ion-card-header>
        <ion-card-title>Aucune demande</ion-card-title>
      </ion-card-header>

      <ion-card-content>
        Les nouvelles demandes apparaîtront ici.
      </ion-card-content>
    </ion-card>
  }
</ion-content>

SCSS local

.requests-page {
  --background: #f6f8fb;
}

.requests-list {
  background: transparent;
}

.request-item {
  --background: #ffffff;
  --border-radius: 18px;
  --padding-start: 16px;
  --inner-padding-end: 12px;
  --min-height: 76px;
  margin-bottom: 12px;
}

.request-item::part(native) {
  box-shadow: 0 8px 24px rgba(15, 23, 42, 0.07);
}

Composants Ionic natifs

ion-list, ion-item, ion-label et ion-badge gardent la structure mobile attendue.

Templates Angular 20

Les conditions utilisent @if et la boucle utilise @for, sans revenir à une écriture Angular ancienne.

Style encapsulé

Le SCSS reste attaché à la page. Les tokens globaux restent réservés au thème et aux vrais choix transverses.

Responsive Ionic

Pour des cartes ou blocs responsives, on s’appuie sur ion-grid, ion-row et ion-col.

Ce qu’il faut éviter dans un projet Ionic v8

Certaines pratiques peuvent fonctionner temporairement, mais elles rendent le projet plus fragile à chaque évolution de composant, de thème ou de parcours mobile.

Erreurs fréquentes de personnalisation CSS dans Ionic avec sélecteurs globaux, surcharge et contournements fragiles

Forcer l’encapsulation Angular

::ng-deep n’est pas une base saine pour styliser Ionic. Il vaut mieux chercher une variable, une Shadow Part ou une classe locale.

Multiplier les !important

Si une règle doit tout forcer, c’est souvent que le style n’est pas appliqué au bon niveau du composant.

Tout remplacer par des div

Les composants Ionic apportent structure, accessibilité, modes iOS/MD et cohérence tactile. Les supprimer doit rester l’exception.

Styliser globalement tous les items

Une règle globale sur ion-item touchera aussi menus, modales, formulaires et listes internes.

Alternative ciblée

.settings-item {
  --border-radius: 16px;
  margin-bottom: 12px;
}

Où placer le CSS dans un projet Ionic Angular

Le choix dépend de la portée du style. Le bon réflexe consiste à rapprocher le CSS du composant quand le style n’a pas vocation à s’appliquer partout.

SCSS du composant

À privilégier pour une page, une liste, une carte, un tableau de bord ou une modale particulière.

variables.scss

À réserver aux couleurs principales, typographies, modes, tokens et choix de thème réellement transverses.

global.scss

À utiliser avec prudence pour quelques utilitaires globaux, pas pour corriger chaque composant Ionic au cas par cas.

Checklist : personnalisation propre ou bricolage fragile ?

Avant de forcer un style Ionic, pose ces questions :

  • Existe-t-il une variable CSS Ionic pour ce composant ?
  • Le composant expose-t-il un Shadow Part utilisable avec ::part() ?
  • Un slot permet-il de placer correctement l’élément ?
  • Le style doit-il être local à une page ou global à toute l’application ?
  • Le composant Ionic natif peut-il être conservé ?
  • Le responsive peut-il être géré avec ion-grid, ion-row et ion-col ?
  • Le contraste et l’accessibilité restent-ils corrects ?
  • Le style fonctionne-t-il en mode iOS et Material Design ?

Conclusion

Personnaliser Ionic ne consiste pas à forcer le Shadow DOM avec du CSS agressif. Avec Ionic v8, la bonne approche est plus propre : utiliser les variables CSS, les Shadow Parts, les slots et les composants Ionic prévus pour le mobile.

C’est ce qui permet de créer une interface personnalisée sans casser la cohérence de l’application, sans fragiliser les mises à jour et sans transformer le projet en accumulation de correctifs CSS.

Faire corriger une interface Ionic difficile à maintenir