Tabela larga no celular: rolagem com nome ou ficha por linha, sem espremer
Escolha entre rolagem horizontal acessível e layout de fichas, mantenha cabeçalho ligado a cada valor e teste no telefone se ainda dá para saber de qual coluna é o número.
O relatório "Vendas por loja" tem oito colunas: loja, pedidos, faturamento, ticket médio, devoluções, frete, margem e variação. No desktop, perfeito. No celular do gerente regional, cada coluna ficou com 40 pixels de largura, os números quebraram em três linhas e "R$ 18.430,00" virou "R$ / 18.430 / ,00".
A resposta curta: não esprema a tabela. Você tem dois caminhos honestos. Se a pessoa precisa comparar linhas, deixe a tabela com largura natural dentro de uma área de rolagem horizontal com nome, mantendo a primeira coluna fixa. Se cada linha é lida isoladamente, transforme cada linha numa ficha que repete o nome de cada campo ao lado do valor. Os dois preservam a pergunta "de qual coluna é este número?".
Por que a tabela espreme
Tabela HTML tenta caber no contêiner. Quando o espaço acaba, o navegador reduz as colunas até o limite da palavra mais longa de cada uma e quebra o resto. Com width: 100% num contêiner de 360 pixels, oito colunas ficam com uns 45 pixels cada, descontado o espaçamento. Números longos quebram em pontos que destroem o sentido.
Quando o texto não pode quebrar, o problema muda de lugar: a tabela estoura a página e o layout inteiro passa a rolar para o lado, incluindo cabeçalho e menu. A pessoa rola para ver a coluna "margem" e perde a coluna "loja". Ela vê 23% e não sabe de qual loja é.
Qual caminho escolher
- Rolagem horizontal quando o valor está na comparação: ranking de lojas, extrato, planilha de preços. A pessoa precisa ver a coluna inteira de cima a baixo.
- Fichas quando cada linha é um objeto: lista de pedidos, cadastro de clientes, chamados. A pessoa lê um registro de cada vez.
- Menos colunas sempre que possível: pergunte se o celular precisa das oito. Às vezes a versão móvel mostra três colunas e um link para o detalhe.
Como fazer a rolagem horizontal acessível
- Envolva a tabela num contêiner com
overflow-x: auto. Só a tabela rola, o resto da página fica parado. - Dê ao contêiner
role="region", um nome viaaria-labelledbyapontando para a legenda etabindex="0", para quem usa teclado conseguir focar e rolar com as setas. - Use
captioncomo título da tabela,th scope="col"no cabeçalho eth scope="row"na primeira célula de cada linha. - Impeça a quebra de números com
white-space: nowrape defina uma largura mínima para a tabela. - Fixe a primeira coluna com
position: stickye fundo opaco. - Deixe visível que há mais conteúdo: a última coluna cortada pela metade já sinaliza, ou um texto curto acima da tabela.
<div class="rolagem-tabela" role="region" aria-labelledby="cap-vendas" tabindex="0">
<table>
<caption id="cap-vendas">Vendas por loja, setembro de 2026</caption>
<thead>
<tr>
<th scope="col">Loja</th>
<th scope="col">Pedidos</th>
<th scope="col">Faturamento</th>
<th scope="col">Margem</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Centro</th>
<td>412</td>
<td>R$ 18.430,00</td>
<td>23%</td>
</tr>
</tbody>
</table>
</div>
.rolagem-tabela {
overflow-x: auto;
max-width: 100%;
}
.rolagem-tabela:focus-visible {
outline: 3px solid #1a5fb4;
outline-offset: 2px;
}
.rolagem-tabela table {
border-collapse: collapse;
min-width: 44rem;
}
.rolagem-tabela th,
.rolagem-tabela td {
padding: 0.5rem 0.75rem;
white-space: nowrap;
text-align: right;
}
.rolagem-tabela th[scope="row"] {
position: sticky;
left: 0;
background: #fff;
text-align: left;
}
O fundo branco na coluna fixa é obrigatório: sem ele, os números das outras colunas passam por baixo e aparecem através do nome da loja. Se você também quer o cabeçalho fixo ao rolar na vertical, a técnica e os motivos pelos quais o sticky às vezes não gruda estão em cabeçalho fixo de tabela.
Como fazer o layout de fichas
Para a lista de pedidos, cada linha vira um bloco. A tabela continua sendo tabela no HTML, e o CSS muda a apresentação só em telas estreitas. Cada célula carrega o nome da coluna num atributo, que o CSS mostra antes do valor.
<td data-rotulo="Faturamento">R$ 18.430,00</td>
@media (max-width: 40rem) {
.tabela-fichas thead {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
}
.tabela-fichas tr {
display: block;
border: 1px solid #ccc;
border-radius: 6px;
margin-bottom: 0.75rem;
padding: 0.5rem;
}
.tabela-fichas td,
.tabela-fichas th[scope="row"] {
display: flex;
justify-content: space-between;
gap: 1rem;
}
.tabela-fichas td::before {
content: attr(data-rotulo);
font-weight: 600;
}
}
Um alerta importante: mudar o display de elementos de tabela pode fazer alguns navegadores deixarem de expor a estrutura de tabela para leitores de tela. Teste com o leitor de tela do aparelho. Se a estrutura sumir, uma saída conhecida é reforçar com papéis ARIA explícitos (role="table", role="row", role="cell", role="columnheader"). Outra é gerar fichas de verdade, com lista e rótulos no HTML, quando o conteúdo não é comparativo.
Também note que o cabeçalho foi escondido só visualmente, e não com display: none, para continuar disponível a tecnologias assistivas.
O que não fazer
Trocar a tabela por um amontoado de div para "facilitar o responsivo" é o erro mais caro. Você perde a associação entre cabeçalho e célula, perde a navegação por tabela do leitor de tela e passa a manter dois layouts manualmente. Se o conteúdo é tabular, o HTML é table. A partir daí, a decisão de layout é do CSS, escrito primeiro para o celular como mostra CSS mobile-first.
Erros comuns
- Deixar a tabela com
width: 100%e oito colunas. Os valores quebram em pedaços e "R$ 18.430,00" vira três linhas ilegíveis. - Página inteira rolando para o lado. Menu e cabeçalho somem junto, e a pessoa se perde na própria tela.
- Coluna fixa sem fundo. O conteúdo que rola aparece por baixo do nome e nenhum dos dois se lê.
- Área de rolagem sem foco nem nome. Quem usa teclado não consegue rolar e o leitor de tela não sabe o que é aquela região.
- Esconder o cabeçalho com
display: none. A associação entre valor e coluna desaparece para quem não enxerga. - Testar só no modo responsivo do desktop. Rolagem com o dedo, largura real e leitor de tela do aparelho se comportam diferente.
Checklist
- Cada tabela larga foi classificada como comparativa (rolagem) ou de registros (fichas).
- A tabela tem
caption,th scope="col"eth scope="row". - Só o contêiner da tabela rola na horizontal, não a página.
- O contêiner de rolagem tem nome,
role="region"e é focável. - Números não quebram linha.
- A primeira coluna fica fixa com fundo opaco.
- No layout de fichas, todo valor aparece com o nome da coluna.
- O resultado foi conferido no telefone com o leitor de tela ligado.
Abra no celular a tabela mais larga do seu sistema e role até a última coluna. Você ainda consegue dizer, sem voltar, a qual linha e a qual coluna pertence o número que está vendo?
Referência: https://www.w3.org/WAI/tutorials/tables/