L’invasion du html
mutant
- Slides en ligne
- ffoodd.fr/devquest.2025/
Niveau 0
L’inspecteur
C’est notre héros du jour : invoquez-le avec F12.
L’inspecteur développe un site web, et tout se passe pour le mieux.
Mais au moment de faire un audit d’accessibilité, le DOM est sens dessus dessous et des scripts tiers font n’importe quoi !
Ni une, ni deux : l’inspecteur dégaine ses outils, il faut corriger le tir !
Niveau 0
Les outils
L’inspecteur n’a pas de flingue, il a une API !
Pour réparer le DOM, nous allons nous servir d’un MutationObserver
.
Quelques règles :
- Il faut l’instancier.
- Il faut lui donner une cible.
- Il lui faut une fonction de rappel.
- Il faut le débrancher, à un moment.
Et maintenant, en avant !
const observer = new MutationObserver();
observer.observe(
document.querySelector('#cible'),
callback
);
observer.disconnect();
Niveau 1
Le zombie
Entrons dans le vif du sujet : les changements d’attribut
Avez-vous déjà eu besoin de déclencher quelque chose en JavaScript lorsqu’un élément change d’attribut ?
Songez à tous ces attributs qui peuvent être importants :
hidden
, aria-label
, aria-invalid
…
Niveau 1
Le zombie
Niveau 2
Le super-vilain
Il n’y a pas que des gentils dans la vie.
Cas d’usage : les changements textuels
Avez-vous déjà eu besoin de déclencher quelque chose en JavaScript lorsque le contenu textuel d’un élement change ?
Imaginez un peu : un bouton dont l’intitulé change, mais pas d’état ni de classe auxquels s’accrocher ? Ou mieux, vous faites vos slides en HTML, avec une vue présentateur que vous voulez synchroniser sur votre pagination.
Niveau 2
Le super-vilain
Niveau 3
L’alien
Ils sont parmi nous !
Cas d’usage : les changements de descendance directe
Un contenu injecté inopinément — au hasard, lors d’un scroll infini, un script tiers qui injecte tout seul son DOM… — c’est irritant !
Ou encore : une iframe
dont vous devriez ajuster la hauteur en fonction de son contenu…
Ceci n’est pas inspiré de faits réels, évidemment !
Niveau 3
L’alien
Niveau 4
Le fantôme
Vous n’avez pas entendu un truc ?
Cas d’usage : un attribut précis change pour une valeur spécifique
Imaginez un framework qui indique l’état invalide d’un champ de formulaire
avec une classe, mais sans aria-invalid
? Vous savez comment patcher ça,
maintenant.
Toute ressemblance avec des frameworks serait purement fortuite.
Niveau 4
Le fantôme
Niveau 5
Le sorcier
Il faut se méfier des types encapuchonnés
avec un grand bâton.
Cas d’usage : les changements de descendance profonde
Le saviez-vous ? Un Web Component ne peut pas émettre un événement en disparaissant… Donc si vous voulez déclencher quelque chose, vous saurez comment faire !
Toute ressemblance avec des frameworks serait purement fortuite.
Niveau 5
Le sorcier
Niveau 6
Le vampire
Il faut aussi se méfier des types avec un sourire qui déborde.
Cas d’usage : les valeurs disparues
Vous avez connu l’époque des classes .open
et .show
pour afficher ou masquer un élément — et aucun autre changement dans le DOM ?
Ou un script tiers qui fait des trucs sans émettre d’événements ?
Bien entendu, ce sujet est une pure fiction.
Niveau 6
Le vampire
Niveau 7
Le vieillissement
Vous ne l’aviez pas vu venir, hein ?
Cas d’usage : les caractères disparus
Un composant de création de mot de passe qui enlève la description des contraintes franchies…
Vous n’avez jamais vu ça ?
Niveau 7
Le vieillissement
Niveau 8
Le boss final
C’est le moment de sauver des vies.
La fonction de rappel dispose aussi de pouvoirs.
Jusqu’à présent, j’ai savamment supprimé l’élément mutant : mais comment faire si on veut trier, filtrer… bref, tenir compte du contexte ?
Niveau 8
Le boss final
Niveau 8
Les solutions
Le bazooka
document.querySelectorAll('mu-tant:not([type=""])')
.forEach(mutant => mutant.remove());
Le précautionneux
if (mutation.target.nodeName === 'MU-TANT' && mutation.target.type !== '') {
mutation.target.remove();
} else if (mutation.target.closest('mu-tant') !== undefined) {
mutation.target.closest('mu-tant').remove();
}
Malgré toutes les options, on peut avoir du mal à trier les mutations.
Fort à propos, le type MutationRecord
dispose de tout un tas de propriétés bien utiles.
Niveau bonus
Mais encore ?
Les MutationObserver
ne sont pas seuls !
-
Les
IntersectionObserver
permettent de surveiller les collisions visuelles entre éléments ; -
Les
ResizeObserver
permettent de surveiller les changements de dimensions d’un élément ; -
Les
PerformanceObserver
permettent de surveiller différents indicateurs de performance et de les consigner dans les logs.
Générique de fin
Merci
Découvrez le jeu réalisé pour le dernier devFest Nantes !
Crédits
- Typographie de titraille : Luckiest Guy par Astigmatic ;
- Typographie de labeur : Zilla Slab par Mozilla ;
- Typographie monospace : FontWithASyntaxHighlighter par Heikki Lotvonen ;
- Typographie pour les émojis : Twemoji COLR par Mozilla.
- Moteur de présentation inspiré de "CSS scroll-snap slide deck that supports live coding" de Stephanie Eckles sur Smashing Magazine.