Todas as atividades
Quiz e Avaliação

Conjunto de Questões

Agrupa múltiplas questões de tipos diferentes em uma única atividade. Permite avaliação abrangente de um tema com variação de formatos.

Conhecimento e compreensão quiz conjunto múltiplos formatos question-set

Experimente

Responda as questões a seguir sobre design instrucional:

1 / 3

Qual sigla representa as etapas Análise, Design, Desenvolvimento, Implementação e Avaliação?

Código-fonte

PHP

Dados de exemplo

Duas perguntas de tipos diferentes, fixas no próprio arquivo.

1 <?php
2 $perguntas = [
3 [
4 'tipo' => 'multipla-escolha',
5 'pergunta' => 'Qual sigla representa as etapas Análise, Design, Desenvolvimento, Implementação e Avaliação?',
6 'opcoes' => [
7 ['texto' => 'SAM', 'correta' => false],
8 ['texto' => 'ADDIE', 'correta' => true],
9 ['texto' => 'SCORM', 'correta' => false],
10 ],
11 ],
12 [
13 'tipo' => 'verdadeiro-falso',
14 'afirmacao' => 'A avaliação formativa ocorre somente ao final do curso.',
15 'correta' => false,
16 ],
17 ];
18 $total = count($perguntas);
19 ?>

Estrutura da atividade

Contador no topo e as perguntas empilhadas, todas menos a primeira nascem ocultas.

1 <div class="questao" data-tipo="conjunto-questoes" data-total="<?= $total ?>">
2
3 <div class="questao-cabecalho">
4 <p>Responda as perguntas a seguir:</p>
5 <span><span class="questao-atual">1</span> / <?= $total ?></span>
6 </div>
7
8 <?php foreach ($perguntas as $qi => $p): ?>
9 <div class="questao-item<?= $qi > 0 ? ' oculto' : '' ?>" data-qi="<?= $qi ?>">
10
11 <?php if ($p['tipo'] === 'multipla-escolha'): ?>
12 <div class="sub-questao" data-qi="<?= $qi ?>">
13 <p class="questao-pergunta"><?= htmlspecialchars($p['pergunta']) ?></p>
14 <div class="questao-opcoes">
15 <?php foreach ($p['opcoes'] as $opcao): ?>
16 <button type="button" class="sub-opcao" data-correta="<?= $opcao['correta'] ? 'true' : 'false' ?>" data-selecionada="false" data-estado="padrao">
17 <?= htmlspecialchars($opcao['texto']) ?>
18 </button>
19 <?php endforeach; ?>
20 </div>
21 <button type="button" class="sub-verificar">Verificar resposta</button>
22 <p class="sub-feedback" hidden></p>
23 </div>
24
25 <?php elseif ($p['tipo'] === 'verdadeiro-falso'): ?>
26 <div class="sub-questao" data-qi="<?= $qi ?>">
27 <p class="questao-pergunta"><?= htmlspecialchars($p['afirmacao']) ?></p>
28 <div class="questao-opcoes">
29 <button type="button" class="sub-opcao" data-correta="<?= $p['correta'] ? 'true' : 'false' ?>" data-selecionada="false" data-estado="padrao">Verdadeiro</button>
30 <button type="button" class="sub-opcao" data-correta="<?= !$p['correta'] ? 'true' : 'false' ?>" data-selecionada="false" data-estado="padrao">Falso</button>
31 </div>
32 <button type="button" class="sub-verificar">Verificar resposta</button>
33 <p class="sub-feedback" hidden></p>
34 </div>
35 <?php endif; ?>
36
37 </div>
38 <?php endforeach; ?>

Botão único de avançar

Fora do laço de perguntas — sempre a última coisa do card, some de novo a cada clique.

1 <button type="button" class="questao-proximo" hidden>Próxima →</button>
2
3 <div class="questao-resultado" hidden>
4 <p class="questao-placar"><span class="questao-acertos">0</span> / <?= $total ?> respostas corretas</p>
5 <button type="button" class="questao-reiniciar">Recomeçar atividade</button>
6 </div>
7
8 </div>
CSS

Card e cabeçalho

