Como fazer um site responsivo CSS

Abra o seu site no celular. Se o texto aparece minúsculo, se você precisa dar zoom com dois dedos para ler, ou se a página rola para os lados, o site não é responsivo. E isso pesa: hoje a maior parte dos acessos na internet vem do celular, e o Google usa a versão mobile do site como referência para posicionar as páginas na busca.

Neste artigo vamos construir, passo a passo, um site que se adapta sozinho ao tamanho da tela: duas colunas no computador, uma coluna no tablet e um menu empilhado no celular, com direito a um banner diferente para cada tamanho. Tudo com HTML e CSS puros.

O que é um site responsivo?

Um site responsivo é aquele que reorganiza o próprio layout de acordo com a largura da tela. Não existe uma versão “para celular” e outra “para computador”: é o mesmo HTML, e o CSS decide como mostrar cada parte em cada tamanho.

O mesmo site em três telas: computador com duas colunas, tablet com uma coluna e celular com menu empilhado Computador 2 colunas (30% + 70%) Tablet colunas empilhadas Celular menu empilhado
O mesmo HTML em três tamanhos de tela. Quem muda a organização é o CSS.

Para chegar nesse resultado, precisamos de três ingredientes:

1Meta viewportAvisa o celular para usar a largura real da tela.
2Layout flexívelColunas em porcentagem, com flexbox.
3Media queriesRegras de CSS que só valem em certos tamanhos de tela.

Ingrediente 1: a meta tag viewport

Sem nenhuma instrução, o navegador do celular finge que a tela tem uns 980px de largura, desenha a página nesse tamanho e depois encolhe tudo para caber. Resultado: um site em miniatura, com texto ilegível. A linha abaixo, dentro do <head>, desliga esse comportamento:

<meta name="viewport" content="width=device-width, initial-scale=1">
  • width=device-width: a largura da página é a largura real do aparelho.
  • initial-scale=1: a página abre sem zoom, em tamanho 100%.
Celular sem meta viewport mostra o site em miniatura; com meta viewport mostra o layout adaptado Sem a meta viewport tudo minúsculo, precisa de zoom o celular finge ter ~980pxCom a meta viewport usa a largura real da tela
Esquecer a meta viewport faz todo o resto do CSS responsivo parecer “não funcionar” no celular.
Guarde isto: sem a meta viewport, suas media queries podem até funcionar no computador (diminuindo a janela), mas no celular de verdade o layout continua o de computador, em miniatura. É o erro número 1 de quem está começando.

A estrutura do nosso exemplo

O site de exemplo tem cinco blocos, usando tags semânticas, que dizem ao navegador (e ao Google) o papel de cada parte:

<header class="cabecalho"> ... </header>     <!-- banner com o título -->
<nav class="barra_nav"> ... </nav>           <!-- menu -->

<div class="coluna">
  <aside class="lateral"> ... </aside>       <!-- coluna da esquerda (30%) -->
  <main class="principal"> ... </main>      <!-- conteúdo principal (70%) -->
</div>

<footer class="rodape"> ... </footer>        <!-- rodapé -->

A <div class="coluna"> é uma caixa que envolve as duas colunas. É nela que o flexbox vai agir.

Ingrediente 2: layout flexível com flexbox

O flexbox é um modo de layout do CSS feito para organizar elementos em linha ou em coluna. Ele funciona sempre em dupla: um container (a caixa de fora) e seus itens (as caixas de dentro).

display: flex — os filhos lado a lado

Por padrão, blocos como <aside> e <main> ficam um embaixo do outro. Quando o container recebe display: flex, os filhos passam a ficar lado a lado:

.coluna {
  display: flex;      /* os filhos ficam lado a lado */
  flex-wrap: wrap;    /* se não couberem, quebram para a linha de baixo */
}

flex: 30% e 70% — a largura de cada coluna

Nos itens, a propriedade flex define o tamanho de cada um. Usamos porcentagem, e não pixels, para que as colunas se ajustem a qualquer largura de tela:

.lateral {
  flex: 30%;          /* a lateral ocupa 30% da largura */
}

