Todas as atividades
Exibição Visual

Carrossel de Imagens

Exibe uma sequência de imagens navegáveis com legendas. O aprendiz avança pelos slides no próprio ritmo, ideal para conteúdo visual como processos, exemplos e antes/depois.

Conhecimento e compreensão carrossel imagens slides carousel

Experimente

Código-fonte

PHP

Dados de exemplo

Cada slide tem imagem, título e descrição. A ordem do array é a ordem de navegação. Quatro a oito slides é a faixa ideal — menos que isso não justifica o formato, mais que isso cansa quem navega um por um.

1 <?php
2 $titulo = 'Metamorfose da Borboleta';
3 $slides = [
4 ['imagem' => 'ovo.jpg', 'titulo' => '1. Ovo', 'descricao' => 'A fêmea deposita o ovo na face inferior de uma folha, escolhida por já ser o alimento da lagarta que vai eclodir dali.'],
5 ['imagem' => 'lagarta.jpg', 'titulo' => '2. Lagarta', 'descricao' => 'Fase de crescimento: a lagarta come continuamente e troca de pele várias vezes conforme o corpo aumenta de tamanho.'],
6 ['imagem' => 'crisalida.jpg', 'titulo' => '3. Crisálida', 'descricao' => 'Dentro do invólucro rígido, o corpo da lagarta se reorganiza quase por completo antes de emergir transformado.'],
7 ['imagem' => 'borboleta.jpg', 'titulo' => '4. Borboleta', 'descricao' => 'O adulto emerge, espera as asas secarem e endurecerem, e só então voa pela primeira vez.'],
8 ];
9 $total = count($slides);
10 ?>

Cabeçalho

Título e indicador de posição ("1/4") ficam juntos, centralizados — dá pra saber onde se está na sequência antes mesmo de olhar o slide.

1 <div class="carrossel">
2 <div class="cabecalho">
3 <p class="titulo"><?= htmlspecialchars($titulo) ?></p>
4 <span class="indicador" data-indicador>1/<?= $total ?></span>
5 </div>

Slides

Todos os slides já existem no HTML desde o carregamento — só o primeiro nasce com a classe "ativo". Trocar de slide é só mover essa classe, nunca recriar ou apagar conteúdo.

1 <div class="slides">
2 <?php foreach ($slides as $i => $slide): ?>
3 <div class="slide<?= $i === 0 ? ' ativo' : '' ?>" data-slide="<?= $i ?>">
4 <img class="imagem" src="<?= htmlspecialchars($slide['imagem']) ?>" alt="<?= htmlspecialchars($slide['titulo']) ?>">
5 <p class="numero-titulo"><?= htmlspecialchars($slide['titulo']) ?></p>
6 <p class="descricao"><?= htmlspecialchars($slide['descricao']) ?></p>
7 </div>
8 <?php endforeach; ?>
9 </div>

Navegação

"Anterior"/"Próximo" desabilitam nas pontas — a navegação não dá a volta do último slide pro primeiro. Os dots não têm essa restrição: pulam direto pra qualquer slide, de qualquer ponto da sequência.

1 <div class="navegacao">
2 <button type="button" class="botao-anterior" disabled>&larr; Anterior</button>
3 <div class="dots">
4 <?php for ($i = 0; $i < $total; $i++): ?>
5 <button type="button" class="dot<?= $i === 0 ? ' ativo' : '' ?>" data-dot="<?= $i ?>"></button>
6 <?php endfor; ?>
7 </div>
8 <button type="button" class="botao-proximo">Próximo &rarr;</button>
9 </div>
10 </div>
CSS

Cartão e cabeçalho

O cabeçalho tem fundo próprio (mais escuro que o cartão) só pra funcionar como caixa de título — separa visualmente "onde estou" (título + indicador) do conteúdo que muda a cada slide.

