Curso de CSS / Criar um site responsivo com HTML e CSS
Você pode combinar HTML semântico, variáveis CSS compartilhadas, navegação com Flexbox e layout de cartões em Grid para construir um pequeno site responsivo. Comece com conteúdo legível e um layout utilizável para telas estreitas, depois adicione ajustes para telas mais largas e estados de interação visíveis.
Defina a página e os critérios de aceitação
Decida qual conteúdo e comportamento a página precisa antes de aplicar o estilo. Em telas estreitas, a navegação se ajusta quando necessário e os cards formam uma coluna. Mais espaço disponível permite duas ou três colunas. Limite a largura de leitura geral para que o texto não se torne excessivamente longo em telas largas.
| Requisitos | Critérios de conclusão |
|---|---|
| estrutura de conteúdo | Um título principal, frase introdutória, três cards e rodapé são lidos em ordem. |
| tela estreita | Menus e cards são legíveis sem rolagem horizontal completa |
| tela larga | Os cartões são dispostos em várias colunas enquanto mantêm a largura máxima do corpo |
| navegação por teclado | Uma marca de foco aparece nos atalhos para o texto e links de menu/movimento. |
| Mudanças de conteúdo | Mesmo se você inserir descrições longas e strings sem espaços, o layout cresce para acomodá-las, sem altura fixa que corte o conteúdo. |
| movimento reduzido | Permite que você se mova conforme necessário sem rolagem suave e transições decorativas. |
Este exemplo é uma tela estática e não há links no próprio cartão. O menu de introdução/curso e os grandes links de navegação levam a seções do mesmo documento. Para expandir sua lista de cursos reais, coloque o URL do post verificado no título do cartão. Não é necessário adicionar formulários não utilizados ou animações infinitas para completar este exercício.
Prepare arquivos e HTML semântico
Crie index.html e style.css no mesmo local, em uma pasta vazia. Ao criar o arquivo, certifique-se de que não seja index.html.txt devido à extensão oculta e salve como UTF-8. A tag link em index.html aponta para style.css na mesma pasta. Nenhuma instalação ou build separado é necessário.
learning-site/
index.html
style.css
Primeiro, salve todo o HTML abaixo como index.html. Mesmo que o CSS esteja vazio, o título, o link e o conteúdo do cartão devem ser lidos em ordem. header é a área do cabeçalho do site, nav é a navegação, main é o conteúdo principal e footer é o rodapé. Use h2 para a seção de tópicos e h3 para os títulos dos cartões, abaixo do h1 do arquivo independente. Este HTML é um exemplo de um arquivo independente, portanto, ele está separado da estrutura da página que está diretamente anexada ao corpo do WordPress.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>A Small Learning Site</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<a class="skip-link" href="#main">Skip to main content</a>
<header class="site-header">
<div class="container header-inner">
<p class="site-name">Learning Notes</p>
<nav aria-label="Main navigation">
<a href="#intro">About</a><a href="#lessons">Lessons</a>
</nav>
</div>
</header>
<main id="main" tabindex="-1">
<section id="intro" class="hero" aria-labelledby="intro-title">
<div class="container">
<h1 id="intro-title">Learn to Build Webpages Step by Step</h1>
<p>Structure content with HTML and adapt its appearance with CSS.</p>
<a class="button" href="#lessons">Explore the lessons</a>
</div>
</section>
<section id="lessons" class="lessons container" aria-labelledby="lessons-title">
<h2 id="lessons-title">Learning topics</h2>
<ul class="card-grid" role="list">
<li><article class="card"><h3>HTML structure</h3><p>Organize content with headings and paragraphs.</p></article></li>
<li><article class="card"><h3>CSS styles</h3><p>Adjust colors, fonts, and spacing.</p></article></li>
<li><article class="card"><h3>Responsive layout</h3><p>Arrange cards to fit the available width.</p></article></li>
</ul>
</section>
</main>
<footer class="site-footer"><div class="container"><p>Small learning site exercise</p></div></footer>
</body>
</html>
O atalho para o texto principal está conectado ao ID de main. tabindex="-1" permite que main receba foco sem adicioná-lo à ordem normal de tabulação. Toque em um menu ou atalho para navegar até essa seção e garanta que a navegação pelo teclado continue a partir do conteúdo principal. Para o propósito e composição do atalho, consulte a técnica de atalho de texto W3C.
Defina valores compartilhados e largura do conteúdo
Comece o style.css com a seguinte seção. Nomear as variáveis de cor de acordo com suas funções facilita a alteração da cor de destaque compartilhada. border-box inclui padding e bordas na largura declarada, simplificando a definição de tamanho. Estabeleça um layout base que possa acomodar o crescimento do conteúdo em vez de atribuir dimensões fixas em todos os lugares. Antes de alterar os valores compartilhados, distinga Variáveis: var(), escopo, herança e fallback.
/* Shared values and base styles */
:root {
--ink: #183044;
--accent: #166b92;
--surface: #eef6fa;
--line: #c9dbe4;
--focus: #164f73;
}
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body { margin: 0; color: var(--ink); font-family: sans-serif; line-height: 1.6; }
a { color: var(--accent); text-underline-offset: .15em; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
.container { width: min(100% - 2rem, 68rem); margin-inline: auto; }
.container, .card { overflow-wrap: anywhere; }
A largura do contêiner é a menor entre “a largura disponível menos 2rem no total, reservando normalmente 1rem de cada lado” e 68rem. Fornece margens à esquerda e à direita para telas estreitas e largura máxima para telas largas. auto para margin-inline centraliza a área. overflow-wrap: anywhere permite que endereços ou identificadores longos e sem espaços sejam quebrados em uma linha, se necessário. Deve-se fazer uma distinção entre a prática que apenas aumenta o comprimento de uma frase geral e a prática que adiciona uma palavra longa.
Se você atualizar neste estágio, as cores, a fonte padrão e a largura do conteúdo serão aplicadas, mas os cabeçalhos e cartões ainda não serão detalhadamente organizados. Se não houver nenhuma mudança, verifique o caminho do arquivo antes de adicionar a seção de volta. Os conceitos de tamanho fluido e largura máxima estão vinculados aos Layout fluido com min() e clamp().
Construa navegação Flexbox e caminhos de foco
Adicione a seguinte seção sob Regras Comuns em style.css: O posicionamento entre o nome do site e o menu é gerenciado pelo header-inner, e o espaçamento dentro do menu é gerenciado pelo nav. Ao separar o intervalo entre as duas posições, você pode reduzir a possibilidade de alterações não intencionais no espaçamento entre os links do menu ao alterar o espaçamento de todo o cabeçalho. Os princípios básicos da direção do eixo e do posicionamento dos itens podem ser encontrados em Flexbox básico: contêineres, itens e eixos.
/* Navigation and header */
.skip-link { position: absolute; left: 1rem; top: -6rem; padding: .5rem; background: white; }
.skip-link:focus { top: 1rem; z-index: 10; }
.site-header { border-bottom: 1px solid var(--line); }
.header-inner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
gap: .5rem 1.5rem; padding-block: 1rem; }
.site-name { margin: 0; font-weight: 700; }
nav { display: flex; flex-wrap: wrap; gap: 1rem; }
flex-wrap coloca o item na linha seguinte se não houver espaço suficiente. Ter um menu de duas linhas em uma tela estreita não é uma falha. Os critérios para julgamento são se há sobreposição, truncamento ou links não clicáveis. Para manter uma ordem de navegação significativa, não use order apenas para inverter a apresentação visual sem avaliar a ordem de leitura e do teclado.
O atalho de texto geralmente é colocado fora da tela superior e é tornado visível quando recebe foco. Ocultá-lo com display:none não cumpre o mesmo propósito porque ele nem mesmo recebe foco do teclado. Ao pressionar Tab pela primeira vez, o link para saltar ao conteúdo aparece. Pressione Enter e depois Tab novamente: o foco deve seguir para o grande link da introdução. O contorno escuro de foco foi escolhido para se destacar tanto do fundo branco quanto do fundo da introdução.
Estilize a introdução fluida e os estados de link
Adicionar as seguintes seções completa o contexto introdutório, o título e os grandes links de navegação. O limite do tamanho do título vincula os valores mínimo, flutuante e máximo. A fonte não se torna infinitamente maior à medida que a largura aumenta, e a configuração do tamanho da fonte, incluindo o termo rem, também é levada em consideração. É necessária uma verificação de tela separada para ver se é realmente fácil de ler quando o usuário aumenta o zoom.
/* Introduction and navigation link */
.hero { padding-block: clamp(3rem, 8vw, 6rem); background: var(--surface); }
.hero h1 { max-width: 18ch; margin-block: 0 1rem;
font-size: clamp(1.8rem, 1.2rem + 2vw, 3rem); line-height: 1.25; }
.hero p { max-width: 50ch; }
.button { display: inline-block; margin-top: .5rem; padding: .7rem 1rem;
border-radius: .4rem; background: var(--accent); color: white; text-decoration: none;
transition: background-color 180ms ease; }
.button:hover { background: #104d6a; }
O max-width: 18ch do cabeçalho usa a largura do glifo “0” da fonte; isso não garante 18 letras por linha. Seu line-height controla as linhas de cabeçalho quebradas, enquanto o parágrafo introdutório é limitado a 50ch. Este exemplo usa fontes sans-serif do sistema e não baixa nenhuma fonte externa.
O grande link usa o elemento a porque navega até a seção de lições no mesmo documento. Uma ação que muda o estado, sem navegar, normalmente deve usar button. Apenas transições de cor de fundo são usadas ao passar o mouse, e nenhum movimento decorativo ou aumento é necessário. O status de foco pode ser confirmado por um contorno comum.
Construa cartões em grade que acomodem o conteúdo
Adicione as seguintes seções para completar seu cartão de curso e rodapé. Remova as margens e marcadores padrão da lista, mas mantenha as estruturas ul e li no HTML. Se uma lista com list-style: none estiver fora de nav, ela pode não ser reconhecida como uma lista na árvore de acessibilidade do Safari. No exemplo, ul especifica role="list" para definir o papel da lista. Esta condição também pode ser encontrada na listagem MDN descrição de acessibilidade. A ordem de leitura do HTML não muda para a disposição de linhas e colunas no Grid.
/* Cards and footer */
.lessons { padding-block: 3rem; }
.lessons h2 { margin-block: 0 1.5rem; }
.card-grid { display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
gap: 1rem; margin: 0; padding: 0; list-style: none; }
.card-grid > li { min-width: 0; }
.card { height: 100%; padding: 1.5rem; border: 1px solid var(--line); border-radius: .5rem; }
.card h3 { margin-block: 0 .75rem; }
.card p { margin-block: 0; }
.site-footer { padding-block: 2rem; border-top: 1px solid var(--line); }
.site-footer p { margin: 0; }
Grid: repeat(), auto-fit, auto-fill e áreas explica a repetição automática de colunas que cabem no contêiner, e minmax() determina o tamanho mínimo e o tamanho expansível de cada coluna. O valor mínimo de min(100%, 16rem) faz com que o cartão encolha até essa largura quando seu elemento pai for mais estreito que 16rem. O espaço livre é dividido por 1fr, e como existem três cartões reais, a largura adicional não cria um quarto cartão. auto-fit pode gerar faixas extras vazias e depois recolhê-las, distribuindo o espaço entre as ocupadas. Veja função repeat do MDN e função minmax.
Sob a condição de que o tamanho do texto de nível superior seja 16px e a largura da página disponível seja a mesma que a da janela de visualização, a largura mínima do cartão é 256px, o espaçamento é de 16px e as margens totais esquerda e direita são 32px. Você precisa de pelo menos 560px de espaço para duas colunas e 832px para três colunas. À medida que a barra de rolagem, a largura do elemento pai e o tamanho da fonte mudam, a largura de transição real também muda, então não a memorize com base no nome do dispositivo.
A altura de um cartão de 100% é o valor que preenche a altura dos itens da lista na mesma linha. Não é uma altura fixa em pixels, então as linhas podem crescer à medida que a descrição cresce. Para evitar que palavras longas ocupem o espaço do item do Grid, defina o min-width do li para 0 e use as regras de quebra de linha do cartão.
Adicione condições de tela ampla e movimento reduzido
Adicione esta seção ao final do style.css. A partir de 64rem, inclusive, o fundo da introdução muda para um gradiente. O grid continua determinando o número de colunas de cartão de forma independente; esta media query não define essa contagem.
/* Conditional adjustments */
@media (min-width: 64rem) {
.hero { background: linear-gradient(100deg, var(--surface), #fff); }
}
@media (prefers-reduced-motion: reduce) {
html { scroll-behavior: auto; }
.button { transition: none; }
}
Na condição de movimento reduzido, mudamos a rolagem para movimento instantâneo e também eliminamos as transições de cor de fundo. O propósito e o foco do link e seu conteúdo são mantidos. A aplicação das regras condicionais está conectada ao Media queries e pontos de quebra baseados no conteúdo, e a verificação de movimento e acessibilidade está conectada ao Verificar layout responsivo: largura, zoom e teclado.
Execute a folha de estilo completa
Este é um arquivo que combina todas as regras adicionadas passo a passo. Use este arquivo inteiro para verificar a ordem do seu código ou para recomeçar. Após salvá-lo na mesma pasta que o index.html, abra o index.html em um navegador e atualize.
/* Shared values and base styles */
:root {
--ink: #183044;
--accent: #166b92;
--surface: #eef6fa;
--line: #c9dbe4;
--focus: #164f73;
}
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body { margin: 0; color: var(--ink); font-family: sans-serif; line-height: 1.6; }
a { color: var(--accent); text-underline-offset: .15em; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
.container { width: min(100% - 2rem, 68rem); margin-inline: auto; }
.container, .card { overflow-wrap: anywhere; }
/* Navigation and header */
.skip-link { position: absolute; left: 1rem; top: -6rem; padding: .5rem; background: white; }
.skip-link:focus { top: 1rem; z-index: 10; }
.site-header { border-bottom: 1px solid var(--line); }
.header-inner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
gap: .5rem 1.5rem; padding-block: 1rem; }
.site-name { margin: 0; font-weight: 700; }
nav { display: flex; flex-wrap: wrap; gap: 1rem; }
/* Introduction and navigation link */
.hero { padding-block: clamp(3rem, 8vw, 6rem); background: var(--surface); }
.hero h1 { max-width: 18ch; margin-block: 0 1rem;
font-size: clamp(1.8rem, 1.2rem + 2vw, 3rem); line-height: 1.25; }
.hero p { max-width: 50ch; }
.button { display: inline-block; margin-top: .5rem; padding: .7rem 1rem;
border-radius: .4rem; background: var(--accent); color: white; text-decoration: none;
transition: background-color 180ms ease; }
.button:hover { background: #104d6a; }
/* Cards and footer */
.lessons { padding-block: 3rem; }
.lessons h2 { margin-block: 0 1.5rem; }
.card-grid { display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
gap: 1rem; margin: 0; padding: 0; list-style: none; }
.card-grid > li { min-width: 0; }
.card { height: 100%; padding: 1.5rem; border: 1px solid var(--line); border-radius: .5rem; }
.card h3 { margin-block: 0 .75rem; }
.card p { margin-block: 0; }
.site-footer { padding-block: 2rem; border-top: 1px solid var(--line); }
.site-footer p { margin: 0; }
/* Conditional adjustments */
@media (min-width: 64rem) {
.hero { background: linear-gradient(100deg, var(--surface), #fff); }
}
@media (prefers-reduced-motion: reduce) {
html { scroll-behavior: auto; }
.button { transition: none; }
}
Altere os valores e diagnostique problemas
- Reduza a largura da tela para cerca de 390px e depois a aumente, mantendo o valor original. Para larguras pequenas deve haver uma coluna, para larguras grandes deve haver duas ou três colunas. Se as condições descritas acima forem as mesmas, as diferenças entre 559px e 560px e 831px e 832px também são comparadas.
- Altere apenas 16rem do card-grid para 20rem. Adicionar mais colunas na mesma tela requer mais espaço. Após a confirmação, restaure para 16rem.
- Altere apenas 68rem do container para 50rem. Mesmo em telas maiores, a largura geral do conteúdo fica mais estreita. Após a confirmação, restaure para 68rem.
- Altere apenas --accent para outra cor suficientemente escura. Veja se o fundo dos links e botões muda junto e restaure suas cores originais. O texto branco do botão e o indicador de foco também devem ser legíveis no novo fundo.
- Estenda a descrição de um cartão em várias frases. Certifique-se de que o conteúdo não seja truncado conforme a altura aumenta e que a altura dos cartões na mesma linha esteja organizada. Após a prática, restaure a frase original.
- Insira uma string em inglês sem espaços no cartão. overflow-wrap: anywhere permite quebrar a string dentro do cartão sem mudar seu valor. Apenas remover temporariamente essa regra de quebra de linha pode causar estouro. Após a comparação, tanto as regras quanto as frases são restauradas.
- Mova-se com Tab e Shift+Tab e pressione Enter para cada link. Você deve ser capaz de navegar para a introdução e os tópicos de estudo sem precisar de um mouse.
- Reproduza as condições de redução de movimento. A navegação pelos links deve continuar funcionando e a rolagem/transições suaves devem desaparecer. Após a confirmação, restaure as configurações de reprodução para o padrão.
Verifique se a navegação, os cards, os indicadores de foco e os parágrafos permanecem legíveis quando o navegador é ampliado ou quando as configurações de fonte mudam. Aumentar temporariamente o tamanho da fonte do html no DevTools testa o dimensionamento baseado em rem, mas é diferente do zoom do navegador. Uma configuração bem-sucedida não estabelece a usabilidade em todas as condições de zoom e tamanho de texto.
| problema | Verifique primeiro |
|---|---|
| Nenhum estilo | Extensão do arquivo, status de salvamento, caminho relativo do link |
| Ocorre rolagem horizontal | Palavras longas, tamanho mínimo da coluna, largura real do elemento pai, border-box ausente |
| Altura do cartão irregular | Definindo a altura da mesma linha e cartão; Linhas diferentes não precisam ser iguais |
| Nenhum indicador de foco visível | Regras que sobrescrevem o contorno, seja o contorno cortado devido ao overflow |
| Efeito de movimento indesejado | Condições reais de mídia e valores aplicados de scroll-behavior·transition |
Selecione o elemento problemático nas Ferramentas de Desenvolvedor para ver a largura calculada real, o seletor e as colunas do Grid. Em vez de mascarar o problema forçando todas as quebras de linha ou adicionando overflow:hidden ao corpo, primeiro corrija o tamanho e o conteúdo do elemento com overflow. Ao verificar o estado base, o estado modificado e o estado de restauração para cada requisito, você pode ir um passo além de copiar o código completo e aplicá-lo também a outros conteúdos.