.principal {
  flex: 70%;          /* o conteúdo ocupa 70% */
}
Container flex com duas colunas: lateral com 30% e principal com 70%; com flex-direction column ficam empilhadas flex-direction: row (padrão) .lateral 30% .principal 70% container .coluna com display: flex → os filhos ficam lado a ladoflex-direction: column .lateral .principal
Com flex-direction: column, os mesmos itens passam a ficar um embaixo do outro.

flex-direction — linha ou coluna?

Essa é a propriedade-chave para a responsividade. Ela define a direção em que os itens são organizados:

  • flex-direction: row (padrão): itens lado a lado, em linha.
  • flex-direction: column: itens um embaixo do outro, em coluna.

No computador queremos row e no celular, column. Para trocar uma pela outra dependendo do tamanho da tela, usamos o terceiro ingrediente.

Ingrediente 3: media queries (@media)

Uma media query é um bloco de CSS com uma condição: as regras dentro dela só valem quando a condição é verdadeira. A condição mais usada é a largura da tela:

Anatomia de uma media query: @media, tipo de mídia, condição e regras @media screen and (max-width: 768px) { .coluna { flex-direction: column; } } a regra especial tipo de mídia (tela) condição: largura até 768px regras que só valem quando a condição é verdadeira
Lê-se: “em telas de até 768px de largura, empilhe as colunas”.

max-width ou min-width?

  • max-width: 768px significa “até 768px”: vale para telas de 768px ou menos.
  • min-width: 768px significa “a partir de 768px”: vale para telas de 768px ou mais.

No nosso exemplo usamos max-width: escrevemos o CSS pensando no computador e depois ajustamos para as telas menores. O caminho inverso, com min-width, se chama mobile first (primeiro o celular) e é assunto para um próximo artigo.

Os pontos de quebra (breakpoints)

Os valores de largura em que o layout muda se chamam breakpoints. Não existe um número mágico, mas alguns são bem comuns:

BreakpointAparelhos típicos
até 500pxCelulares em pé
até 768pxTablets em pé e celulares deitados
até 1024pxTablets deitados e notebooks pequenos
acima de 1024pxNotebooks e monitores
Dica de ouro: escolha o breakpoint olhando para o seu conteúdo, não para um modelo de celular. Diminua a janela devagar e, no ponto em que o layout começar a ficar apertado ou feio, coloque ali uma media query.

As duas media queries do exemplo

Nosso site usa dois breakpoints, cada um resolvendo um problema:

/* Tablets e celulares (até 768px): colunas empilhadas */
@media screen and (max-width: 768px) {
  .coluna {
    flex-direction: column;
  }
}

/* Celulares (até 500px): menu empilhado e banner próprio */
@media screen and (max-width: 500px) {
  .barra_nav {
    flex-direction: column;
  }

  .cabecalho {
    background-image: url(../imagem/banner_celular_420x250.png);
  }
}

Repare que a tela de 400px atende às duas condições (é menor que 768px e menor que 500px), então as duas media queries valem ao mesmo tempo. Já uma tela de 700px só atende à primeira.

Trocando o banner conforme a tela

Um banner largo, de 1500×500, fica lindo no computador. No celular, porém, ele seria cortado e perderia os detalhes das laterais. A solução é trocar a imagem de fundo dentro da media query. Só a propriedade background-image precisa ser repetida: o resto (background-size, color etc.) continua valendo da regra original.

.cabecalho {
  padding: 60px 20px;
  text-align: center;
  color: white;
  background-color: #0a1128;          /* reserva, caso a imagem não carregue */
  background-image: url(../imagem/banner_responsivo.png);
  background-size: cover;             /* cobre toda a área, sem distorcer */
  background-position: center;        /* centraliza o recorte */
}
Por que o ../ no caminho? O caminho da imagem é contado a partir do arquivo CSS, e não do HTML. Como o styles.css está dentro da pasta css/, o ../ sobe um nível antes de entrar na pasta imagem/.

Teste aqui: arraste e veja o layout mudar

A miniatura abaixo reproduz o nosso site. Arraste o canto inferior direito da moldura para a esquerda e veja as colunas se empilharem e, depois, o menu também.

Arraste o canto ↘ da moldura para diminuir
Site ResponsivoCom layout responsivo.
InícioPágina 2Página 3Página 4
Sobre mimImagemTexto da lateral.
TÍTULO DO TEXTOImagemTexto do conteúdo principal.
Seu Nome ©

