Déboguer avec l'inspecteur du navigateur
Maîtriser les DevTools pour diagnostiquer un bug en quelques minutes au lieu de plusieurs heures. Breakpoints, Network, Console, Performance : ce qui sert vraiment au quotidien.
À la fin du cours, tu sais
- Ouvrir et configurer les DevTools selon ton workflow
- Inspecter et modifier le DOM et le CSS en live
- Utiliser la Console au-delà de console.log
- Poser des breakpoints (classiques, conditionnels, logpoints)
- Diagnostiquer une requête réseau en lisant son détail
- Auditer la perf et l'accessibilité d'une page
Prérequis
- Connaître les bases HTML, CSS et JavaScript
- Avoir Chrome, Edge ou Firefox installé
Étape 1 sur 10 : Ouvrir et apprivoiser les DevTools
Chapitre 1
Ouvrir et apprivoiser les DevTools
Premier réflexe : savoir ouvrir, ancrer et configurer ton inspecteur pour qu'il colle à ta façon de bosser.
Les DevTools (les « outils de développement » intégrés à ton navigateur) sont le cockpit du développement front. C'est là que tu inspectes le DOM, que tu ajustes le CSS, que tu lis les erreurs, que tu poses des points d'arrêt et que tu observes le réseau. La différence entre un·e dev qui met dix minutes à comprendre un bug et un·e autre qui met deux heures ne tient pas au talent : elle tient à la maîtrise de ces outils. Avant d'apprendre à les utiliser, il faut savoir les apprivoiser — les ouvrir, les placer, les piloter au clavier.
Quelques raccourcis suffisent à gagner en fluidité, détaillés ci-dessous, mais retiens surtout deux gestes. Le premier, inspecter directement un élément de la page (Cmd/Ctrl+Shift+C) pour atterrir pile sur son code. Le second, et le plus rentable de tous, le menu de commandes (Cmd/Ctrl+Shift+P) : tu y tapes le début d'une action (« screenshot », « coverage », « disable JavaScript ») et tu la déclenches sans jamais chercher dans les menus. C'est l'équivalent de la palette de commandes de VS Code, appliqué au navigateur.
Prends aussi une minute pour ancrer les DevTools là où ça t'arrange : à droite de l'écran, en bas, ou dans une fenêtre séparée si tu as un second moniteur. Et rassure-toi si tu changes de navigateur : Firefox propose les mêmes raccourcis et les mêmes panneaux principaux (Inspecteur, Console, Réseau, Débogueur, Stockage). Les captures de ce cours s'appuient sur Chrome, mais tout ce que tu apprends se transpose directement. Savoir déboguer, c'est une compétence, pas une marque de navigateur.
Les raccourcis à mémoriser
- F12 ou
Cmd+Option+I(Mac) /Ctrl+Shift+I(Windows/Linux) : ouvre les DevTools Cmd+Shift+C/Ctrl+Shift+C: pour inspecter un élément précis directementCmd+Shift+M/Ctrl+Shift+M: bascule en mode responsive- Échap : ouvre/ferme le tiroir Console depuis n'importe quel panneau
Le Command Menu
Le raccourci le plus rentable des DevTools : Cmd+Shift+P / Ctrl+Shift+P. Tu tapes screenshot, disable JavaScript, coverage... Tu pilotes tout au clavier sans chercher dans les menus.
Ancrage des DevTools
Firefox aussi
Mêmes raccourcis, mêmes panneaux principaux (Inspecteur, Console, Réseau, Débogueur, Stockage). Si tu sais déboguer dans Chrome, tu sais déboguer dans Firefox.
Chapitre 2
Panneau Elements : inspecter et modifier en live
Le terrain de jeu HTML/CSS. Tu peux toucher à tout sans toucher au code source.
Le panneau Elements est ton terrain de jeu HTML/CSS. Tu y vois le DOM — la structure réelle de la page telle que le navigateur l'a construite — et tu peux tout modifier en direct : déplacer un nœud, éditer un attribut, changer une couleur, ajouter une règle. Un point important à comprendre dès le départ : ce que tu vois ici, c'est le DOM vivant, pas ton fichier source. Sur une app rendue par un framework (React, Vue), le markup affiché peut différer de ton code, et surtout tes modifications sont temporaires : elles disparaissent au rechargement. C'est un bac à sable pour expérimenter sans risque, pas un éditeur.
C'est justement ce caractère jetable qui rend Elements si utile pour déboguer un affichage. Tu veux savoir si un padding réglerait ton problème d'alignement ? Ajoute-le dans le panneau Styles, observe, ajuste, puis reporte la valeur qui marche dans ton vrai code. Tu peux désactiver une propriété d'une case à cocher pour isoler son effet, et surtout forcer un état (:hover, :focus, :active) : le rendu se verrouille, ce qui te laisse fouiller l'arbre et lire les styles de survol sans avoir à maintenir la souris en place — un geste impossible autrement.
Deux fonctionnalités méritent d'être connues tôt. Le débogueur Flexbox / Grid : quand un élément est un conteneur, un petit badge flex ou grid apparaît à côté ; clique dessus et les lignes de la grille se dessinent en couleur sur la page — indispensable pour comprendre un layout qui « saute ». Et le raccourci $0 : après avoir sélectionné un élément dans Elements, tape $0 dans la Console pour obtenir une référence directe à cet élément ($0.classList.add('debug') pour le manipuler en JavaScript). Ce pont entre Elements et Console est l'un des gestes les plus rentables de tout l'inspecteur.
Manipuler le DOM
- Double-clic sur un attribut pour l'éditer
- Clic droit sur un élément → Edit as HTML pour modifier le markup
- Faire glisser un élément dans l'arbre pour le déplacer
- Touche
Deletepour supprimer un nœud (test rapide)
Le panneau Styles
- Ajouter une règle CSS en cliquant dans la zone (autocomplétion incluse)
- Désactiver/activer une propriété en décochant la case
- Forcer un état :
:hover,:focus,:focus-visible,:active - Color picker avec ratio de contraste WCAG AA/AAA intégré
Flexbox et Grid debugger
Quand un élément est un conteneur Flex ou Grid, un badge flex ou grid apparaît à côté dans le DOM. Clique dessus : les lignes de la grille s'affichent en couleur sur la page. Indispensable pour comprendre un layout cassé.
Le raccourci $0
$0. Tu as une référence directe à l'élément sélectionné. $0.classList.add('debug') pour le manipuler en JS, par exemple.Vrai ou faux ?
Quand tu forces l'état :hover d'un élément depuis le panneau Styles, tu peux inspecter ses styles de survol sans garder la souris dessus.
Chapitre 3
Console : bien plus que console.log
La Console reste l'outil le plus rentable, à condition d'aller au-delà de console.log.
La Console est l'outil que tout le monde utilise et que presque personne n'exploite à fond. La plupart des dev s'arrêtent à console.log(variable), alors qu'elle offre une boîte à outils bien plus riche pour comprendre ce qui se passe. Apprendre trois ou quatre méthodes de plus, c'est transformer un affichage brut en une véritable lecture de l'exécution.
Les plus utiles, illustrées ci-dessous : console.table() affiche un tableau d'objets en colonnes triables, infiniment plus lisible qu'une liste de logs ; console.group() regroupe des logs liés pour ne pas noyer la Console ; console.time() / console.timeEnd() mesurent une durée ; console.assert() ne s'affiche que si une condition est fausse ; et console.trace() montre le chemin d'appels qui a mené jusqu'à un point précis, sans lever d'erreur. Il existe aussi les live expressions (l'icône œil) : une expression réévaluée en continu, par exemple document.activeElement pour suivre le focus pendant que tu navigues au clavier.
Un mot sur les limites, car la Console n'est pas la réponse à tout. Le console.log t'oblige à modifier ton code, à deviner à l'avance ce que tu veux afficher, et à recharger à chaque essai — un cycle lent quand tu cherches à l'aveugle. Un point d'arrêt, que tu verras au chapitre suivant, te laisse au contraire inspecter tout l'état du programme au moment exact où il s'arrête, sans rien éditer. Les deux sont complémentaires. Enfin, pense à retirer tes logs avant la production : oubliés dans le code livré, ils ralentissent un peu et peuvent fuiter des informations sensibles ; une règle de lint comme no-console t'en protège automatiquement.
// Tableau d'objets affiché en colonnes triables
console.table(users);
// Grouper des logs liés
console.group('Traitement commande');
console.log('Étape 1 : validation');
console.log('Étape 2 : paiement');
console.groupEnd();
// Mesurer une durée
console.time('chargement');
// ... du code ...
console.timeEnd('chargement'); // "chargement: 234ms"
// Log conditionnel sans casser le flux
console.assert(user.age >= 18, 'User trop jeune', user);
// Stack trace à un endroit précis (sans throw)
console.trace('passé par ici');Live expressions
L'icône œil en haut de la Console : tu y mets une expression et tu la vois en temps réel. Exemple : document.activeElement pour suivre le focus pendant que tu navigues au clavier.
console.log oublié en prod
console.log oubliés dans le code de prod ralentissent (un peu) et fuitent (parfois) des infos sensibles. Configure ton lint pour les bloquer hors mode dev (eslint no-console).Vrai ou faux ?
Le console.log est l'outil de debug le plus puissant : pas besoin de breakpoints.
Chapitre 4
Sources : breakpoints et pas-à-pas
Le vrai débogage commence ici. Pose des breakpoints, navigue dans la pile, inspecte les variables.
C'est dans le panneau Sources que le débogage prend une autre dimension. Un point d'arrêt (breakpoint) met l'exécution en pause à une ligne précise et te laisse regarder l'intérieur du programme à cet instant exact : la valeur de chaque variable, le chemin d'appels qui t'a mené là, l'état complet. Fini de deviner en semant des console.log : tu observes directement. C'est la compétence qui sépare le débogage par tâtonnement du débogage méthodique.
Il existe plusieurs sortes de points d'arrêt, et savoir choisir le bon fait gagner un temps fou. Le classique (clic sur le numéro de ligne) s'arrête à chaque passage. Le conditionnel ne s'arrête que si une expression est vraie — précieux dans une boucle pour cibler l'itération i === 42 sans cliquer quarante-deux fois. Le logpoint affiche une valeur à chaque passage sans arrêter ni modifier ton code, et disparaît quand tu fermes l'onglet : le remplaçant idéal du console.log qu'on oublie de retirer. Enfin, « Pause on exceptions » met en pause automatiquement sur toute erreur, et les breakpoints DOM se déclenchent quand un élément est modifié — parfait pour traquer un script tiers qui trafique ta page mystérieusement.
Une fois en pause, tu pilotes l'exécution au pas-à-pas avec quatre touches : F8 reprend, F10 passe à la ligne suivante sans entrer dans les fonctions, F11 entre dans la fonction appelée, Shift+F11 en ressort. Et tu lis l'état dans trois zones complémentaires : Scope (toutes les variables visibles à cet instant), Watch (des expressions que tu choisis de suivre, comme cart.length) et Call Stack (la pile d'appels, cliquable pour remonter d'où vient l'exécution). Le scénario ci-dessous te fait dérouler exactement cette enquête sur un bouton qui ne répond plus.
Poser un breakpoint
- Clic sur le numéro de ligne pour un breakpoint classique
- Clic droit → Add conditional breakpoint : ne s'arrête que si une condition est vraie
- Clic droit → Add logpoint : log une valeur sans modifier le code, sans arrêter
- Breakpoint sur exception : pause automatique sur toute erreur (case Pause on exceptions)
Le logpoint, ami invisible
console.log que tu vas oublier de retirer, utilise un logpoint : tu l'ajoutes dans les DevTools, il log à chaque passage, et il disparaît quand tu fermes l'onglet.Les touches du pas-à-pas
F8: Resume (continuer l'exécution)F10: Step over (passer à la ligne suivante sans entrer dans les fonctions)F11: Step into (entrer dans la fonction appelée)Shift+F11: Step out (sortir de la fonction courante)
Scope, Watch, Call Stack
- Scope : toutes les variables visibles à l'arrêt courant
- Watch : tu y ajoutes des expressions à suivre (
user.email,cart.length) - Call Stack : la pile d'appels qui t'a amené ici, cliquable pour remonter
Breakpoints DOM
Clic droit sur un élément dans Elements → Break on → subtree modifications / attribute modifications / node removal. Le débogueur se déclenche dès que cet élément change. Magique pour traquer un JS tiers qui modifie ton DOM mystérieusement.
🧭 Un bouton ne réagit plus : comment tu diagnostiques ?
Un bouton « Ajouter au panier » ne fait plus rien au clic. Aucun message d'erreur visible. À toi de mener l'enquête avec les DevTools.
Par où commences-tu ?
Chapitre 5
Network : voir passer chaque requête
Pour comprendre ce que ton front envoie et reçoit, et à quel coût.
Une bonne partie des bugs front ne vient pas du front lui-même, mais de son dialogue avec le serveur : une requête qui part avec la mauvaise donnée, une réponse en erreur, un appel trop lent. Le panneau Network rend ce dialogue visible. Chaque ligne est une requête — un appel d'API, une image, une feuille de style — avec sa méthode, son statut, sa taille et son temps. C'est le premier endroit où regarder quand « les données ne s'affichent pas » : tu sauras tout de suite si le problème est côté envoi, côté serveur ou côté affichage.
Pour ne pas te noyer, commence par filtrer : le bouton Fetch/XHR isole les appels d'API, et tu peux affiner avec une syntaxe puissante (status-code:404, method:POST, domain:api.exemple.com). Deux cases valent le réflexe : Preserve log pour garder l'historique quand la page navigue, et Disable cache pour forcer le rechargement réel des ressources. Ensuite, ouvre une requête et lis son détail : Headers (ce qui est envoyé et reçu), Payload (le corps de ta requête — l'endroit où vérifier que tu envoies bien ce que tu crois), Response (le corps de la réponse, souvent du JSON) et Timing (la décomposition du temps passé).
Deux fonctionnalités méritent d'entrer dans ta routine. Le throttling (menu No throttling → Slow 4G) simule une connexion mobile lente de façon reproductible : indispensable pour voir ce que vit vraiment un·e utilisateur·ice loin de ta fibre. Et le Copy as cURL / Copy as fetch (clic droit sur une requête) reconstitue la commande complète — en-têtes, corps, cookies compris — que tu peux rejouer dans un terminal, dans Postman ou dans un test. C'est un gain de temps énorme dès qu'il faut reproduire un bug d'API en dehors du navigateur.
Filtres essentiels
- Boutons en haut : Fetch/XHR (les appels API), JS, CSS, Img, Doc
- Filtre texte avancé :
status-code:404,method:POST,domain:api.example.com - Preserve log coché : garde l'historique même quand tu navigues vers une autre page
- Disable cache coché : utile en dev, à décocher en debug de prod
Détail d'une requête
- Headers : ce qui a été envoyé (request) et reçu (response)
- Payload : le corps de la requête (utile pour vérifier ce qui est envoyé)
- Response : le corps de la réponse (souvent du JSON)
- Timing : décomposition (DNS, TCP, TLS, request, response, download)
- Initiator : qui a déclenché la requête (cliquable pour aller au code source)
Throttling : simuler la lenteur
Menu déroulant No throttling en haut → Slow 4G, Fast 3G, ou un profil custom. Indispensable pour tester ce que voit un·e utilisateur·ice sur une connexion mobile lente.
Copy as cURL ou fetch
Chapitre 6
Application : storage, cookies, service workers
Tout ce qui persiste côté navigateur. Souvent là que les bugs « ça marche en navigation privée mais pas chez moi » se règlent.
Le panneau Application, c'est la mémoire du navigateur : tout ce qui persiste d'une visite à l'autre. C'est là que se règlent les bugs déroutants du type « ça marche en navigation privée mais pas dans mon onglet habituel » — presque toujours une donnée périmée coincée dans un stockage local. Savoir inspecter et vider ces stockages fait partie des réflexes de survie du front.
Plusieurs mécanismes de stockage cohabitent, avec des durées de vie différentes. Le LocalStorage persiste entre les sessions (jusqu'à un fermeture/réouverture du navigateur), le SessionStorage s'efface à la fermeture de l'onglet, l'IndexedDB est une véritable base de données structurée côté client, et le Cache Storage contient les ressources mises en cache par un Service Worker. Depuis ce panneau, tu peux lire, modifier et surtout vider chacun d'eux — le premier geste à tenter quand une app se comporte bizarrement avec une vieille donnée.
Deux zones touchent directement à la sécurité. Les cookies d'abord : vérifie leurs drapeaux critiques — HttpOnly (le cookie est inaccessible en JavaScript, ce qui limite les attaques XSS), Secure (transmis uniquement en HTTPS) et SameSite (qui atténue les attaques CSRF). Un cookie d'authentification sans HttpOnly est un signal d'alarme. Les Service Workers ensuite : ce panneau liste ceux qui sont enregistrés, permet de forcer leur mise à jour, de les désinscrire quand ils servent une version périmée, et même de simuler le mode hors-ligne pour tester le comportement de repli de ton app.
Storage
- LocalStorage : persistant entre sessions, ~10 Mo
- SessionStorage : effacé à la fermeture de l'onglet
- IndexedDB : base de données structurée côté navigateur
- Cache Storage : ressources mises en cache par un Service Worker
Cookies
Vérifier les flags critiques : HttpOnly (inaccessible en JS, mitige le XSS), Secure (HTTPS uniquement), SameSite (Strict/Lax/None, mitige le CSRF). Si tu vois un cookie d'authentification sans HttpOnly, c'est un signal d'alarme.
Service Workers
- Liste des SW enregistrés, leur statut (installed, activated)
- Update on reload : force la mise à jour à chaque reload (utile en dev)
- Unregister : supprime un SW qui pose problème
- Offline : simule la déconnexion (test du fallback)
Chapitre 7
Performance, accessibilité, Lighthouse
Aller au-delà du fonctionnel : ta page va-t-elle vite, est-elle accessible, est-elle scannée par Google ?
Une page peut « marcher » et pourtant être lente, inaccessible ou mal référencée. Les DevTools vont bien au-delà du fonctionnel : ils mesurent la performance perçue, l'accessibilité réelle et la qualité globale. Ces audits ne sont pas des bonus cosmétiques — la vitesse influence le taux de rebond et le référencement, et l'accessibilité conditionne l'usage pour une partie non négligeable de tes visiteur·euses (et, en contexte professionnel, ta conformité légale).
Le panneau Performance enregistre une trace pendant que tu navigues, puis les Insights te donnent les Core Web Vitals : le LCP (temps d'affichage du plus gros élément), l'INP (réactivité aux interactions) et le CLS (stabilité visuelle, ces sauts de mise en page agaçants). Tu repères les long tasks (rectangles rouges) qui bloquent le fil principal, et tu compares un avant/après optimisation d'un simple coup d'œil. Ces trois métriques sont exactement celles que Google utilise pour évaluer l'expérience de ta page.
Côté accessibilité et qualité, deux outils font gagner un temps précieux. L'onglet Accessibility (dans Elements) montre l'arbre tel qu'un lecteur d'écran le perçoit : si le nom accessible d'un bouton est (empty), tu tiens un vrai problème, invisible à l'œil mais bloquant pour une personne aveugle. Et Lighthouse génère en trente secondes un rapport noté sur la performance, l'accessibilité, les bonnes pratiques et le SEO, avec des recommandations concrètes et priorisées. Ajoute l'outil Coverage (via le menu de commandes) pour traquer le code JavaScript et CSS jamais utilisé, et le panneau Issues pour anticiper les avertissements du navigateur avant qu'ils ne deviennent des pannes après une mise à jour.
Panneau Performance
- Bouton Record rouge, navigue dans ta page, Stop
- Panneau Insights : LCP, INP, CLS (les Core Web Vitals)
- Repère les Long tasks (rectangles rouges sur la timeline)
- Compare avant/après une optimisation : visuel immédiat
Accessibility tree
Dans Elements, onglet Accessibility. Tu vois l'arbre tel que perçu par un lecteur d'écran : nom accessible, rôle, états ARIA calculés. Si le nom accessible est (empty) sur un bouton, tu as un problème.
Lighthouse en 1 clic
Onglet Lighthouse. Coche les audits voulus (Performance, Accessibility, Best Practices, SEO, PWA), bouton Analyze page load. En 30 secondes tu as un rapport avec des recos concrètes et priorisées.
Coverage : code mort
Via le Command Menu : Coverage. Tu navigues dans ta page, l'outil te dit quel pourcentage de chaque fichier JS/CSS est réellement utilisé. Excellent pour traquer le code mort à supprimer.
Issues
Pour aller plus loin
- Vue d'ensemble des outils de développement Firefox · MDN (nouvel onglet)
- Inspecter et modifier le CSS dans le panneau Styles · Chrome DevTools (en anglais) (nouvel onglet)
- Mettre en pause son code avec les breakpoints · Chrome DevTools (en anglais) (nouvel onglet)
- Analyser l'activité réseau (panneau Network) · Chrome DevTools (en anglais) (nouvel onglet)
🛠️ Exercice optionnel
Déboguer un formulaire qui envoie la mauvaise donnée
Un formulaire de contact envoie systématiquement un champ email vide à l'API, alors que l'utilisateur·ice a bien saisi son adresse. Le bug est facile à voir, plus subtil à diagnostiquer.
Ta mission
- Ouvre l'onglet Network, filtre sur Fetch/XHR, soumets le formulaire.
- Inspecte la requête POST : regarde le Payload et confirme que
emailest vide. - Bascule dans Sources, pose un breakpoint sur la fonction
handleSubmit. - Re-soumets le formulaire. Le débogueur s'arrête. Observe le panneau Scope : quelle propriété est lue ? Est-ce
formData.emailouformData.mail? - Ajoute un logpoint pour confirmer la valeur de
formDatasans modifier le code. - Corrige le nom de champ, relance, vérifie le Payload à nouveau dans Network.
Tu bloques ? Des indices, à dévoiler quand tu en as besoin.
Indice 1
Indice masqué.
Indice 2
Indice masqué.
Indice 3
Indice masqué.
✅ QCM de fin de cours
Teste tes acquis
10 questions, plusieurs réponses parfois possibles. Coche tout ce qui te semble juste, puis valide pour voir ton score et les explications.
- 1
Quel raccourci ouvre les DevTools sur Mac ?
- 2
À quoi sert
console.table(data)? - 3
À quoi sert un breakpoint conditionnel ?
- 4
Quelle touche fait un step over dans le débogueur ?
- 5
Comment simuler une connexion lente pour tester ton site ?
- 6
Où vérifies-tu si un cookie est
HttpOnly? - 7
À quoi sert le panneau Issues ?
- 8
Que fait
$0dans la Console ? - 9
Quel panneau te permet de mesurer le LCP et l'INP ?
- 10
Comment rejouer une requête API depuis ton terminal sans réécrire toute la commande ?
Tu peux laisser des questions sans réponse, elles compteront comme fausses.
🎓 Attestation
Ton attestation de réussite
Termine le QCM avec au moins 80% de bonnes réponses pour débloquer ton attestation de réussite.
Tu veux ce cours pour ton équipe ?
Je peux adapter et animer ce cours pour tes formateur·ices ou tes apprenant·es, en présentiel ou en distanciel. Parlons-en pendant l'audit gratuit.
Réserver un audit gratuit →