Contêiner da atividade e a linha com instrução + contador "1 / N".

1 .questao[data-tipo="conjunto-questoes"] {
2 max-width: 420px;
3 padding: 24px;
4 border: 1px solid #e2e8f0;
5 border-radius: 16px;
6 background: #fff;
7 font-family: sans-serif;
8 }
9
10 .questao-cabecalho {
11 display: flex;
12 align-items: center;
13 justify-content: space-between;
14 margin-bottom: 20px;
15 font-size: 14px;
16 color: #64748b;
17 }
18
19 .questao-cabecalho span:last-child {
20 padding: 4px 10px;
21 border-radius: 999px;
22 background: #f1f5f9;
23 font-size: 12px;
24 }

Pergunta ativa

.oculto tira a pergunta da tela — só uma fica visível por vez.

1 .questao-item.oculto {
2 display: none;
3 }
4
5 .questao-pergunta {
6 margin: 0 0 16px;
7 font-weight: 600;
8 color: #0f172a;
9 }

Alternativas

Cor por data-estado, não por classe fixa — o JS só troca o atributo.

1 .questao-opcoes {
2 display: flex;
3 flex-direction: column;
4 gap: 8px;
5 margin-bottom: 16px;
6 }
7
8 .sub-opcao {
9 padding: 12px 16px;
10 border: 1px solid #cbd5e1;
11 border-radius: 10px;
12 background: #f8fafc;
13 text-align: left;
14 font: inherit;
15 cursor: pointer;
16 }
17
18 .sub-opcao:disabled { cursor: not-allowed; }
19
20 .sub-opcao[data-estado="selecionada"] {
21 border-color: #6366f1;
22 background: rgba(99, 102, 241, .1);
23 color: #4338ca;
24 }
25
26 .sub-opcao[data-estado="correta"] {
27 border-color: #16a34a;
28 background: rgba(22, 163, 74, .1);
29 color: #15803d;
30 }
31
32 .sub-opcao[data-estado="errada"] {
33 border-color: #dc2626;
34 background: rgba(220, 38, 38, .1);
35 color: #b91c1c;
36 }

Verificar e feedback

O texto de acerto/erro nasce oculto; o botão de verificar some depois de usado.