No celular, gire a tela ou abra o artigo no computador para testar.

Como testar no navegador (sem precisar de celular)

  1. Abra o seu index.html no Chrome, Edge ou Firefox.
  2. Aperte F12 para abrir as ferramentas do desenvolvedor.
  3. Aperte Ctrl + Shift + M (ou clique no ícone de celular e tablet) para ativar o modo dispositivo.
  4. Escolha um aparelho na lista do topo (iPhone, Galaxy, iPad…) ou arraste as bordas para testar qualquer largura.

O jeito mais simples continua valendo: diminuir a janela do navegador com o mouse. Por isso o exemplo tem a faixa amarela no topo com esse lembrete.

Erros comuns

1. Esquecer a meta viewport

No computador tudo funciona; no celular, o site aparece em miniatura. Confira se a linha <meta name="viewport" ...> está no <head>.

2. Colocar a media query no começo do CSS

Se a regra normal vier depois da media query, ela sobrescreve a media query (as duas têm a mesma força, e vence a última). Deixe as media queries sempre no final do arquivo.

3. Larguras fixas em pixels

Uma coluna com width: 400px não cabe numa tela de 360px e cria uma rolagem para os lados. Prefira porcentagem e, para imagens, max-width: 100%.

4. Errar o caminho da imagem de fundo

O caminho é contado a partir do arquivo CSS. Se o banner não aparecer, confira o ../ e o nome exato do arquivo (maiúsculas, minúsculas e extensão).

5. Esquecer o espaço depois do and

@media screen and(max-width: 768px), sem o espaço antes do parêntese, faz o navegador ignorar a media query inteira. O certo é and (max-width: 768px).

Código completo do exemplo

Monte a pasta assim e abra o index.html no navegador:

site-responsivo/
├── index.html
├── css/
│   └── styles.css
└── imagem/
    ├── banner_responsivo.png          (1500 × 500)
    └── banner_celular_420x250.png     (420 × 250)
index.html
<!DOCTYPE html>
<html lang="pt-BR">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Site Responsivo</title>
  <link rel="stylesheet" href="css/styles.css">
</head>
<body>

  <!-- Anotação -->
  <div class="anotacao">
    <p>Diminua a janela do navegador para ver o efeito de responsividade.</p>
  </div>

  <!-- Cabeçalho -->
  <header class="cabecalho">
    <h1>Site Responsivo Mobile/Desktop</h1>
    <p>Com <b>layout</b> responsivo.</p>
  </header>

  <!-- Barra de navegação -->
  <nav class="barra_nav">
    <a href="#">Início</a>
    <a href="#">Página 2</a>
    <a href="#">Página 3</a>
    <a href="#">Página 4</a>
  </nav>

  <!-- Layout flexível (conteúdo) -->
  <div class="coluna">

    <aside class="lateral">
      <h2>Sobre mim</h2>
      <p class="legenda">Foto:</p>
      <div class="imagem_falsa">Imagem</div>
      <p>Algum texto genérico para marcar o espaço utilizado no parágrafo.</p>
      <h3>Mais texto</h3>
      <p>Algum texto genérico para marcar o espaço utilizado no parágrafo.</p>
      <div class="imagem_falsa2">Imagem</div>
      <div class="imagem_falsa2">Imagem</div>
      <div class="imagem_falsa2">Imagem</div>
    </aside>

    <main class="principal">
      <article>
        <h2>TÍTULO DO TEXTO</h2>
        <p class="legenda">Texto descritivo, 17 de março de 2023</p>
        <div class="imagem_falsa3">Imagem</div>
        <h3>Mais texto</h3>
        <p>Algum texto genérico para marcar o espaço utilizado no parágrafo.</p>
      </article>

      <article>
        <h2>TÍTULO DO TEXTO</h2>
        <p class="legenda">Texto descritivo, 16 de março de 2023</p>
        <div class="imagem_falsa3">Imagem</div>
        <h3>Mais texto</h3>
        <p>Algum texto genérico para marcar o espaço utilizado no parágrafo.</p>
      </article>
    </main>

  </div>

  <!-- Rodapé -->
  <footer class="rodape">
    <p>Seu Nome &copy;</p>
  </footer>

