🎨 Fase 0 — HTML & CSS
Bem-vindo ao DevTrail! Aqui começa sua jornada. Nesta fase você vai revisar e solidificar HTML e CSS — a estrutura e o estilo de tudo que existe na web. Ao final, você terá uma página de portfólio publicada no GitHub Pages.
1. Crie sua conta e o repositório
- Acesse github.com e crie sua conta (gratuita)
- Clique em New repository
- Nome:
html-css-review - Marque Add a README file e clique em Create repository
2. Instale o Git no seu computador
Baixe em git-scm.com e instale com as opções padrão.
3. Configure sua identidade (uma vez só)
git config --global user.name "Seu Nome"
git config --global user.email "seu@email.com"
4. Clone o repositório no seu computador
# Abra o terminal, navegue até onde quer salvar os projetos
cd Documentos # ou qualquer pasta
# Clone o repositório (substitua SEU-USUARIO pelo seu usuário do GitHub)
git clone https://github.com/SEU-USUARIO/html-css-review.git
# Entre na pasta
cd html-css-review
5. Fluxo que você vai repetir todo dia
# APÓS cada sessão de prática (noite):
git status # ver o que mudou
git add . # adicionar todos os arquivos
git commit -m "tipo: o que foi feito" # registrar com mensagem
git push origin main # enviar para o GitHub
6. Tipos de mensagem de commit
| Tipo | Quando usar | Exemplo |
|---|---|---|
study |
Exercícios e anotações de aprendizado | study: estrutura html da pagina |
feat |
Nova funcionalidade ou seção criada | feat: secao de projetos com grid |
style |
CSS, layout, cores, espaçamento | style: flexbox no header |
fix |
Correção de algo que estava errado | fix: alinhamento do menu mobile |
chore |
Setup, configuração, estrutura de pastas | chore: cria estrutura inicial |
7. Estrutura de pastas para esta fase
html-css-review/
├── README.md
├── portfolio/ ← projeto principal (cresce ao longo dos 10 dias)
│ ├── index.html
│ └── style.css
└── exercicios/ ← exercícios diários
├── dia-01/
├── dia-02/
└── ...
O que é HTML?
HTML (HyperText Markup Language) é a linguagem de estrutura da web. Ele descreve o conteúdo e o significado de uma página — títulos, parágrafos, imagens, listas, links. O navegador lê o HTML e exibe o resultado na tela.
Estrutura básica de um documento HTML
Todo arquivo HTML começa com esta estrutura. Salve sempre com extensão .html.
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Minha Página</title>
</head>
<body>
<!-- Todo o conteúdo visível vai aqui -->
<h1>Olá, mundo!</h1>
<p>Meu primeiro parágrafo.</p>
</body>
</html>
Cada parte explicada
<!DOCTYPE html>— diz ao navegador que é HTML5 (versão atual)<html lang="pt-BR">— raiz da página;langajuda leitores de tela e buscadores<head>— configurações invisíveis: charset, viewport, título, link para CSS<meta charset="UTF-8">— garante que acentos e ç funcionem<meta name="viewport">— essencial para o site funcionar bem em celular<title>— texto que aparece na aba do navegador<body>— tudo que o usuário vê fica aqui
Tags semânticas vs <div>
Uma <div> é uma caixa genérica sem significado. Tags semânticas comunicam o
propósito do conteúdo para o navegador, leitores de tela e motores de busca.
<div class="cabecalho">
<div class="navegacao">...</div>
</div>
<div class="conteudo-principal">
<div class="artigo">...</div>
<div class="lateral">...</div>
</div>
<div class="rodape">...</div>
<header>
<nav>...</nav>
</header>
<main>
<article>...</article>
<aside>...</aside>
</main>
<footer>...</footer>
Tags semânticas principais
| Tag | Uso |
|---|---|
<header> |
Cabeçalho da página ou de uma seção |
<nav> |
Menu de navegação |
<main> |
Conteúdo principal (único por página) |
<section> |
Seção temática com título |
<article> |
Conteúdo independente (post, card, produto) |
<aside> |
Conteúdo relacionado mas secundário (sidebar) |
<footer> |
Rodapé da página ou seção |
Tags de texto e conteúdo
<!-- Hierarquia de títulos: use h1 uma vez por página -->
<h1>Título principal da página</h1>
<h2>Seção</h2>
<h3>Subseção</h3>
<!-- Parágrafo -->
<p>Texto comum. <strong>Negrito importante.</strong> <em>Itálico ênfase.</em></p>
<!-- Links -->
<a href="https://github.com">Texto do link</a>
<a href="sobre.html">Link para outra página</a>
<a href="#contato">Link para âncora na mesma página</a>
<!-- Imagem -->
<img src="foto.jpg" alt="Descrição da imagem">
<!-- Listas -->
<ul> <!-- não ordenada -->
<li>Item 1</li>
<li>Item 2</li>
</ul>
<ol> <!-- ordenada (numerada) -->
<li>Primeiro</li>
<li>Segundo</li>
</ol>
Estrutura do projeto portfólio — Dia 1
Esta é a estrutura HTML do portfólio que vamos construir. Hoje criamos o esqueleto. Nos próximos dias vamos adicionar CSS, Flexbox, Grid e muito mais.
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Portfólio | Seu Nome</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<nav>
<a href="#" class="logo">SeuNome</a>
<ul>
<li><a href="#sobre">Sobre</a></li>
<li><a href="#projetos">Projetos</a></li>
<li><a href="#contato">Contato</a></li>
</ul>
</nav>
</header>
<main>
<!-- SEÇÃO HERO -->
<section id="hero">
<h1>Olá, sou <span>Seu Nome</span> 👋</h1>
<p>Desenvolvedor Front-end em formação. Apaixonado por criar experiências web incríveis.</p>
<a href="#projetos" class="btn">Ver meus projetos</a>
</section>
<!-- SEÇÃO SOBRE -->
<section id="sobre">
<h2>Sobre mim</h2>
<p>Escreva aqui um parágrafo sobre você, seus objetivos e o que está estudando.</p>
</section>
<!-- SEÇÃO PROJETOS -->
<section id="projetos">
<h2>Projetos</h2>
<article class="card">
<h3>TaskFlow</h3>
<p>Gerenciador de tarefas em JavaScript puro.</p>
<a href="#">Ver projeto</a>
</article>
<article class="card">
<h3>Busca de CEP</h3>
<p>Consulta de endereços usando a API ViaCEP.</p>
<a href="#">Ver projeto</a>
</article>
<article class="card">
<h3>App de Clima</h3>
<p>Previsão do tempo com dados em tempo real.</p>
<a href="#">Ver projeto</a>
</article>
</section>
<!-- SEÇÃO CONTATO -->
<section id="contato">
<h2>Contato</h2>
<form>
<label for="nome">Nome</label>
<input type="text" id="nome" name="nome" placeholder="Seu nome">
<label for="email">E-mail</label>
<input type="email" id="email" name="email" placeholder="seu@email.com">
<label for="mensagem">Mensagem</label>
<textarea id="mensagem" name="mensagem" rows="5"></textarea>
<button type="submit">Enviar mensagem</button>
</form>
</section>
</main>
<footer>
<p>Feito com 💙 por Seu Nome — <a href="https://github.com/seu-usuario">GitHub</a></p>
</footer>
</body>
</html>
Crie um arquivo exercicios/dia-01/index.html com a estrutura de uma página de
receita culinária usando tags semânticas corretas. Inclua:
- Um
<header>com o nome da receita em<h1> - Um
<main>com dois<section>: ingredientes (lista<ul>) e modo de preparo (lista<ol>) - Um
<footer>com seu nome como autor - Uma imagem com
altdescritivo
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bolo de Chocolate</title>
</head>
<body>
<header>
<h1>Bolo de Chocolate</h1>
<p>Receita clássica e fofinha</p>
</header>
<main>
<section>
<h2>Ingredientes</h2>
<img src="bolo.jpg" alt="Bolo de chocolate com cobertura e fatia cortada">
<ul>
<li>3 ovos</li>
<li>2 xícaras de farinha de trigo</li>
<li>1 xícara de achocolatado</li>
<li>1 xícara de açúcar</li>
<li>1 xícara de leite</li>
<li>1/2 xícara de óleo</li>
<li>1 colher de sopa de fermento</li>
</ul>
</section>
<section>
<h2>Modo de Preparo</h2>
<ol>
<li>Preaqueça o forno a 180°C</li>
<li>Bata os ovos com o açúcar até dobrar de volume</li>
<li>Adicione o leite e o óleo, misture bem</li>
<li>Peneire a farinha e o achocolatado e incorpore à mistura</li>
<li>Adicione o fermento por último, mexendo delicadamente</li>
<li>Despeje em forma untada e asse por 35 minutos</li>
</ol>
</section>
</main>
<footer>
<p>Receita por Seu Nome</p>
</footer>
</body>
</html>
Copie o código do portfólio (seção acima) para o arquivo
portfolio/index.html. Personalize com seu nome, e abra no navegador para ver o
resultado (sem CSS ainda, estará sem estilo — isso é normal!).
Não esqueça de criar também o arquivo portfolio/style.css vazio — vamos
preenchê-lo amanhã.
study: estrutura html semantica do portfolio
git push origin main
O que é CSS?
CSS (Cascading Style Sheets) controla a aparência visual do HTML — cores, fontes, espaçamentos, tamanhos, posicionamento. Sem CSS, toda página seria texto preto em fundo branco.
Como conectar o CSS ao HTML
<!-- Método correto: arquivo externo -->
<link rel="stylesheet" href="style.css">
style="color:red") e a tag
<style> no HTML. Use sempre um arquivo .css separado — é mais
organizado e reutilizável.
Seletores CSS
Um seletor define a quem a regra se aplica. O bloco { } define o
que vai mudar.
/* Seletor de elemento — aplica a TODAS as tags desse tipo */
p { color: gray; }
h1 { font-size: 32px; }
/* Seletor de classe — aplica a qualquer elemento com class="nome" */
.card { background: white; }
.btn { padding: 10px 20px; }
/* Seletor de ID — aplica a UM elemento com id="nome" (use com moderação) */
#hero { background: #0d1117; }
/* Seletor descendente — p dentro de .card */
.card p { color: #666; }
/* Múltiplos seletores — mesma regra para vários */
h1, h2, h3 { font-family: sans-serif; }
Box Model — o modelo de caixa
Todo elemento HTML é uma caixa com 4 camadas:
As 4 camadas (de dentro para fora)
- content — o conteúdo em si (texto, imagem)
- padding — espaço interno entre o conteúdo e a borda
- border — a borda da caixa
- margin — espaço externo entre elementos
.card {
/* padding: dentro da borda */
padding: 20px; /* todos os lados */
padding: 10px 20px; /* vertical horizontal */
padding: 10px 20px 10px 20px; /* top right bottom left */
/* margin: fora da borda */
margin: 0 auto; /* centraliza horizontalmente */
margin-bottom: 16px;
/* border */
border: 1px solid #ccc;
border-radius: 8px; /* arredonda os cantos */
/* width & height */
width: 300px;
max-width: 100%; /* nunca ultrapassa o container pai */
}
* { box-sizing: border-box; } — faz o padding e
border serem incluídos na largura total do elemento, evitando surpresas.Unidades de medida
| Unidade | O que é | Quando usar |
|---|---|---|
px |
Pixels — valor fixo | Bordas, sombras, valores pequenos e precisos |
rem |
Relativo ao tamanho base do documento (padrão: 16px) | Fontes, espaçamentos — escala com acessibilidade |
em |
Relativo ao tamanho do elemento pai | Espaçamentos internos do componente |
% |
Percentual do elemento pai | Larguras fluidas e responsivas |
vh/vw |
Percentual da altura/largura da viewport | Seções full-screen, hero |
Cores
/* Hexadecimal: #RRGGBB ou #RGB */
color: #e34c26;
color: #fff; /* branco */
color: #000; /* preto */
/* RGB e RGBA (a = transparência 0-1) */
color: rgb(30, 30, 30);
color: rgba(0, 0, 0, 0.5); /* 50% transparente */
/* HSL: hue saturation lightness (mais intuitivo para criar paletas) */
color: hsl(220, 80%, 60%);
background: hsl(220, 80%, 10%); /* escurece mantendo o tom */
Tipografia
body {
font-family: 'Segoe UI', system-ui, sans-serif; /* pilha de fontes */
font-size: 16px; /* tamanho base */
line-height: 1.6; /* espaço entre linhas (sem unidade = relativo) */
color: #333;
}
h1 {
font-size: 2.5rem; /* 40px se base = 16px */
font-weight: 700; /* 400=normal, 700=bold */
letter-spacing: -0.5px; /* espaço entre letras */
color: #0d1117;
}
/* Google Fonts: adicione no <head> do HTML */
/* <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet"> */
body { font-family: 'Inter', sans-serif; }
CSS do Portfólio — Dia 2
Adicione este CSS no arquivo portfolio/style.css:
/* ===== RESET & BASE ===== */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Segoe UI', system-ui, sans-serif;
font-size: 16px;
line-height: 1.7;
color: #1a1a2e;
background: #ffffff;
}
/* ===== TIPOGRAFIA ===== */
h1 { font-size: 2.5rem; font-weight: 700; margin-bottom: 1rem; }
h2 { font-size: 1.75rem; font-weight: 600; margin-bottom: 1rem; }
h3 { font-size: 1.25rem; font-weight: 600; margin-bottom: 0.5rem; }
p { color: #555; margin-bottom: 1rem; }
a { color: #264de4; text-decoration: none; }
a:hover { text-decoration: underline; }
/* ===== LAYOUT ===== */
section {
padding: 80px 0;
max-width: 1000px;
margin: 0 auto;
padding-left: 24px;
padding-right: 24px;
}
/* ===== HEADER ===== */
header {
background: #0d1117;
padding: 0 24px;
position: sticky;
top: 0;
z-index: 100;
}
header nav {
max-width: 1000px;
margin: 0 auto;
height: 60px;
display: flex;
align-items: center;
justify-content: space-between;
}
.logo {
font-weight: 700;
font-size: 1.1rem;
color: #ffffff;
text-decoration: none;
}
header nav ul {
list-style: none;
display: flex;
gap: 28px;
}
header nav ul a {
color: #8892a4;
font-size: 0.9rem;
transition: color 0.2s;
}
header nav ul a:hover {
color: #ffffff;
text-decoration: none;
}
/* ===== HERO ===== */
#hero {
background: #0d1117;
color: white;
text-align: center;
padding: 100px 24px;
max-width: 100%;
}
#hero h1 { color: white; font-size: 3rem; }
#hero span { color: #264de4; }
#hero p { color: #8892a4; font-size: 1.1rem; max-width: 500px; margin: 0 auto 2rem; }
/* ===== BOTÃO ===== */
.btn {
display: inline-block;
background: #264de4;
color: white;
padding: 12px 28px;
border-radius: 8px;
font-weight: 600;
text-decoration: none;
transition: background 0.2s;
}
.btn:hover {
background: #1a3ab8;
text-decoration: none;
}
/* ===== CARDS ===== */
.card {
background: #f8f9fa;
border: 1px solid #e9ecef;
border-radius: 12px;
padding: 24px;
margin-bottom: 16px;
}
/* ===== FORMULÁRIO ===== */
form { max-width: 560px; }
label { display: block; font-weight: 600; font-size: 0.875rem; margin-bottom: 6px; margin-top: 16px; }
input, textarea {
width: 100%;
padding: 10px 14px;
border: 1px solid #dee2e6;
border-radius: 8px;
font-size: 1rem;
font-family: inherit;
}
input:focus, textarea:focus {
outline: none;
border-color: #264de4;
box-shadow: 0 0 0 3px rgba(38, 77, 228, 0.15);
}
form button {
margin-top: 20px;
background: #264de4;
color: white;
border: none;
padding: 12px 28px;
border-radius: 8px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
}
/* ===== FOOTER ===== */
footer {
background: #0d1117;
color: #8892a4;
text-align: center;
padding: 32px 24px;
font-size: 0.875rem;
}
footer a { color: #264de4; }
Crie exercicios/dia-02/style.css para estilizar a página da receita do Dia 1.
Use:
box-sizing: border-boxno*- Fonte diferente da padrão com
font-family - Cor de fundo suave e cor de texto adequada
- Padding nas seções para não grudar nas bordas
- Um
max-widthnobodyou em uma classe container - Estilo diferente para o
h1,h2e os itens da lista
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: Georgia, serif;
font-size: 16px;
line-height: 1.7;
color: #2d2d2d;
background: #fdf8f2;
}
.container {
max-width: 700px;
margin: 0 auto;
padding: 0 24px;
}
header {
background: #8b2500;
color: white;
padding: 40px 24px;
text-align: center;
}
h1 {
font-size: 2rem;
margin-bottom: 0.5rem;
color: white;
}
header p { color: rgba(255,255,255,0.8); }
section {
padding: 32px 24px;
max-width: 700px;
margin: 0 auto;
}
h2 {
font-size: 1.4rem;
color: #8b2500;
margin-bottom: 16px;
padding-bottom: 8px;
border-bottom: 2px solid #e9d5c8;
}
ul, ol { padding-left: 20px; }
li {
margin-bottom: 8px;
color: #444;
}
footer {
background: #2d2d2d;
color: #aaa;
text-align: center;
padding: 20px;
font-size: 0.875rem;
}
Cole o CSS do portfólio (código acima) no arquivo portfolio/style.css. Abra o
index.html no navegador e veja a transformação! Personalize as cores principais
se quiser — troque #264de4 por outra cor de sua preferência.
style: css base com tipografia e cores do portfolio
O que é Flexbox?
Flexbox é um sistema de layout CSS que organiza elementos em uma dimensão (linha ou coluna). É perfeito para alinhar itens dentro de um container, criar navbars, centralizar conteúdo e distribuir espaço entre elementos.
display: flex é o
flex container. Os filhos diretos são os flex items.
Propriedades do Container (pai)
.container {
display: flex; /* ativa o flexbox */
/* DIREÇÃO */
flex-direction: row; /* → padrão: em linha */
flex-direction: column; /* ↓ em coluna */
flex-direction: row-reverse; /* ← linha invertida */
/* ALINHAMENTO NO EIXO PRINCIPAL (horizontal se row) */
justify-content: flex-start; /* |●●●_______| */
justify-content: center; /* |____●●●____| */
justify-content: flex-end; /* |_______●●●| */
justify-content: space-between; /* |●___●___●| */
justify-content: space-around; /* |_●__●__●_| */
justify-content: space-evenly; /* |__●__●__●__| */
/* ALINHAMENTO NO EIXO CRUZADO (vertical se row) */
align-items: stretch; /* padrão: estica até a altura do container */
align-items: center; /* centraliza verticalmente */
align-items: flex-start; /* topo */
align-items: flex-end; /* base */
/* QUEBRA DE LINHA */
flex-wrap: nowrap; /* padrão: não quebra */
flex-wrap: wrap; /* quebra para a próxima linha */
/* ESPAÇO ENTRE ITENS */
gap: 16px; /* espaço entre todos os itens */
gap: 16px 24px; /* vertical horizontal */
}
Propriedades do Item (filho)
.item {
/* flex-grow: quanto cresce para ocupar espaço extra */
flex-grow: 0; /* padrão: não cresce */
flex-grow: 1; /* cresce para ocupar espaço disponível */
/* flex-shrink: quanto encolhe se faltar espaço */
flex-shrink: 1; /* padrão: pode encolher */
flex-shrink: 0; /* não encolhe nunca */
/* flex-basis: tamanho inicial antes de crescer/encolher */
flex-basis: 200px;
flex-basis: auto; /* padrão */
/* shorthand: grow shrink basis */
flex: 1; /* atalho para flex: 1 1 0 */
flex: 0 0 200px; /* largura fixa de 200px */
/* alinhamento individual (sobrescreve align-items do pai) */
align-self: center;
}
Padrões mais usados
/* Centralizar algo na tela */
.centralizado {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
/* Navbar com logo à esquerda e menu à direita */
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 24px;
}
/* Itens iguais que dividem o espaço */
.cols {
display: flex;
gap: 16px;
}
.cols .col {
flex: 1; /* todos iguais */
}
/* Sidebar + conteúdo */
.layout {
display: flex;
gap: 24px;
}
.sidebar { flex: 0 0 240px; } /* largura fixa */
.content { flex: 1; } /* ocupa o resto */
Aplicando ao Portfólio — navbar com Flexbox
O CSS do Dia 2 já usa Flexbox no nav. Agora vamos melhorar a seção hero e preparar
os cards:
/* HERO com dois conteúdos lado a lado (texto + imagem futura) */
#hero .hero-content {
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
max-width: 600px;
margin: 0 auto;
}
/* TAGS de tecnologia abaixo do texto do hero */
.tags {
display: flex;
gap: 8px;
flex-wrap: wrap;
justify-content: center;
}
.tag-item {
background: rgba(38, 77, 228, 0.15);
color: #8aabff;
padding: 4px 12px;
border-radius: 99px;
font-size: 0.8rem;
font-weight: 500;
}
/* Atualize o HTML do hero para incluir as tags */
Adicione também no index.html, dentro de #hero, após o botão:
<section id="hero">
<div class="hero-content">
<h1>Olá, sou <span>Seu Nome</span> 👋</h1>
<p>Desenvolvedor Front-end em formação. Apaixonado por criar experiências web incríveis.</p>
<a href="#projetos" class="btn">Ver meus projetos</a>
<div class="tags">
<span class="tag-item">HTML</span>
<span class="tag-item">CSS</span>
<span class="tag-item">JavaScript</span>
<span class="tag-item">React</span>
</div>
</div>
</section>
Crie exercicios/dia-03/index.html com um layout de galeria de
fotos usando Flexbox:
- Um container com
display: flex,flex-wrap: wrapegap: 16px - 6 "fotos" (pode usar cores de fundo no lugar de imagens reais)
- Cada foto com largura de aproximadamente 30% para ficarem 3 por linha
- Altura fixa de 200px cada uma
- Um título centralizado acima da galeria
<!-- index.html -->
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<title>Galeria</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Minha Galeria</h1>
<div class="galeria">
<div class="foto" style="background:#e34c26"></div>
<div class="foto" style="background:#264de4"></div>
<div class="foto" style="background:#f7df1e"></div>
<div class="foto" style="background:#61dafb"></div>
<div class="foto" style="background:#3fb950"></div>
<div class="foto" style="background:#bc8cff"></div>
</div>
</body>
</html>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: sans-serif; padding: 32px; background: #f5f5f5; }
h1 { text-align: center; margin-bottom: 24px; font-size: 1.8rem; }
.galeria {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.foto {
flex: 0 0 calc(33.333% - 11px); /* 3 por linha descontando gap */
height: 200px;
border-radius: 12px;
}
Aplique as mudanças do CSS e HTML do portfólio acima. Depois, abra o Flexbox Froggy e tente completar pelo menos os 12 primeiros níveis — é rápido e fixa bem as propriedades na memória.
style: flexbox no hero e navbar do portfolio
O que é CSS Grid?
CSS Grid é um sistema de layout bidimensional — controla linhas e colunas ao mesmo tempo. Enquanto o Flexbox é ideal para uma linha ou coluna de itens, o Grid é perfeito para layouts de página completos e galerias complexas.
Flexbox vs Grid — quando usar cada um?
- Flexbox: navbar, lista de tags, botões lado a lado, alinhar um item dentro de outro — uma dimensão
- Grid: layout da página, galeria de cards, formulários alinhados — duas dimensões
- Dica: na prática, você usa os dois juntos! Grid para a estrutura geral, Flexbox dentro dos componentes.
Criando colunas e linhas
.grid {
display: grid;
/* COLUNAS */
grid-template-columns: 200px 200px 200px; /* 3 colunas fixas */
grid-template-columns: 1fr 1fr 1fr; /* 3 colunas iguais */
grid-template-columns: repeat(3, 1fr); /* mesmo resultado */
grid-template-columns: 250px 1fr; /* sidebar + conteúdo */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); /* responsivo! */
/* LINHAS */
grid-template-rows: auto; /* padrão: altura do conteúdo */
grid-template-rows: 100px 1fr auto; /* header fixo, main flexível, footer auto */
/* ESPAÇAMENTO */
gap: 24px;
column-gap: 16px;
row-gap: 24px;
}
A unidade fr — fração do espaço disponível
/* Imagine um container de 900px com gap de 24px */
/* Duas colunas iguais: cada uma fica com ~438px */
grid-template-columns: 1fr 1fr;
/* Sidebar + conteúdo: sidebar=250px, conteúdo=626px */
grid-template-columns: 250px 1fr;
/* Três colunas: 1ª pequena, 2ª grande, 3ª média */
grid-template-columns: 1fr 2fr 1fr;
Posicionando itens no grid
/* Um item que ocupa 2 colunas */
.destaque {
grid-column: span 2; /* ocupa 2 colunas */
grid-row: span 2; /* ocupa 2 linhas */
}
/* Posicionamento preciso (linha inicial / linha final) */
.header { grid-column: 1 / 4; } /* da coluna 1 até a 4 (3 colunas) */
.sidebar { grid-column: 1 / 2; } /* apenas coluna 1 */
.main { grid-column: 2 / 4; } /* colunas 2 e 3 */
.footer { grid-column: 1 / -1; } /* -1 = até o final */
Grid Template Areas — layout visual
.pagina {
display: grid;
grid-template-areas:
"header header header"
"sidebar main main"
"footer footer footer";
grid-template-columns: 250px 1fr 1fr;
gap: 16px;
min-height: 100vh;
}
header { grid-area: header; }
aside { grid-area: sidebar; }
main { grid-area: main; }
footer { grid-area: footer; }
Auto-fill + minmax — grid responsivo automático
Essa é uma das técnicas mais poderosas do Grid: colunas que se adaptam automaticamente ao espaço disponível, sem media queries!
.cards {
display: grid;
/* cria quantas colunas couberem, com mínimo 250px e máximo 1fr */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 24px;
}
/* Em tela larga: 3 colunas. Em tablet: 2. No mobile: 1. */
Portfólio — Seção de Projetos com Grid
Substitua o CSS dos cards no style.css:
/* GRID DE PROJETOS */
#projetos .grid-projetos {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 24px;
margin-top: 32px;
}
.card {
background: #ffffff;
border: 1px solid #e9ecef;
border-radius: 12px;
padding: 24px;
transition: transform 0.2s, box-shadow 0.2s;
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.08);
}
.card h3 { margin-bottom: 8px; color: #0d1117; }
.card p { color: #666; font-size: 0.9rem; margin-bottom: 16px; }
.card a {
font-size: 0.85rem;
font-weight: 600;
color: #264de4;
}
/* Card em destaque (ocupa 2 colunas se houver espaço) */
.card.destaque {
grid-column: span 2;
}
Atualize o HTML da seção de projetos para usar a classe grid-projetos:
<section id="projetos">
<h2>Projetos</h2>
<div class="grid-projetos">
<article class="card destaque">
<h3>🗂️ TaskFlow</h3>
<p>Gerenciador de tarefas completo. Desenvolvido em HTML+CSS+JS puro, depois migrado para React e TypeScript.</p>
<a href="#">Ver projeto →</a>
</article>
<article class="card">
<h3>📍 Busca de CEP</h3>
<p>Consulta de endereços usando a API ViaCEP com async/await.</p>
<a href="#">Ver projeto →</a>
</article>
<article class="card">
<h3>🌤️ App de Clima</h3>
<p>Previsão do tempo com geolocalização e dados em tempo real.</p>
<a href="#">Ver projeto →</a>
</article>
</div>
</section>
Recrie a galeria do Dia 3 usando CSS Grid em vez de Flexbox. Depois, adicione um elemento que ocupe 2 colunas (destaque). Compare o resultado com a versão Flexbox — qual ficou mais fácil de controlar?
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: sans-serif; padding: 32px; background: #f5f5f5; }
h1 { text-align: center; margin-bottom: 24px; font-size: 1.8rem; }
.galeria {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
.foto {
height: 200px;
border-radius: 12px;
}
/* Elemento em destaque: ocupa 2 colunas */
.foto.destaque {
grid-column: span 2;
height: 300px;
}
Aplique as mudanças de CSS e HTML acima. Veja como o card "TaskFlow" ocupa duas colunas. Experimente adicionar mais cards e observe como o grid se adapta.
Opcional: acesse cssgridgarden.com e complete alguns níveis para fixar o grid.
style: secao de projetos com css grid
Elementos de formulário
Formulários são como o usuário envia dados para o sistema. Em JavaScript (próxima fase), você vai capturar e processar esses dados. Por enquanto, foco na estrutura e no estilo.
<form action="/enviar" method="POST">
<!-- LABEL sempre vinculado ao input pelo "for" = "id" -->
<label for="nome">Nome completo</label>
<input type="text" id="nome" name="nome" placeholder="Ex: João Silva" required>
<!-- Tipos de input mais comuns -->
<input type="email" name="email" placeholder="seu@email.com">
<input type="password" name="senha" placeholder="Mínimo 8 caracteres">
<input type="number" name="idade" min="18" max="100">
<input type="tel" name="telefone" placeholder="(11) 99999-9999">
<input type="date" name="data">
<input type="url" name="site" placeholder="https://">
<!-- Checkbox e Radio -->
<input type="checkbox" id="aceito" name="aceito">
<label for="aceito">Aceito os termos de uso</label>
<input type="radio" id="js" name="linguagem" value="js">
<label for="js">JavaScript</label>
<input type="radio" id="py" name="linguagem" value="py">
<label for="py">Python</label>
<!-- Select (dropdown) -->
<label for="nivel">Nível</label>
<select id="nivel" name="nivel">
<option value="">Selecione...</option>
<option value="iniciante">Iniciante</option>
<option value="intermediario">Intermediário</option>
<option value="avancado">Avançado</option>
</select>
<!-- Textarea -->
<label for="mensagem">Mensagem</label>
<textarea id="mensagem" name="mensagem" rows="5" placeholder="Escreva aqui..."></textarea>
<!-- Botões -->
<button type="submit">Enviar</button>
<button type="reset">Limpar</button>
<button type="button">Clique (não envia o form)</button>
</form>
Validação nativa do HTML
<!-- required: campo obrigatório -->
<input type="text" required>
<!-- minlength / maxlength: tamanho do texto -->
<input type="password" minlength="8" maxlength="32">
<!-- min / max: para números e datas -->
<input type="number" min="1" max="10">
<!-- pattern: expressão regular para validar formato -->
<input type="text" pattern="[0-9]{5}-[0-9]{3}" placeholder="00000-000">
<!-- O navegador bloqueia o envio se a validação falhar -->
Estilizando formulários
/* Reset de estilos nativos dos inputs */
input, textarea, select, button {
font-family: inherit; /* herda a fonte do corpo */
font-size: 1rem;
}
/* Campo de texto base */
.campo {
width: 100%;
padding: 10px 14px;
border: 1px solid #dee2e6;
border-radius: 8px;
background: #fff;
color: #333;
outline: none;
transition: border-color 0.2s, box-shadow 0.2s;
}
/* Estado de foco — acessibilidade importante! */
.campo:focus {
border-color: #264de4;
box-shadow: 0 0 0 3px rgba(38, 77, 228, 0.15);
}
/* Estado inválido após interação */
.campo:invalid:not(:placeholder-shown) {
border-color: #dc3545;
box-shadow: 0 0 0 3px rgba(220, 53, 69, 0.15);
}
/* Estado válido */
.campo:valid:not(:placeholder-shown) {
border-color: #3fb950;
}
/* Label */
label {
display: block;
font-weight: 600;
font-size: 0.875rem;
color: #333;
margin-bottom: 6px;
}
/* Grupo de campo */
.form-group {
margin-bottom: 20px;
}
/* Select */
select.campo {
cursor: pointer;
appearance: none; /* remove estilo nativo */
background-image: url("data:image/svg+xml,..."); /* seta customizada */
}
Crie um formulário de cadastro de usuário em exercicios/dia-05/
com os campos: nome, e-mail, senha, data de nascimento, linguagem favorita (radio), nível
(select) e um checkbox de termos. Adicione validação nativa e estilize tudo com CSS.
<form>
<div class="form-group">
<label for="nome">Nome completo *</label>
<input class="campo" type="text" id="nome" required minlength="3" placeholder="Seu nome">
</div>
<div class="form-group">
<label for="email">E-mail *</label>
<input class="campo" type="email" id="email" required placeholder="seu@email.com">
</div>
<div class="form-group">
<label for="senha">Senha *</label>
<input class="campo" type="password" id="senha" required minlength="8">
</div>
<div class="form-group">
<label for="nascimento">Data de nascimento</label>
<input class="campo" type="date" id="nascimento">
</div>
<div class="form-group">
<label>Linguagem favorita</label>
<div class="radio-group">
<label><input type="radio" name="lang" value="js"> JavaScript</label>
<label><input type="radio" name="lang" value="py"> Python</label>
<label><input type="radio" name="lang" value="ts"> TypeScript</label>
</div>
</div>
<div class="form-group">
<label for="nivel">Nível atual</label>
<select class="campo" id="nivel">
<option value="">Selecione...</option>
<option>Iniciante</option>
<option>Intermediário</option>
<option>Avançado</option>
</select>
</div>
<div class="form-group">
<label style="flex-direction:row;gap:8px;display:flex;align-items:center;font-weight:400">
<input type="checkbox" required> Aceito os termos de uso
</label>
</div>
<button type="submit" class="btn">Criar conta</button>
</form>
O formulário de contato já está no HTML desde o Dia 1. Hoje, aplique os estilos CSS da seção
de formulários para deixá-lo bonito e com estados de foco visíveis. Adicione também o
atributo required nos campos de nome, e-mail e mensagem.
feat: formulario de contato estilizado com validacao
O que é design responsivo?
Um site responsivo adapta seu layout para funcionar bem em qualquer tamanho de tela — do celular ao monitor ultrawide. Em 2024, mais de 60% do tráfego web vem de dispositivos móveis.
1. Viewport meta tag — obrigatório
Sem isso, o navegador mobile simula uma tela desktop e o site fica minúsculo. Já está no nosso HTML desde o Dia 1.
<meta name="viewport" content="width=device-width, initial-scale=1.0">
2. Media Queries
Media queries aplicam estilos CSS condicionalmente, dependendo do tamanho da tela.
/* Aplica quando a tela tem ATÉ 768px de largura */
@media (max-width: 768px) {
.nav-menu { display: none; }
h1 { font-size: 1.8rem; }
}
/* Aplica quando a tela tem PELO MENOS 768px */
@media (min-width: 768px) {
.container { padding: 0 48px; }
}
/* Aplica ENTRE dois tamanhos */
@media (min-width: 480px) and (max-width: 768px) {
.grid { grid-template-columns: repeat(2, 1fr); }
}
3. Breakpoints comuns
| Nome | Tamanho | Dispositivos |
|---|---|---|
| Mobile | até 480px | Smartphones pequenos |
| Mobile L | até 768px | Smartphones grandes |
| Tablet | 769px – 1024px | Tablets, iPad |
| Desktop | 1025px – 1280px | Notebooks |
| Wide | 1281px+ | Monitores grandes |
4. Mobile-first — a abordagem correta
Escreva o CSS base para mobile e use min-width para adicionar estilos em telas
maiores. É mais fácil escalar para cima do que comprimir para baixo.
/* BASE: mobile (sem media query) */
.grid-projetos {
display: grid;
grid-template-columns: 1fr; /* 1 coluna no mobile */
gap: 16px;
}
/* TABLET: 2 colunas */
@media (min-width: 640px) {
.grid-projetos {
grid-template-columns: repeat(2, 1fr);
}
}
/* DESKTOP: 3 colunas */
@media (min-width: 1024px) {
.grid-projetos {
grid-template-columns: repeat(3, 1fr);
}
}
5. Imagens responsivas
/* Nunca ultrapassa o container pai */
img {
max-width: 100%;
height: auto; /* mantém proporção */
display: block;
}
Portfólio — Tornando responsivo
Adicione ao final do style.css:
/* ===== RESPONSIVIDADE ===== */
@media (max-width: 768px) {
/* Título hero menor */
#hero h1 { font-size: 2rem; }
#hero p { font-size: 1rem; }
/* Grid de projetos: 1 coluna */
#projetos .grid-projetos {
grid-template-columns: 1fr;
}
/* Card destaque: sem span no mobile */
.card.destaque {
grid-column: span 1;
}
/* Seções com menos padding */
section {
padding: 48px 16px;
}
/* Navbar: ocultar links (voltaremos com JS depois) */
header nav ul {
display: none;
}
}
F12 → clique no ícone de dispositivo móvel (ou Ctrl+Shift+M). Você
pode simular diferentes tamanhos de tela.
Pegue o exercício da galeria (Dia 3 ou 4) e torne-a responsiva sem usar auto-fill — use media queries manualmente:
- Mobile: 1 coluna
- Tablet (≥ 480px): 2 colunas
- Desktop (≥ 768px): 3 colunas
.galeria {
display: grid;
grid-template-columns: 1fr; /* mobile: 1 coluna */
gap: 16px;
}
@media (min-width: 480px) {
.galeria {
grid-template-columns: repeat(2, 1fr); /* tablet: 2 */
}
}
@media (min-width: 768px) {
.galeria {
grid-template-columns: repeat(3, 1fr); /* desktop: 3 */
}
}
Aplique as media queries ao portfólio. Teste no DevTools (F12) em diferentes tamanhos: 375px (iPhone), 768px (iPad), 1280px (desktop). Corrija qualquer coisa que esteja estranha no mobile.
style: responsividade mobile no portfolio
Variáveis CSS (Custom Properties)
Variáveis CSS permitem armazenar valores (cores, tamanhos, fontes) em um lugar e reutilizá-los em todo o código. Trocar uma cor do tema fica trivial.
/* Declaração: sempre no :root para acesso global */
:root {
/* Paleta */
--cor-primaria: #264de4;
--cor-primaria-hover: #1a3ab8;
--cor-fundo: #0d1117;
--cor-texto: #e6edf3;
--cor-texto-suave: #8892a4;
/* Tipografia */
--fonte-base: 'Segoe UI', system-ui, sans-serif;
--tamanho-base: 16px;
/* Espaçamento */
--espacamento-sm: 8px;
--espacamento-md: 16px;
--espacamento-lg: 32px;
/* Borda */
--radius: 8px;
--borda: 1px solid rgba(255,255,255,0.08);
}
/* Uso: var(--nome-da-variavel) */
body {
font-family: var(--fonte-base);
color: var(--cor-texto);
background: var(--cor-fundo);
}
.btn {
background: var(--cor-primaria);
border-radius: var(--radius);
padding: var(--espacamento-sm) var(--espacamento-lg);
}
.btn:hover {
background: var(--cor-primaria-hover);
}
/* Dark/Light mode com variáveis */
[data-tema="claro"] {
--cor-fundo: #ffffff;
--cor-texto: #1a1a2e;
}
Pseudo-classes
Pseudo-classes selecionam elementos em estados específicos ou posições na estrutura.
/* Estados de interação */
a:hover { color: blue; } /* mouse em cima */
a:visited { color: purple; } /* link já visitado */
a:active { color: red; } /* clicando agora */
input:focus { border-color: blue; } /* elemento focado */
input:disabled { opacity: 0.5; } /* campo desabilitado */
/* Posição na estrutura */
li:first-child { font-weight: bold; } /* primeiro filho */
li:last-child { border-bottom: none; } /* último filho */
li:nth-child(2) { color: red; } /* segundo filho */
li:nth-child(odd) { background: #f5f5f5; } /* filhos ímpares */
li:nth-child(even) { background: #fff; } /* filhos pares */
li:nth-child(3n) { color: blue; } /* a cada 3 filhos */
/* Estado de formulário */
input:valid { border-color: green; }
input:invalid { border-color: red; }
input:required::after { content: " *"; color: red; }
/* Elemento sem filhos */
p:empty { display: none; }
/* Negação */
li:not(:last-child) { border-bottom: 1px solid #eee; }
Pseudo-elementos
Pseudo-elementos criam elementos virtuais no DOM — úteis para decorações sem poluir o HTML.
/* ::before e ::after: inserem conteúdo antes/depois do elemento */
/* Sempre precisam de "content" (pode ser vazio "") */
/* Ícone de asterisco em campos obrigatórios */
label.obrigatorio::after {
content: " *";
color: red;
}
/* Linha decorativa abaixo do título */
h2 {
position: relative;
padding-bottom: 12px;
}
h2::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
width: 48px;
height: 3px;
background: var(--cor-primaria);
border-radius: 99px;
}
/* Seta decorativa em cards */
.card::before {
content: "→";
position: absolute;
top: 20px;
right: 20px;
color: var(--cor-primaria);
opacity: 0;
transition: opacity 0.2s;
}
.card:hover::before { opacity: 1; }
/* Selecionar texto */
::selection {
background: rgba(38, 77, 228, 0.3);
color: white;
}
Portfólio — Variáveis e efeitos hover
Refatore o início do style.css para usar variáveis CSS:
:root {
--primaria: #264de4;
--primaria-hover: #1a3ab8;
--fundo-escuro: #0d1117;
--fundo-card: #ffffff;
--texto: #1a1a2e;
--texto-suave: #666;
--borda: #e9ecef;
--radius: 12px;
--sombra: 0 8px 30px rgba(0,0,0,0.08);
}
/* Linha decorativa nos h2 */
h2 {
position: relative;
padding-bottom: 14px;
margin-bottom: 32px;
}
h2::after {
content: "";
position: absolute;
bottom: 0; left: 0;
width: 40px; height: 3px;
background: var(--primaria);
border-radius: 99px;
}
/* Hover nos cards */
.card {
position: relative;
overflow: hidden;
}
.card::before {
content: "";
position: absolute;
top: 0; left: 0;
width: 3px; height: 100%;
background: var(--primaria);
transform: scaleY(0);
transform-origin: bottom;
transition: transform 0.25s ease;
}
.card:hover::before { transform: scaleY(1); }
Crie uma lista de 10 itens de menu de restaurante estilizando com pseudo-classes e pseudo-elementos:
- Alternar cor de fundo nos itens pares/ímpares (
:nth-child) - Negrito no primeiro e último item
- Remover borda do último item com
:not(:last-child) - Adicionar um emoji "🍽️" antes de cada item com
::before - Efeito hover que muda a cor de fundo e move o item 4px para a direita
:root { --primaria: #264de4; }
.menu { list-style: none; max-width: 400px; border: 1px solid #eee; border-radius: 12px; overflow: hidden; }
.menu li {
position: relative;
padding: 14px 14px 14px 40px;
border-bottom: 1px solid #eee;
cursor: pointer;
transition: background 0.2s, transform 0.2s;
}
.menu li::before {
content: "🍽️";
position: absolute;
left: 12px;
}
.menu li:nth-child(even) { background: #f9f9f9; }
.menu li:first-child, .menu li:last-child { font-weight: 700; }
.menu li:not(:last-child) { border-bottom: 1px solid #eee; }
.menu li:last-child { border-bottom: none; }
.menu li:hover { background: rgba(38,77,228,.08); transform: translateX(4px); }
Aplique a refatoração com variáveis CSS e adicione os pseudo-elementos nos h2 e
nos cards. Lembre-se de substituir as cores hardcoded por var(--primaria) em
todo o arquivo.
style: variaveis css e pseudo-elementos no portfolio
transition — animações de estado
A propriedade transition anima a mudança de um valor CSS para outro (por exemplo, ao
passar o mouse).
.btn {
background: #264de4;
/* transition: propriedade duração timing-function delay */
transition: background 0.2s ease;
/* Múltiplas propriedades */
transition: background 0.2s ease, transform 0.2s ease, box-shadow 0.3s ease;
/* Atalho para animar tudo (cuidado: pode ser lento) */
transition: all 0.2s ease;
}
.btn:hover {
background: #1a3ab8;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(38, 77, 228, 0.4);
}
/* Timing functions */
transition: color 0.3s ease; /* suave (padrão) */
transition: color 0.3s ease-in; /* começa devagar */
transition: color 0.3s ease-out; /* termina devagar */
transition: color 0.3s ease-in-out; /* começa e termina devagar */
transition: color 0.3s linear; /* velocidade constante */
transition: color 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); /* personalizado (bounce) */
Propriedades mais animadas
| Propriedade | Para que serve |
|---|---|
opacity |
Aparecer/desaparecer (0 = invisível, 1 = visível) |
transform |
Mover, girar, escalar sem afetar o layout |
background-color |
Mudança de cor de fundo |
color |
Mudança de cor de texto |
box-shadow |
Sombra aparecendo/mudando |
border-color |
Borda mudando de cor |
transform — movimentar sem quebrar o layout
.elemento {
/* Mover */
transform: translateX(20px); /* horizontal */
transform: translateY(-10px); /* vertical (negativo = para cima) */
transform: translate(10px, -5px); /* ambos */
/* Escalar */
transform: scale(1.1); /* 10% maior */
transform: scale(0.95); /* 5% menor */
transform: scaleX(1.5); /* só horizontal */
/* Girar */
transform: rotate(45deg); /* 45 graus horário */
transform: rotate(-90deg); /* 90 graus anti-horário */
/* Inclinar */
transform: skewX(10deg);
/* Combinar (ordem importa!) */
transform: translateY(-4px) scale(1.02);
}
@keyframes — animações completas
Para animações mais complexas que não dependem de interação do usuário.
/* Definindo a animação */
@keyframes aparecer {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes pulsar {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
@keyframes girar {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
/* Aplicando a animação */
.hero-title {
/* animation: nome duração timing delay repetições direção */
animation: aparecer 0.6s ease-out forwards;
}
.loader {
animation: girar 1s linear infinite;
}
.badge {
animation: pulsar 2s ease-in-out infinite;
}
Spinner em CSS puro — mini projeto
<div class="spinner"></div>
@keyframes spin {
to { transform: rotate(360deg); }
}
.spinner {
width: 40px;
height: 40px;
border: 3px solid rgba(38, 77, 228, 0.2);
border-top-color: #264de4;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
Portfólio — Animações de entrada
/* Animação de entrada para o hero */
@keyframes fadeUp {
from { opacity: 0; transform: translateY(30px); }
to { opacity: 1; transform: translateY(0); }
}
#hero h1 {
animation: fadeUp 0.7s ease-out forwards;
}
#hero p {
animation: fadeUp 0.7s 0.15s ease-out both;
}
#hero .btn {
animation: fadeUp 0.7s 0.3s ease-out both;
}
#hero .tags {
animation: fadeUp 0.7s 0.45s ease-out both;
}
/* Respeitar preferência do usuário por menos movimento */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
Crie uma página com um botão e um card que demonstra 4 tipos de animação:
- Botão com
transitionde cor e sombra no hover - Card com
transform: translateYno hover - Um spinner com
@keyframes - Um elemento que aparece com animação de fade-in ao carregar a página
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes spin {
to { transform: rotate(360deg); }
}
body { font-family: sans-serif; padding: 40px; background: #f5f5f5; display: flex; flex-direction: column; gap: 24px; align-items: flex-start; }
.btn {
padding: 12px 28px; background: #264de4; color: white; border: none;
border-radius: 8px; font-size: 1rem; font-weight: 600; cursor: pointer;
transition: background 0.2s, transform 0.2s, box-shadow 0.2s;
}
.btn:hover {
background: #1a3ab8; transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(38,77,228,0.4);
}
.card {
background: white; border: 1px solid #e9ecef; border-radius: 12px;
padding: 24px; width: 280px;
transition: transform 0.25s ease, box-shadow 0.25s ease;
animation: fadeIn 0.8s ease-out forwards;
}
.card:hover { transform: translateY(-6px); box-shadow: 0 12px 32px rgba(0,0,0,0.1); }
.spinner {
width: 40px; height: 40px; border-radius: 50%;
border: 3px solid rgba(38,77,228,0.2);
border-top-color: #264de4;
animation: spin 0.8s linear infinite;
}
Aplique as animações de fadeUp no hero. Recarregue a página e observe o efeito cascata nos elementos do hero aparecendo com delays diferentes. Adicione também transições suaves nos links da navegação.
style: transicoes e animacoes de entrada no portfolio
Como position funciona
A propriedade position define como um elemento é posicionado no documento. É
fundamental para menus dropdown, modais, tooltips, cabeçalhos fixos e overlays.
static — o padrão
/* static é o padrão de todos os elementos */
/* top, right, bottom, left e z-index NÃO funcionam com static */
.elemento { position: static; }
relative — relativo a si mesmo
.caixa {
position: relative;
top: 10px; /* move 10px para baixo DO LUGAR ORIGINAL */
left: 20px; /* move 20px para a direita DO LUGAR ORIGINAL */
/* O espaço original é preservado no layout */
}
/* Uso mais importante: criar um "âncora" para filhos absolute */
.container {
position: relative; /* filho absolute se posicionará em relação a este */
}
absolute — relativo ao pai com position
/* O elemento sai do fluxo normal — não ocupa espaço */
/* Se posiciona em relação ao pai mais próximo com position != static */
.card {
position: relative; /* âncora para filhos */
}
.card .badge {
position: absolute;
top: 12px;
right: 12px;
/* Agora "12px do topo do card" e "12px da direita do card" */
}
fixed — relativo à viewport
/* Fica fixo na tela mesmo ao rolar a página */
header {
position: fixed;
top: 0;
left: 0;
width: 100%; /* obrigatório: ocupa a largura total */
z-index: 100; /* fica acima de outros elementos */
}
/* Botão de "voltar ao topo" */
.btn-top {
position: fixed;
bottom: 24px;
right: 24px;
}
sticky — híbrido de relative e fixed
/* Funciona como relative ATÉ chegar no threshold,
depois funciona como fixed dentro do container pai */
.menu-categoria {
position: sticky;
top: 60px; /* gruda a 60px do topo quando chegar lá */
}
/* Muito usado em: headers de tabela, sidebars, menus de seção */
z-index — controle de camadas
/* Só funciona em elementos com position != static */
/* Maior número = mais na frente */
.overlay { position: fixed; z-index: 400; }
.modal { position: fixed; z-index: 500; }
.tooltip { position: absolute; z-index: 600; }
/* Convenção de z-index por camadas */
:root {
--z-base: 0;
--z-elevado: 10;
--z-sticky: 100;
--z-header: 200;
--z-overlay: 400;
--z-modal: 500;
--z-toast: 700;
}
Dropdown com position — mini projeto
<nav>
<div class="menu-item">
Projetos ▾
<ul class="dropdown">
<li><a href="#">TaskFlow</a></li>
<li><a href="#">Busca de CEP</a></li>
<li><a href="#">App de Clima</a></li>
</ul>
</div>
</nav>
.menu-item {
position: relative;
cursor: pointer;
padding: 8px 16px;
}
.dropdown {
position: absolute;
top: 100%; /* logo abaixo do pai */
left: 0;
background: white;
border: 1px solid #eee;
border-radius: 8px;
box-shadow: 0 8px 24px rgba(0,0,0,0.12);
list-style: none;
min-width: 180px;
opacity: 0;
visibility: hidden;
transform: translateY(-8px);
transition: opacity 0.2s, transform 0.2s, visibility 0.2s;
z-index: 200;
}
/* Mostrar ao hover */
.menu-item:hover .dropdown {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.dropdown li a {
display: block;
padding: 10px 16px;
color: #333;
text-decoration: none;
transition: background 0.15s;
}
.dropdown li a:hover { background: #f5f5f5; }
Crie um card de produto com:
- Um badge "NOVO" no canto superior direito com
position: absolute - Um overlay de hover que escurece a imagem com
position: absoluteeopacity - Um botão "Ver mais" que aparece sobre o overlay ao hover
.card-produto {
position: relative;
width: 260px;
border-radius: 12px;
overflow: hidden;
cursor: pointer;
}
.card-imagem {
width: 100%; height: 200px;
background: linear-gradient(135deg, #264de4, #61dafb);
}
.badge-novo {
position: absolute; top: 12px; right: 12px;
background: #f0883e; color: white;
font-size: 11px; font-weight: 700; padding: 4px 10px;
border-radius: 99px;
}
.overlay {
position: absolute; inset: 0; /* shorthand para top right bottom left */
background: rgba(0,0,0,0.5);
display: flex; align-items: center; justify-content: center;
opacity: 0; transition: opacity 0.25s;
}
.card-produto:hover .overlay { opacity: 1; }
.btn-overlay {
background: white; color: #333;
padding: 10px 20px; border-radius: 8px;
font-weight: 600; font-size: 14px;
transform: translateY(10px);
transition: transform 0.25s;
}
.card-produto:hover .btn-overlay { transform: translateY(0); }
Adicione o menu dropdown de projetos na navbar do portfólio. O header já tem
position: sticky do CSS do Dia 2. Adicione o dropdown de projetos usando o
código acima, adaptando os links para as seções do portfólio.
feat: dropdown de projetos na navbar com css position
Revisão geral — checklist técnico
Antes de publicar, revise o portfólio com este checklist:
Publicando no GitHub Pages
GitHub Pages permite hospedar sites estáticos gratuitamente diretamente de um repositório.
Passo a passo
- Certifique-se que seu código está atualizado no GitHub
(
git push origin main) - Acesse seu repositório html-css-review no GitHub
- Clique em Settings (aba no topo)
- No menu lateral, clique em Pages
- Em "Source", selecione main e a pasta /root
- Clique em Save
- Aguarde 2–5 minutos e acesse:
https://SEU-USUARIO.github.io/html-css-review/portfolio/
README do repositório
Um bom README faz diferença. Atualize o README.md com este modelo:
# HTML & CSS Review — DevTrail Fase 0
Revisão e prática de HTML e CSS como parte da minha trilha de desenvolvimento front-end.
## 🔗 Demo ao vivo
[Ver portfólio no GitHub Pages](https://SEU-USUARIO.github.io/html-css-review/portfolio/)
## 📁 Estrutura
- `portfolio/` — Página de portfólio pessoal (projeto principal da fase)
- `exercicios/` — Exercícios diários de HTML e CSS
## 📚 O que aprendi nesta fase
- HTML5 semântico e acessibilidade
- CSS: seletores, box model, tipografia
- Flexbox e CSS Grid
- Design responsivo com media queries
- Variáveis CSS, pseudo-classes e pseudo-elementos
- Transições e animações CSS
- Position e z-index
- Deploy com GitHub Pages
## 🛠️ Tecnologias
HTML5 · CSS3 · Git · GitHub Pages
feat: portfolio finalizado e publicado no github pages
Evolução dia a dia
| Dia | O que foi adicionado ao portfólio |
|---|---|
| Dia 1 | Estrutura HTML semântica completa (header, main, footer, seções) |
| Dia 2 | CSS base: tipografia, cores, box model, botão, header dark |
| Dia 3 | Flexbox no hero: tags empilhadas, navbar alinhada |
| Dia 4 | Grid na seção de projetos com card em destaque |
| Dia 5 | Formulário de contato estilizado com validação nativa |
| Dia 6 | Responsividade completa testada em mobile, tablet e desktop |
| Dia 7 | Variáveis CSS, linha decorativa nos h2, efeito hover nos cards |
| Dia 8 | Animações de entrada no hero (fadeUp com delays) |
| Dia 9 | Dropdown de projetos na navbar |
| Dia 10 | Revisão, polimento final e deploy no GitHub Pages |