1 .sub-verificar,
2 .questao-proximo,
3 .questao-reiniciar {
4 width: 100%;
5 padding: 12px 16px;
6 border: none;
7 border-radius: 10px;
8 background: #4f46e5;
9 color: #fff;
10 font: inherit;
11 font-weight: 600;
12 cursor: pointer;
13 }
14
15 .sub-feedback {
16 margin-top: 12px;
17 padding: 10px 14px;
18 border-radius: 10px;
19 font-size: 14px;
20 }
21
22 .sub-feedback.acerto { background: #dcfce7; color: #14532d; }
23 .sub-feedback.erro { background: #fee2e2; color: #7f1d1d; }
24 .sub-feedback.aviso { background: #fef3c7; color: #78350f; }

Resultado final

Placar e botão de recomeçar, escondidos até a última pergunta ser verificada.

1 .questao-resultado {
2 padding: 16px;
3 border-radius: 10px;
4 background: #eef2ff;
5 text-align: center;
6 }
7
8 .questao-placar {
9 margin: 0 0 12px;
10 font-size: 22px;
11 font-weight: 700;
12 color: #4338ca;
13 }
14
15 .questao-reiniciar {
16 background: #e5e7eb;
17 color: #1f2937;
18 }
JavaScript

Encontrar os elementos da atividade

Contador, placar e o botão único de avançar — compartilhados por todas as perguntas.

1 document.addEventListener('DOMContentLoaded', function () {
2 document.querySelectorAll('.questao[data-tipo="conjunto-questoes"]').forEach(function (questao) {
3 var total = parseInt(questao.dataset.total, 10);
4 var acertos = 0;
5 var atualEl = questao.querySelector('.questao-atual');
6 var proximo = questao.querySelector('.questao-proximo');
7 var resultado = questao.querySelector('.questao-resultado');
8 var acertosEl = questao.querySelector('.questao-acertos');

Selecionar e verificar cada pergunta

Um bloco de correção por pergunta — cada uma guarda se já foi respondida.

1 questao.querySelectorAll('.sub-questao').forEach(function (subQuestao) {
2 var qi = parseInt(subQuestao.dataset.qi, 10);
3 var opcoes = subQuestao.querySelectorAll('.sub-opcao');
4 var verificar = subQuestao.querySelector('.sub-verificar');
5 var fb = subQuestao.querySelector('.sub-feedback');
6
7 // Seleção tipo rádio: marca a escolhida, devolve as demais ao padrão.
8 // Nada é corrigido ainda — só "Verificar" revela acerto ou erro.
9 opcoes.forEach(function (opcao) {
10 opcao.addEventListener('click', function () {
11 if (subQuestao.dataset.respondida === 'true') return;
12 opcoes.forEach(function (o) {
13 var sel = o === opcao;
14 o.dataset.selecionada = sel ? 'true' : 'false';
15 o.dataset.estado = sel ? 'selecionada' : 'padrao';
16 });
17 fb.hidden = true;
18 });
19 });
20
21 verificar.addEventListener('click', function () {
22 if (subQuestao.dataset.respondida === 'true') return;
23
24 var escolhida = Array.prototype.filter.call(opcoes, function (o) {
25 return o.dataset.selecionada === 'true';
26 })[0];
27 if (!escolhida) {
28 fb.className = 'sub-feedback aviso';
29 fb.textContent = 'Escolha uma alternativa antes de verificar.';
30 fb.hidden = false;
31 return;
32 }
33
34 subQuestao.dataset.respondida = 'true';
35 var correta = escolhida.dataset.correta === 'true';
36 if (correta) acertos++;
37
38 opcoes.forEach(function (o) {
39 o.disabled = true;
40 if (o.dataset.correta === 'true') o.dataset.estado = 'correta';
41 else if (o === escolhida) o.dataset.estado = 'errada';
42 else o.dataset.estado = 'padrao';
43 });
44
45 fb.className = 'sub-feedback ' + (correta ? 'acerto' : 'erro');
46 fb.textContent = correta ? 'Correto!' : 'Não foi dessa vez.';
47 fb.hidden = false;
48
49 verificar.hidden = true;

Revelar o botão de avançar

Rotula pra esta pergunta ("Próxima →" ou "Ver resultado" na última) e grava o qi nele.

1 proximo.textContent = qi < total - 1 ? 'Próxima →' : 'Ver resultado';
2 proximo.dataset.qi = qi;
3 proximo.hidden = false;
4 });
5 });

Avançar pra próxima pergunta ou pro resultado

Um único botão pra atividade inteira — o clique já o esconde de novo.

1 proximo.addEventListener('click', function () {
2 var qi = parseInt(proximo.dataset.qi, 10);
3 proximo.hidden = true;
4 questao.querySelector('.questao-item[data-qi="' + qi + '"]').classList.add('oculto');
5
6 if (qi === total - 1) {
7 resultado.hidden = false;
8 acertosEl.textContent = acertos;
9 } else {
10 questao.querySelector('.questao-item[data-qi="' + (qi + 1) + '"]').classList.remove('oculto');
11 atualEl.textContent = qi + 2;
12 }
13 });

Reiniciar

Zera o placar, volta pra primeira pergunta e limpa seleção, cores e feedback de todas.

1 questao.querySelector('.questao-reiniciar').addEventListener('click', function () {
2 acertos = 0;
3 atualEl.textContent = 1;
4 resultado.hidden = true;
5
6 questao.querySelectorAll('.questao-item').forEach(function (item, i) {
7 item.classList.toggle('oculto', i !== 0);
8 });
9 questao.querySelectorAll('.sub-questao').forEach(function (subQuestao) {
10 delete subQuestao.dataset.respondida;
11 subQuestao.querySelector('.sub-verificar').hidden = false;
12 subQuestao.querySelector('.sub-feedback').hidden = true;
13 });
14 questao.querySelectorAll('.sub-opcao').forEach(function (o) {
15 o.disabled = false;
16 o.dataset.selecionada = 'false';
17 o.dataset.estado = 'padrao';
18 });
19 });