</body>
</html>
css/styles.css
* {
  box-sizing: border-box;
}

/* Estilo do body */
body {
  font-family: Arial, sans-serif;
  margin: 0;
}

.anotacao {
  background-color: rgb(244, 248, 19);
  padding: 5px;
  text-align: center;
  font-weight: bold;
}

.anotacao p {
  margin: 8px 0;
}

/* Cabeçalho */
.cabecalho {
  padding: 60px 20px;
  text-align: center;
  color: white;
  background-color: #0a1128;                      /* reserva, caso a imagem não carregue */
  background-image: url(../imagem/banner_responsivo.png);
  background-size: cover;
  background-position: center;
}

/* Barra de navegação: links lado a lado */
.barra_nav {
  display: flex;
  background-color: #333;
}

.barra_nav a {
  color: white;
  padding: 14px 20px;
  text-decoration: none;
  text-align: center;
}

/* Trocar a cor quando o cursor estiver sobre o link */
.barra_nav a:hover {
  background-color: #ddd;
  color: black;
}

/* Contorno para quem navega pelo teclado */
.barra_nav a:focus-visible {
  outline: 3px solid #f68e36;
  outline-offset: -3px;
}

/* Coluna: as duas colunas lado a lado */
.coluna {
  display: flex;
  flex-wrap: wrap;
}

/* Barra lateral: 30% da largura */
.lateral {
  flex: 30%;
  background-color: #f1f1f1;
  padding: 20px;
}

/* Coluna principal: 70% da largura */
.principal {
  flex: 70%;
  background-color: white;
  padding: 20px;
}

.legenda {
  font-size: 13px;
  font-weight: bold;
}

/* Imagens falsas, apenas para marcar o espaço */
.imagem_falsa {
  background-color: #0ec40e7e;
  width: 100%;
  height: 200px;
  padding: 20px;
}

.imagem_falsa2 {
  background-color: #c7313191;
  width: 100%;
  height: 60px;
  padding: 20px;
  margin-bottom: 16px;
}

.imagem_falsa3 {
  background-color: #313bc777;
  width: 100%;
  height: 200px;
  padding: 20px;
}

/* Rodapé */
.rodape {
  padding: 20px;
  text-align: center;
  background-color: #ddd;
  font-size: 22px;
  font-weight: bold;
}

/* ===== RESPONSIVIDADE ===== */

/* Tablets e celulares (até 768px): as colunas ficam uma embaixo da outra */
@media screen and (max-width: 768px) {
  .coluna {
    flex-direction: column;
  }
}

/* Celulares (até 500px): menu empilhado e banner próprio para tela pequena */
@media screen and (max-width: 500px) {
  .barra_nav {
    flex-direction: column;
  }

  .cabecalho {
    background-image: url(../imagem/banner_celular_420x250.png);
  }
}

Resumo rápido

RecursoPara que serve
<meta name="viewport">Faz o celular usar a largura real da tela
display: flexColoca os filhos do container lado a lado
flex-wrap: wrapDeixa os itens quebrarem de linha quando não cabem
flex: 30%Define o tamanho do item em relação ao container
flex-direction: columnEmpilha os itens um embaixo do outro
@media (max-width: 768px)Aplica regras só em telas de até 768px

Desafio para praticar

  1. Monte o projeto com a estrutura de pastas acima e teste nas três larguras: computador, tablet (700px) e celular (400px).
  2. Crie uma terceira media query, para telas de até 400px, que diminua o tamanho do h1 do cabeçalho.
  3. Mude as proporções das colunas para 25% e 75%. O que acontece com a lateral no computador?
  4. Apague a meta viewport, abra o site no seu celular e compare. Depois, coloque-a de volta.
  5. Desafio extra: faça os links do menu ocuparem a mesma largura no computador, adicionando flex: 1 em .barra_nav a.

Washington Paiva — instrutor de Desenvolvimento de Sistemas · washington.pro.br

Compartilhe:

Profissional engajado com as últimas tendências tecnológicas e de gestão, buscando continuamente aprimorar suas competências e compartilhar seu conhecimento.

Publicar comentário