Intégration web angularforall.com

- HTML Dialog natif : modale sans JavaScript

Html5 Dialog Modale Native Accessibilité
HTML Dialog natif : modale sans JavaScript

Créez des modales natives en HTML5 avec la balise <dialog> : syntaxe, attributs, pseudo-éléments ::backdrop, accessibilité et exemple complet. Sans dépendre de Bootstrap ou JavaScript.

Introduction : le natif avant Bootstrap

Pendant des années, les développeurs web ont dû choisir entre :

  • jQuery UI ou Bootstrap Modal : puissants mais lourds
  • Modales custom : flexibles mais chronophages (accessibilité, animations, gestion du clavier)

Aujourd'hui, la balise <dialog> (introduite en HTML5 et maintenant supportée par tous les navigateurs modernes) offre une troisième voie : native, légère et accessible par défaut.

Avantages de <dialog> natif

  • Zéro dépendance : pas de Bootstrap, jQuery, ou libraries tiers
  • Accessible par défaut : focus management, ARIA roles automatiques, lecteurs d'écran
  • Légère : quelques bytes de HTML/CSS, pas de JavaScript obligatoire
  • Performante : optimisée nativement par les navigateurs
  • API simple : show(), showModal(), close()
  • Stylisable : ::backdrop, transitions CSS, propriétés custom

Bien sûr, Bootstrap modales restent utiles pour les projets complexes avec designs élaborés. Mais pour 90% des cas d'usage simples à intermédiaires, <dialog> est la solution idéale.

Syntaxe et structure basique

La balise <dialog> minimale

Voici la structure la plus simple :

<!-- Définir la dialog -->
<dialog id="monDialog">
    <h2>Titre de ma modale</h2>
    <p>Contenu de la modale.</p>
    <button onclick="document.getElementById('monDialog').close()">
        Fermer
    </button>
</dialog>

<!-- Bouton pour ouvrir -->
<button onclick="document.getElementById('monDialog').showModal()">
    Ouvrir la modale
</button>

C'est tout ce qu'il faut ! Aucun CSS spécial, aucune dépendance. La modale s'affiche au centre de l'écran avec un overlay semi-transparent.

Contenu complexe

Les dialogs peuvent contenir n'importe quel HTML :

<dialog id="confirmDialog">
    <!-- Header -->
    <header>
        <h2>Confirmez votre action</h2>
        <!-- Bouton native X -->
        <button aria-label="Fermer" onclick="this.closest('dialog').close()">
            ✕
        </button>
    </header>

    <!-- Main content -->
    <main>
        <p>Êtes-vous sûr de vouloir supprimer cet élément ?</p>
        <p><strong>Cette action est irréversible.</strong></p>
    </main>

    <!-- Footer avec actions -->
    <footer class="d-flex gap-2 justify-content-end">
        <button onclick="this.closest('dialog').close('cancel')"
                class="btn btn-secondary">
            Annuler
        </button>
        <button onclick="this.closest('dialog').close('confirm')"
                class="btn btn-danger">
            Supprimer
        </button>
    </footer>
</dialog>

Notez comment on utilise les méthodes : showModal() pour ouvrir et close() pour fermer, avec un argument optionnel pour retourner une valeur.

Attributs : open et comportement modal

L'attribut open

Cet attribut booléen indique si la dialog est affichée :

<!-- Dialog visible au chargement (non-modale) -->
<dialog open>
    <p>Je suis visible par défaut en mode non-modal.</p>
</dialog>

Attention : open seul place la dialog en mode non-modal (pas de backdrop bloquant). La page reste interactive derrière.

Modale vs non-modale

Il y a deux façons d'afficher une dialog :

// 1) Mode NON-MODAL (non-bloquant)
dialog.show();
// → L'utilisateur peut cliquer derrière
// → Pas de backdrop grisé
// → Parfait pour des info-bulles, sidebars

// 2) Mode MODAL (bloquant)
dialog.showModal();
// → L'utilisateur ne peut pas cliquer derrière
// → Backdrop semi-transparent apparaît
// → L'interaction est limitée à la dialog

Utilisez showModal() pour les confirmations, formulaires importants. Utilisez show() pour les notifications non-critiques.

Pseudo-éléments ::backdrop et styling

Personnaliser l'overlay

Le pseudo-élément ::backdrop permet de styliser l'overlay sombre derrière la modale :

/* Style par défaut du backdrop */
dialog::backdrop {
    background-color: rgba(0, 0, 0, 0.5);
}

/* Personnalisé : gradient, blur, etc. */
dialog::backdrop {
    background: linear-gradient(135deg, rgba(0,0,0,0.3), rgba(0,0,0,0.8));
    backdrop-filter: blur(2px); /* Pour les navigateurs supportant backdrop-filter */
}

Styliser la dialog elle-même

