Comment faire un quiz en HTML et JavaScript ?
Publié le
Un quiz interactif est un excellent exercice pour pratiquer HTML, CSS et JavaScript. Dans ce tutoriel, nous allons construire pas à pas un quiz à choix multiples : l'utilisateur sélectionne une réponse par question, clique sur « Valider » et voit immédiatement les bonnes et mauvaises réponses surlignées, ainsi que son score. Il peut ensuite tout réinitialiser pour recommencer.
Partie 1 : Structure HTML
1.1 Le squelette de la page et le conteneur principal
On commence par une page HTML standard. Tout le quiz sera regroupé dans une
div.quiz-container centrée, qui contiendra
l'introduction, les questions, les boutons d'action et la zone de résultat.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Quiz simple</title>
</head>
<body>
<div class="quiz-container">
<!-- tout le quiz ira ici -->
</div>
</body>
</html>
1.2 La section d'introduction
On ajoute une section .introduction avec un titre
h1 et un court paragraphe explicatif.
<section class="introduction">
<h1>Quiz de démo</h1>
<p>
Choisis une réponse par question puis clique sur « Valider ».
Les bonnes et mauvaises réponses seront surlignées.
</p>
</section>
1.3 Structure d'une question
Chaque question est un article.question-block avec un
attribut data-question-id unique. À l'intérieur :
-
Une
div.question-textpour le texte de la question. - Une
div.options-containerpour les réponses.
Chaque option est un label.option-label (rend toute la
ligne cliquable) contenant :
-
Une
div.option-contentqui aligne les éléments. - Un
span.option-letter(A., B., C…). -
Un
input type="radio"avec le mêmenamepour toutes les options d'une question, et l'attributdata-correct="true"sur la bonne réponse. -
Un
span.option-textpour le texte de la réponse.
<section class="articles-container">
<!-- Question 1 -->
<article class="question-block" data-question-id="q1">
<div class="question-text">
1. Quelle balise HTML est utilisée pour créer un lien hypertexte ?
</div>
<div class="options-container">
<label class="option-label">
<div class="option-content">
<span class="option-letter">A.</span>
<input type="radio" name="q1" value="a" />
<span class="option-text"><link></span>
</div>
</label>
<label class="option-label">
<div class="option-content">
<span class="option-letter">B.</span>
<input type="radio" name="q1" value="b" data-correct="true" />
<span class="option-text"><a></span>
</div>
</label>
<label class="option-label">
<div class="option-content">
<span class="option-letter">C.</span>
<input type="radio" name="q1" value="c" />
<span class="option-text"><href></span>
</div>
</label>
</div>
</article>
<!-- Question 2 : même structure, name="q2", data-correct sur la bonne réponse -->
<article class="question-block" data-question-id="q2">
<div class="question-text">
2. Quel type d'input HTML permet de créer un bouton radio ?
</div>
<div class="options-container">
<label class="option-label">
<div class="option-content">
<span class="option-letter">A.</span>
<input type="radio" name="q2" value="a" />
<span class="option-text">input type="checkbox"</span>
</div>
</label>
<label class="option-label">
<div class="option-content">
<span class="option-letter">B.</span>
<input type="radio" name="q2" value="b" data-correct="true" />
<span class="option-text">input type="radio"</span>
</div>
</label>
<label class="option-label">
<div class="option-content">
<span class="option-letter">C.</span>
<input type="radio" name="q2" value="c" />
<span class="option-text">input type="button"</span>
</div>
</label>
</div>
</article>
</section>
Pour ajouter une troisième question, il suffit de dupliquer un
article.question-block, de changer
data-question-id en
q3, de mettre
name="q3" sur les radios, et de placer
data-correct="true" sur la bonne réponse.
1.4 Les boutons d'action et la zone de résultat
En dehors du conteneur de questions, on ajoute la barre d'actions et un bloc de résultat vide au départ.
<div class="quiz-actions">
<button id="reset-quiz" class="secondary">Réinitialiser</button>
<button id="validate-quiz">Valider</button>
</div>
<div id="quiz-result"></div>
Partie 2 : CSS
Le CSS ci-dessous couvre uniquement ce qui est nécessaire au bon fonctionnement visuel du quiz : mise en page des questions, alignement des options, et coloration des états correct / incorrect. Tu peux l'enrichir à ta guise.
/* --- Conteneur global --- */
.quiz-container {
max-width: 900px;
margin: 0 auto;
padding: 0 16px;
}
/* --- Bloc question --- */
.question-block {
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0,0,0,.05);
padding: 16px 12px;
margin-bottom: 24px;
}
/* --- Texte de la question --- */
.question-text {
font-weight: 600;
color: #2c3e50;
border-bottom: 1px solid #e3e9f5;
padding-bottom: 8px;
margin-bottom: 14px;
}
/* --- Liste d'options --- */
.options-container {
display: flex;
flex-direction: column;
gap: 8px;
}
/* --- Ligne d'option cliquable --- */
.option-label {
display: flex;
background: #f5f7fa;
border: 1px solid transparent;
border-radius: 8px;
padding: 8px 10px;
cursor: pointer;
transition: background-color .25s, border-color .25s;
}
.option-content {
display: flex;
align-items: center;
width: 100%;
}
.option-letter {
font-weight: bold;
min-width: 22px;
margin-right: 10px;
color: #555;
}
.option-label input[type="radio"] {
margin-right: 10px;
transform: scale(1.1);
cursor: pointer;
flex-shrink: 0;
}
.option-text {
flex: 1;
color: #333;
overflow-wrap: break-word;
}
/* --- États après correction --- */
.option-label.selected-correct {
background-color: #e6ffed;
border-color: #28a745;
}
.option-label.selected-incorrect {
background-color: #ffe6e6;
border-color: #dc3545;
}
/* --- Zone de résultat global --- */
#quiz-result {
display: none; /* caché par défaut */
margin: 20px auto;
padding: 16px;
border-radius: 8px;
background: #f0f4f8;
font-weight: 600;
text-align: center;
box-shadow: 0 2px 8px rgba(0,0,0,.1);
}
/* --- Boutons --- */
.quiz-actions {
display: flex;
justify-content: space-between;
gap: 12px;
margin-bottom: 16px;
}
.quiz-actions button {
padding: 10px 18px;
border-radius: 6px;
border: none;
background-color: #0069d9;
color: #fff;
font-weight: 600;
cursor: pointer;
}
.quiz-actions button.secondary {
background-color: #6c757d;
}
/* --- Responsive mobile --- */
@media (max-width: 480px) {
.quiz-actions {
flex-direction: column;
}
.quiz-actions button {
width: 100%;
}
}
Partie 3 : JavaScript
3.1 Récupérer les éléments du DOM
On commence par cibler les éléments dont on aura besoin tout au long du script, et on crée une fonction utilitaire pour récupérer tous les blocs de questions.
const validateButton = document.getElementById('validate-quiz');
const resetButton = document.getElementById('reset-quiz');
const resultBox = document.getElementById('quiz-result');
function getQuestionBlocks() {
return document.querySelectorAll('.question-block');
}
3.2 Vérifier que toutes les questions ont une réponse
Avant de corriger le quiz, on s'assure que chaque bloc contient au moins un radio coché.
Si ce n'est pas le cas, on affiche un message d'erreur et on arrête l'exécution avec
return.
function allQuestionsAnswered() {
for (const block of getQuestionBlocks()) {
const checked = block.querySelector('input[type="radio"]:checked');
if (!checked) return false;
}
return true;
}
validateButton.addEventListener('click', () => {
if (!allQuestionsAnswered()) {
resultBox.style.display = 'block';
resultBox.textContent = 'Tu dois répondre à toutes les questions avant de valider.';
return; // on arrête ici
}
// … suite de la correction
});
3.3 Calculer le score et colorier les réponses
Pour chaque question, on retire d'abord les classes d'état précédentes, puis on récupère
la réponse cochée. Si elle porte l'attribut
data-correct, c'est une bonne réponse : on ajoute
selected-correct et on incrémente le score. Sinon on
ajoute selected-incorrect sur le choix de
l'utilisateur, et selected-correct sur la vraie bonne
réponse.
// (dans le callback du bouton Valider, après le garde allQuestionsAnswered)
const questionBlocks = getQuestionBlocks();
let total = questionBlocks.length;
let score = 0;
questionBlocks.forEach(block => {
// 1. Nettoyer les classes d'état précédentes
block.querySelectorAll('.option-label').forEach(label => {
label.classList.remove('selected-correct', 'selected-incorrect');
});
// 2. Récupérer la réponse sélectionnée
const selectedInput = block.querySelector('input[type="radio"]:checked');
const label = selectedInput.closest('.option-label');
const isCorrect = selectedInput.hasAttribute('data-correct');
// 3. Appliquer les classes et calculer le score
if (isCorrect) {
score++;
label.classList.add('selected-correct');
} else {
label.classList.add('selected-incorrect');
// Afficher aussi la bonne réponse
const correctInput = block.querySelector('input[data-correct]');
if (correctInput) {
correctInput.closest('.option-label').classList.add('selected-correct');
}
}
});
// 4. Afficher le résultat
resultBox.style.display = 'block';
resultBox.textContent = `Tu as ${score} bonne(s) réponse(s) sur ${total}.`;
3.4 Bloquer les radios après validation
Une fois la correction affichée, on désactive tous les boutons radio pour empêcher l'utilisateur de modifier ses réponses.
function setRadiosDisabled(disabled) {
document.querySelectorAll('input[type="radio"]').forEach(radio => {
radio.disabled = disabled;
});
}
// Appel à la fin du traitement de validation :
setRadiosDisabled(true);
3.5 Réinitialiser le quiz
Le bouton « Réinitialiser » décoche tous les radios, les réactive, supprime les classes d'état et masque la zone de résultat.
function clearSelections() {
document.querySelectorAll('input[type="radio"]').forEach(radio => {
radio.checked = false;
radio.disabled = false;
});
document.querySelectorAll('.option-label').forEach(label => {
label.classList.remove('selected-correct', 'selected-incorrect');
});
resultBox.style.display = 'none';
resultBox.textContent = '';
}
resetButton.addEventListener('click', () => {
clearSelections();
});
3.6 Script complet
Voici le script JavaScript dans son intégralité, tel qu'il doit être placé juste avant
la balise </body>.
const validateButton = document.getElementById('validate-quiz');
const resetButton = document.getElementById('reset-quiz');
const resultBox = document.getElementById('quiz-result');
function getQuestionBlocks() {
return document.querySelectorAll('.question-block');
}
function allQuestionsAnswered() {
for (const block of getQuestionBlocks()) {
if (!block.querySelector('input[type="radio"]:checked')) return false;
}
return true;
}
function setRadiosDisabled(disabled) {
document.querySelectorAll('input[type="radio"]')
.forEach(r => r.disabled = disabled);
}
function clearSelections() {
document.querySelectorAll('input[type="radio"]').forEach(r => {
r.checked = false; r.disabled = false;
});
document.querySelectorAll('.option-label').forEach(l =>
l.classList.remove('selected-correct', 'selected-incorrect')
);
resultBox.style.display = 'none';
resultBox.textContent = '';
}
validateButton.addEventListener('click', () => {
if (!allQuestionsAnswered()) {
resultBox.style.display = 'block';
resultBox.textContent = 'Tu dois répondre à toutes les questions avant de valider.';
return;
}
const questionBlocks = getQuestionBlocks();
let score = 0;
questionBlocks.forEach(block => {
block.querySelectorAll('.option-label').forEach(l =>
l.classList.remove('selected-correct', 'selected-incorrect')
);
const selected = block.querySelector('input[type="radio"]:checked');
const label = selected.closest('.option-label');
const isCorrect = selected.hasAttribute('data-correct');
if (isCorrect) {
score++;
label.classList.add('selected-correct');
} else {
label.classList.add('selected-incorrect');
const correct = block.querySelector('input[data-correct]');
if (correct) correct.closest('.option-label').classList.add('selected-correct');
}
});
resultBox.style.display = 'block';
resultBox.textContent = `Tu as ${score} bonne(s) réponse(s) sur ${questionBlocks.length}.`;
setRadiosDisabled(true);
});
resetButton.addEventListener('click', clearSelections);
Quiz interactif
Voici le quiz en action. Choisis une réponse par question, puis clique sur « Valider » pour voir ta correction et ton score.
Quiz de démo
Choisis une réponse par question puis clique sur « Valider ».