Capítulo 11
Tabelas
5 min de leitura 962 palavras 2 gravuras
Este capítulo marca dados em linhas e colunas. A agenda da Oficina Costeira, coletivo fictício de design em João Pessoa, vira tabela acessível. Tabela não é ferramenta de layout. O exemplo correspondente é 11-tabelas, no pacote que acompanha o volume.
Este volume tem 52 capítulos. Ciclo: ler → copiar → mudar uma coisa → prever → recarregar → conferir.
O que você vai aprender
- Usar
table,tretdsó para dado tabular. - Colocar
captioncomo resumo. - Marcar
thcomscope="col"ouscope="row". - Agrupar
thead,tbodyetfoot. - Entender
colspansem quebrar a conta das células. - Recusar tabela para desenhar o menu da Oficina.
Tabela é planilha, não página
Quando a informação é “isto cruzado com aquilo”, use tabela. Agenda: dia × atividade × local. Equipe em lista não precisa de tabela. O menu nunca precisa.
Há vinte anos gente usava table para colocar o logo à esquerda e o texto à direita. Isso é layout. Layout neste volume virá com CSS (flex e grid, mais adiante). HTML de tabela para aparência atrapalha o leitor de tela e o celular.
Erro comum: envolver a home inteira da Oficina Costeira numa table de uma coluna. Parece “organizado”. É o instrumento errado.
Linha e célula
table envolve o conjunto. tr é a linha. td é a célula de dado. Célula não fica solta fora da linha.
<table>
<tr>
<td>12</td>
<td>Revisão de cartaz</td>
<td>Restinga (fictício)</td>
</tr>
</table>
Isso ainda é pobre: falta título das colunas e falta legenda. O navegador mostra um grid. Quem ouve a página não sabe o que cada número significa.
caption
caption é o primeiro filho da tabela. Resume o conteúdo. A pessoa decide se entra na grade ou pula.
<table>
<caption>Encontros fictícios de setembro na Oficina Costeira</caption>
<tr>
<td>12</td>
<td>Revisão de cartaz</td>
</tr>
</table>
Não use caption para o h1 da página. O h1 continua “Agenda”. A caption fala da tabela.

th e scope
th é célula de cabeçalho. scope="col" diz: este th nomeia a coluna. scope="row" nomeia a linha.
<table>
<caption>Encontros fictícios de setembro na Oficina Costeira</caption>
<thead>
<tr>
<th scope="col">Dia</th>
<th scope="col">Atividade</th>
<th scope="col">Local</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">12</th>
<td>Revisão de cartaz — Farol da Restinga</td>
<td>Restinga (fictício)</td>
</tr>
<tr>
<th scope="row">19</th>
<td>Leitura do Guia da Lagoa</td>
<td>Lagoa (fictício)</td>
</tr>
<tr>
<th scope="row">26</th>
<td>Montagem do Ateliê da Pedra</td>
<td>Centro (fictício)</td>
</tr>
</tbody>
</table>
Sem scope, o leitor de tela adivinha. Com scope, a célula “19” se anuncia como dia, não como texto solto.
Copie a tabela para agenda.html dentro de main id="conteudo", com skip-link e lang="pt-BR". Mude só a atividade do dia 12. Preveja a célula. Recarregue. Confira.
thead, tbody, tfoot
thead agrupa as linhas de cabeçalho. tbody o miolo. tfoot totais ou notas. Todos exigem tr dentro. Não substituem a linha.
<tfoot>
<tr>
<th scope="row">Total</th>
<td colspan="2">Três encontros fictícios</td>
</tr>
</tfoot>
colspan="2" funde duas colunas. A conta de células da linha precisa fechar com as outras linhas. Se o cabeçalho tem três colunas, esta linha tem 1 (th) + 2 (td colspan) = 3.
rowspan funde para baixo. Use pouco. Grade irregular é difícil de ouvir.
CSS só depois da marcação
border-collapse: collapse junta bordas. vertical-align alinha o texto na célula. Cor e tipo são regras como em qualquer elemento.
table {
border-collapse: collapse;
width: 100%;
}
th,
td {
border: 1px solid #333;
padding: 0.5rem;
text-align: left;
}
Isso não transforma a tabela em menu. O seletor table estiliza dado. O menu continua em nav ul.
Arquivo no disco: HTML da agenda. Página no navegador: grade. Teste em 127.0.0.1: Tab deve entrar na tabela depois do skip-link e do menu. Publicação pública não é pedida.

Erro comum: th sem scope em tabela com cabeçalho nas duas direções. O dia 12 vira só “negrito”.
Página completa da agenda
Estrutura da página: skip-link, header com nav, main com h1 e a table, footer. Cinco itens de menu. aria-current="page" em Agenda.
Não coloque a tabela no header. Não use tabela para as três pessoas da Equipe: ali a lista ul já basta.
Abra exemplos/11-tabelas/agenda.html. Troque um th scope="col" por td. Preveja: visual parecido, significado pior. Recarregue. Confira no inspetor.
Não aninhe table dentro de table neste volume. Não coloque o menu da Oficina Costeira em células. Não use colspan para “centralizar o logo”.
Se a agenda crescer, uma linha por encontro. Data ISO pode ir num time datetime="2026-09-12" dentro da célula, para a máquina. O texto visível pode continuar “12”.
Leia a tabela em voz alta: “Dia 12, revisão de cartaz, Restinga fictícia.” Se a frase não se monta, falta scope.
Não estilize só a primeira coluna com bgcolor antigo. Use seletor CSS. Atributos de apresentação no HTML de tabela são do século passado.
Copie a tabela da agenda para um arquivo novo agenda-teste.html. Tire a caption. Recarregue. A grade continua. A acessibilidade piora. Recoloque a caption. Confira o primeiro elemento da table no inspetor.
th em toda a primeira linha. th na primeira célula de cada linha de dado, se o dia for o nome da linha. Não transforme toda a tabela em th: aí some o dado.
Layout da página: header, main, footer. A tabela mora no main. Fora daí ela compete com o menu e perde o sentido.
O exemplo deste capítulo está em 11-tabelas.
Atividades
- Por que o menu da Oficina Costeira não deve ser uma
table? - O que
scope="row"faz na célula do dia 19? - Qual o papel de
captionem relação aoh1Agenda? - No exemplo, mude só uma célula de local. O que a grade mostrou depois de salvar e recarregar?
Respostas comentadas
- Menu é lista de destinos, não cruzamento de dados.
nav+uldescreve navegação. Tabela forçaria linhas e colunas sem relação tabular. - Anuncia que “19” é o cabeçalho daquela linha. O leitor associa a atividade e o local a esse dia.
- O
h1nomeia a página. Acaptionresume a tabela, para quem decide se explora a grade. - Só aquela célula muda. As outras linhas permanecem. Se nada mudou, a aba não é o
agenda.htmldo exemplo 11.
Referências
O arquivo completo
Referência do exemplo 11-tabelas, reproduzida aqui para que você possa conferir sem sair da página.
assets/javascript/simulacao.js
const form=document.querySelector("#simulacao");if(form){form.querySelector("button[type=submit]").disabled=false;form.addEventListener("submit",event=>{event.preventDefault();document.querySelector("#retorno").textContent="Simulação concluída. Nada foi enviado ou guardado.";});}