1 .carrossel {
2 border: 1px solid #e2e8f0;
3 border-radius: 16px;
4 overflow: hidden;
5 font-family: inherit;
6 }
7 .cabecalho {
8 padding: 20px 24px;
9 text-align: center;
10 background: #f1f5f9;
11 border-bottom: 1px solid #cbd5e1;
12 }
13 .titulo {
14 margin: 0;
15 font-size: 18px;
16 font-weight: 700;
17 color: #0f172a;
18 }
19 .indicador {
20 display: inline-block;
21 margin-top: 6px;
22 font-size: 12px;
23 font-family: monospace;
24 color: #64748b;
25 }

Slide

display:none no slide inativo, não opacity nem visibility — um slide escondido não deve ocupar espaço nem ser lido por leitor de tela enquanto não é a vez dele.

1 .slide {
2 display: none;
3 padding: 20px;
4 }
5 .slide.ativo {
6 display: block;
7 }
8 .imagem {
9 width: 100%;
10 aspect-ratio: 1 / 1;
11 object-fit: cover;
12 border-radius: 12px;
13 margin-bottom: 16px;
14 }
15 .numero-titulo {
16 margin: 0 0 8px;
17 font-size: 16px;
18 font-weight: 600;
19 color: #1e293b;
20 }
21 .descricao {
22 margin: 0;
23 font-size: 14px;
24 line-height: 1.6;
25 color: #475569;
26 }

Navegação

O dot ativo fica maior e colorido (não é só uma troca de cor) — o formato diferente ajuda quem tem dificuldade de distinguir cor a perceber a posição atual mesmo assim.

1 .navegacao {
2 display: flex;
3 align-items: center;
4 gap: 12px;
5 padding: 0 20px 20px;
6 }
7 .botao-anterior,
8 .botao-proximo {
9 border: 1px solid #cbd5e1;
10 border-radius: 8px;
11 background: #f8fafc;
12 padding: 8px 14px;
13 font-size: 13px;
14 font-weight: 600;
15 color: #334155;
16 cursor: pointer;
17 }
18 .botao-anterior:disabled,
19 .botao-proximo:disabled {
20 opacity: 0.4;
21 cursor: default;
22 }
23 .dots {
24 flex: 1;
25 display: flex;
26 justify-content: center;
27 gap: 6px;
28 }
29 .dot {
30 width: 8px;
31 height: 8px;
32 border-radius: 999px;
33 border: none;
34 background: #cbd5e1;
35 cursor: pointer;
36 transition: width 0.15s ease, background-color 0.15s ease;
37 }
38 .dot.ativo {
39 width: 20px;
40 background: #6366f1;
41 }
JavaScript

Ir para um slide

Troca o slide e o dot ativos juntos, sempre pelo mesmo caminho — clique num dot, clique em "Próximo" ou em "Anterior" chamam esta mesma função, então nunca ficam fora de sincronia um do outro.

1 document.addEventListener('DOMContentLoaded', function () {
2 var carrossel = document.querySelector('.carrossel');
3 var slides = carrossel.querySelectorAll('.slide');
4 var dots = carrossel.querySelectorAll('.dot');
5 var indicador = carrossel.querySelector('.indicador');
6 var btnAnterior = carrossel.querySelector('.botao-anterior');
7 var btnProximo = carrossel.querySelector('.botao-proximo');
8 var total = slides.length;
9 var atual = 0;
10
11 function irPara(indice) {
12 slides[atual].classList.remove('ativo');
13 dots[atual].classList.remove('ativo');
14
15 atual = indice;
16
17 slides[atual].classList.add('ativo');
18 dots[atual].classList.add('ativo');
19 indicador.textContent = (atual + 1) + '/' + total;
20 btnAnterior.disabled = atual === 0;
21 btnProximo.disabled = atual === total - 1;
22 }

Ligar os controles

"Anterior"/"Próximo" andam um slide por vez e nunca dão a volta (por isso desabilitam nas pontas); os dots pulam direto pro índice clicado, de qualquer slide pra qualquer outro.

1 btnAnterior.addEventListener('click', function () { irPara(atual - 1); });
2 btnProximo.addEventListener('click', function () { irPara(atual + 1); });
3 dots.forEach(function (dot, indice) {
4 dot.addEventListener('click', function () { irPara(indice); });
5 });