/* Style de base */
dialog {
    border: none;
    border-radius: 12px;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
    max-width: 600px;
    padding: 2rem;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

/* Mode sombre optionnel */
@media (prefers-color-scheme: dark) {
    dialog {
        background-color: #1e1e1e;
        color: #e0e0e0;
    }
    dialog::backdrop {
        background-color: rgba(0, 0, 0, 0.8);
    }
}

/* Animations d'entrée/sortie */
dialog {
    animation: slideIn 0.3s ease-out;
}

@keyframes slideIn {
    from {
        opacity: 0;
        transform: translateY(-30px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

Bootstrap n'est pas nécessaire : utilisez flexbox, grid, et les utilitaires CSS natifs pour organiser le contenu.

Interactions JavaScript : show() et showModal()

Exemple complet avec gestion d'événements

// Récupérer la référence
const dialog = document.getElementById('myDialog');
const openBtn = document.getElementById('openBtn');
const closeBtn = document.getElementById('closeBtn');

// Ouvrir en mode modal
openBtn.addEventListener('click', () => {
    dialog.showModal();
});

// Fermer
closeBtn.addEventListener('click', () => {
    dialog.close();
});

// Écouter la fermeture (important pour actions post-modale)
dialog.addEventListener('close', () => {
    console.log('Dialog fermée. Valeur retournée :', dialog.returnValue);
    if (dialog.returnValue === 'confirm') {
        // Utilisateur a cliqué "Confirmer"
    }
});

// Fermer en cliquant en dehors (backdrop)
dialog.addEventListener('click', (e) => {
    if (e.target === dialog) {
        dialog.close('cancel');
    }
});

Gestion du clavier

Les dialogs modales capturent automatiquement la touche Escape. Mais vous pouvez personnaliser :

dialog.addEventListener('cancel', (e) => {
    // Utilisateur a appuyé sur Escape
    console.log('Dialog annulée par Escape');
    // Optionnel : e.preventDefault() pour empêcher la fermeture
});

// Gestion personnalisée d'autres touches
dialog.addEventListener('keydown', (e) => {
    if (e.key === 'Enter' && e.ctrlKey) {
        // Ctrl+Entrée = soumettre
        dialog.close('confirm');
    }
});

Formulaires dans <dialog>

Modale de formulaire complet

<dialog id="contactDialog">
    <form method="dialog">
        <!-- method="dialog" = ferme la dialog à la soumission -->

        <h2>Nous contacter</h2>

        <div class="mb-3">
            <label for="name" class="form-label">Nom</label>
            <input type="text" id="name" class="form-control" required>
        </div>

        <div class="mb-3">
            <label for="email" class="form-label">Email</label>
            <input type="email" id="email" class="form-control" required>
        </div>

        <div class="mb-3">
            <label for="message" class="form-label">Message</label>
            <textarea id="message" class="form-control" rows="4" required></textarea>
        </div>

        <div class="d-flex gap-2 justify-content-end">
            <button type="button" formmethod="dialog" value="cancel" class="btn btn-secondary">
                Annuler
            </button>
            <button type="submit" value="confirm" class="btn btn-primary">
                Envoyer
            </button>
        </div>
    </form>
</dialog>

<script>
const contactDialog = document.getElementById('contactDialog');
const contactForm = contactDialog.querySelector('form');

// Récupérer le formulaire au submit
contactDialog.addEventListener('close', () => {
    if (contactDialog.returnValue === 'confirm') {
        const name = document.getElementById('name').value;
        const email = document.getElementById('email').value;
        const message = document.getElementById('message').value;

        console.log('Envoi du formulaire :', { name, email, message });
        // Appel API, etc.

        // Réinitialiser après envoi
        contactForm.reset();
    }
});
</script>

Astuce : Utilisez method="dialog" sur le formulaire pour fermer automatiquement la dialog à la soumission.

Accessibilité et bonnes pratiques

Points clés d'accessibilité

Les dialogs natives gèrent beaucoup d'accessibilité automatiquement, mais quelques points à vérifier :

<dialog id="a11yDialog" role="dialog" aria-labelledby="dialogTitle">
    <h2 id="dialogTitle">Titre accessible</h2>
    <p id="dialogDesc">Description utile du dialogue.</p>

    <!-- aria-describedby lie la description au titre -->
    <!-- Les lecteurs d'écran annoncent l'intention de la dialog -->

    <form>
        <!-- Tous les contrôles doivent être accessibles au clavier -->
        <label for="firstName">Prénom <abbr title="requis">*</abbr></label>
        <input id="firstName" required>

        <button type="submit">Envoyer</button>
        <button type="button" onclick="this.closest('dialog').close()">
            <span class="visually-hidden">Fermer la dialog</span>
            ✕
        </button>
    </form>
</dialog>

Bonnes pratiques

  • Focus trap : La modale capture le focus ; l'utilisateur ne peut naviguer que dans la modale
  • Escape key : Autorisez la fermeture avec la touche Escape
  • Labels explicites : Utilisez aria-labelledby pour lier le titre
  • Contraste : Vérifiez le contraste entre texte et fond (WCAG 4.5:1 minimum)
  • Responsive : Adaptez la taille sur mobile avec media queries
/* Responsive : plein écran sur mobile */
@media (max-width: 768px) {
    dialog {
        max-width: 90vw;
        max-height: 90vh;
        margin: auto;
    }
}

Conclusion et alternatives

Résumé : La balise <dialog> native offre une solution légère, accessible et performante pour les modales. C'est la première option à considérer dans la plupart des projets.

Quand utiliser <dialog> :

  • Formulaires de contact, login, confirmations
  • Modales d'alerte ou d'information
  • Projets sans dépendances externes
  • Applications mobiles légères

Quand utiliser Bootstrap ou autres libraries :

  • Designs complexes avec multiples animations
  • Intégration avec des composants Bootstrap existants
  • Support IE11 (nécessite polyfill pour <dialog>)
  • Carousel, accordions, ou transitions avancées dans la modale

Pour débuter, testez <dialog> sur vos prochains projets. Vous découvrirez qu'elle résout 90% des besoins en modales, avec zero dépendances.

Ressources utiles

Partager