HTML & CSS
Guia de Estudo

// Rocketseat Fullstack · Nível 3 · v3.0 — material completo ✅

HTML CSS Positions Seletores Flexbox Grid
01

Tags & Anatomia

// como o HTML é estruturado

Anatomia de um elemento HTML
<h1 id="titulo">Olá Mundo</h1>

// tag de abertura → <h1>
// atributo → id="titulo"
// conteúdo → Olá Mundo
// tag de fechamento → </h1>
// elemento = tudo isso junto
Tags vazias, comentários e caracteres reservados
<!-- comentário -->

<img src="" alt=""> ← sem conteúdo
<br/>

&lt; → <   &gt; → >   &amp; → &
&nbsp; → espaço   <br/> → quebra linha
Tags visuais vs Tags semânticas — qual a diferença?
APENAS VISUAIS — sem significado
<b>negrito visual — não diz que é importante
<i>itálico visual — não diz que é ênfase
<u>sublinhado — sem significado extra
<s>riscado — só visual, sem semântica
<sup> → sobrescrito: x2 · emc²
<sub> → subscrito: H2O · CO2
SEMÂNTICAS — comunicam significado
<strong>importância — leitores de tela enfatizam
<em>ênfase — entonação diferente para leitores
<del>removido — conteúdo deletado semanticamente
<ins>inserido — conteúdo adicionado semanticamente
<mark>destacado — relevante no contexto
<abbr> → abreviação com title explicativo
💡 Regra prática: prefira sempre as tags semânticas. Use <strong> no lugar de <b>, e <em> no lugar de <i>. As tags visuais puras (<b>, <i>, <u>) existem mas não transmitem nenhuma informação para buscadores ou tecnologias assistivas. Reserve <sup> e <sub> para contextos matemáticos e científicos onde o posicionamento tem significado real.
Fluxo HTML — block vs inline
BLOCK — ocupa todo o bloco, empurra próximo pra baixo

<p> texto 1 </p>

<p> texto 2 </p>

div, p, h1–h6, header, section, main...
INLINE — fica na mesma linha que os outros
link 1 link 2 link 3
a, span, em, strong, img...
02

Atributos Globais

// funcionam em qualquer elemento HTML

AtributoUsoExemplo
idIdentificador único — só pode existir uma vez na página<div id="menu">
classAgrupa elementos — vários elementos podem ter a mesma classe<div class="card">
styleCSS inline diretamente no elemento (evite no dia a dia)<p style="color:red">
titleTooltip ao passar o mouse<img title="Logo">
hiddenEsconde o elemento (como display:none)<div hidden>
data-*Atributos personalizados para armazenar dados<div data-id="42">
langDefine o idioma do conteúdo<html lang="pt-BR">
tabindexControla a ordem de foco com Tab<div tabindex="0">
💡 id vs class: Use id quando o elemento é único na página (âncora, JS). Use class quando vai repetir o estilo em vários elementos.
03

Elementos Semânticos

// tags com significado para o navegador e buscadores

Estrutura semântica de uma página
<header> ← cabeçalho da página ou seção
<nav> ← menu de navegação
<main> ← conteúdo principal (único)
  <section> ← seção temática
  <article> ← conteúdo autossuficiente
  <aside> ← conteúdo lateral/relacionado
<footer> ← rodapé
Por que semântica?
→ Acessibilidade (leitores de tela)
→ SEO (buscadores entendem o conteúdo)
→ Código mais legível e manutenível

div e span não têm significado semântico.
Use quando não houver tag específica.
Tags de texto semânticas
<h1> → h6 ← hierarquia de títulos
<p> ← parágrafo
<strong> ← importância (negrito semântico)
<em> ← ênfase (itálico semântico)
<blockquote> ← citação longa
<time> ← data/hora
<mark> ← texto destacado/marcado
Tags de lista e mídia
<ul> / <ol> / <li>
// listas não-ordenada, ordenada, item

<figure> + <figcaption>
// imagem + legenda semântica

<details> + <summary>
// accordion nativo sem JS
04

Estrutura & Caminhos

// anatomia do documento e como referenciar arquivos

Estrutura base de um documento HTML
<!DOCTYPE html> ← define HTML5
<html lang="pt-BR">
<head> ← não aparece na página
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width">
  <title>Nome da Aba</title>
  <link rel="stylesheet" href="style.css">
</head>
<body> ← o que aparece na tela
  ...
</body>
</html>
Tipos de caminho para src e href
// Absoluto — URL completa
https://site.com/img/logo.png

// Relativo — parte da pasta atual
./img/logo.png ← mesma pasta
../img/logo.png ← pasta acima
img/logo.png ← relativo ao index

// Raiz — parte do root do domínio
/img/logo.png
Elementos do <head> — o que cada um faz
TagO que faz
<meta charset>Define a codificação (UTF-8 garante acentos e emojis)
<meta viewport>Essencial para responsividade em mobile
<title>Texto da aba do navegador e resultado em buscadores
<link rel="stylesheet">Conecta o arquivo CSS externo
<meta name="description">Descrição exibida no Google (SEO)
<link rel="icon">O favicon (ícone da aba)
05

Anatomia & Cascata

// como o CSS é escrito e qual regra vence

Anatomia de uma regra CSS
h1 { ← seletor
  color: red; ← propriedade: valor
  font-size: 24px;
} ← declaração

// seletor = quem recebe o estilo
// propriedade = o que muda
// valor = como muda
Formas de aplicar CSS
// 1. Externo (recomendado)
<link rel="stylesheet" href="style.css">

// 2. Interno (no <head>)
<style> h1 { color: red; } </style>

// 3. Inline (evite — alta especificidade)
<h1 style="color:red">
⭐ Cascata — qual regra vence quando há conflito
1. Importância
  !important sempre vence (use raramente)
2. Especificidade
  inline > #id > .class > tag
3. Ordem de aparição
  a última regra declarada vence
/* especificidade crescente */
p { color: gray; } ← (0,0,1)
.texto { color: blue; } ← (0,1,0)
#titulo { color: red; } ← (1,0,0)
/* o #id vence, cor = red */
06

Seletores & Combinators

// como mirar em elementos específicos

Seletores básicos
*universal — seleciona tudo
h1tipo — pelo nome da tag
.classeclasse — por atributo class
#idid — por atributo id (único)
a, plista — seleciona ambos
Combinators
div pdescendente — qualquer <p> dentro de <div>
div > pfilho direto — só <p> diretamente filho
h2 + padjacente — <p> logo após <h2> (mesmo nível)
Exemplo visual dos combinators
article p → descendente
article
  div
    p ← selecionado
span, mark → lista
span ← selecionado
p
mark ← selecionado
h2 + p → adjacente
h2
p ← selecionado
p ← não
06.2

Seletores especiais — ( ) vs [ ]

// pseudo-classes funcionais vs seletores de atributo

Os três formatos e quando cada um aparece
:pseudo-class
a:hover
input:focus
li:first-child
p:last-child
Seleciona pelo estado ou posição. Dois pontos simples : antes do nome.
:funcional( ) — com parênteses
:not(.ativo)
:has(input:checked)
:nth-child(2n+1)
:is(h1, h2, h3)
Pseudo-classes que recebem um argumento. Os () contêm um seletor ou expressão que o CSS avalia.
[ ] — seletor de atributo
[type="checkbox"]
[disabled]
[href^="https"]
input[required]
Seleciona pelo atributo HTML. Os [] contêm o nome do atributo e opcionalmente o valor.
Seletor de atributo [ ] — variações
SintaxeSeleciona
[attr]Elemento que tem o atributo, qualquer valor
[attr="val"]Atributo igual exatamente a "val"
[attr^="val"]Atributo que começa com "val"
[attr$="val"]Atributo que termina com "val"
[attr*="val"]Atributo que contém "val" em qualquer posição
Combinando os três — exemplo real
/* input de senha com foco */
input[type="password"]:focus { border-color: cyan; }

/* card que contém checkbox marcado */
.card:has(input[type="checkbox"]:checked) {
  background: rgba(0,255,0,0.1);
}

/* links externos */
a[href^="http"]:not([href*="meusite.com"]) {
  color: orange;
}
💡 Resumo mental: use : para estados e posições, () quando a pseudo-class precisa de um argumento, e [] quando quer selecionar pelo atributo HTML.
06.3

&.classe vs & .classe — o espaço que muda tudo

// modificar o próprio elemento vs selecionar um filho

Visualizando a diferença
SEM espaço — &.btn-primary
.btn {
  &.btn-primary { background: blue; }
}

/* compila para: .btn.btn-primary */
/* elemento com as DUAS classes */
/* ✅ funciona */
<button class="btn btn-primary">

/* ❌ não funciona */
<div class="btn">
  <span class="btn-primary">
COM espaço — & .btn-primary
.btn {
  & .btn-primary { background: blue; }
}

/* compila para: .btn .btn-primary */
/* .btn-primary DENTRO de .btn */
/* ✅ funciona */
<div class="btn">
  <span class="btn-primary">

/* ❌ não funciona */
<button class="btn btn-primary">
Quando usar cada um no dia a dia
SEM espaço — variações e estados do componente
.btn {
  &.primary { background: blue; }
  &.danger { background: red; }
  &.large { padding: 12px 24px; }
  &:hover { opacity: 0.8; }
  &:disabled { opacity: 0.4; }
}
COM espaço — estilizando filhos
.card {
  & h2 { font-size: 1.4rem; }
  & p { color: gray; }
  & .badge { color: cyan; }
  & img { width: 100%; }
}
💡 Regra simples:
&.classe → "o próprio elemento COM essa classe" — use para variações e estados
& .classe → "elemento com essa classe DENTRO de mim" — use para filhos e descendentes
06.5

CSS Nesting

// seletores filhos dentro do pai — sem repetição, sem pré-processador

Antes — CSS clássico repetitivo
.card { background: #111; }
.card h2 { color: white; }
.card p { color: gray; }
.card:hover { background: #222; }
.card .badge { color: red; }

/* .card repetido em todo lugar 😩 */
Agora — com CSS Nesting
.card {
  background: #111;

  h2 { color: white; }
  p { color: gray; }

  &:hover { background: #222; }
  .badge { color: red; }
}

/* tudo agrupado, sem repetir .card ✅ */
O & — representa o seletor pai
COM & — modifica o próprio elemento
.btn {
  &:hover { } /* .btn:hover */
  &::after { } /* .btn::after */
  &.ativo { } /* .btn.ativo */
  &.large { } /* .btn.large */
  & + & { } /* .btn + .btn */
}
SEM & — seleciona descendente (filho)
.btn {
  :hover { } /* filho em hover */
  .ativo { } /* .btn .ativo (filho) */
  span { } /* span dentro de .btn */
}

/* sem & = descendente — quase sempre
   o que você NÃO quer ao modificar */
Nesting com media queries
.hero {
  font-size: 3rem;
  padding: 80px;

  @media (max-width: 768px) {
    font-size: 1.8rem;
    padding: 40px;
  }
}

/* responsivo dentro do próprio componente */
Nesting profundo — com moderação
.nav {
  ul {
    li {
      a {
        color: white;
        &:hover { color: cyan; }
      }
    }
  }
}

/* funciona — mas evite mais de 3 níveis */
⚡ Exemplo real — componente completo com nesting
.card {
  background: #181818;
  border-radius: 12px;
  padding: 24px;
  transition: transform 0.2s;

  h2 { font-size: 1.4rem; color: white; }
  p { color: #999; line-height: 1.7; }

  &:hover { transform: translateY(-4px); }

  &.destaque {
    border: 2px solid cyan;
    h2 { color: cyan; } /* h2 dentro de .card.destaque */
  }

  @media (max-width: 600px) {
    padding: 16px;
  }
}
💡 Suporte nativo: funciona em todos os browsers modernos desde 2023 — Chrome 112+, Firefox 117+, Safari 16.5+. Sem Sass, sem PostCSS, sem build tool.

⚠️ Regra de ouro: no máximo 3 níveis de profundidade. Mais que isso gera seletores com especificidade muito alta, difíceis de sobrescrever e de ler.
07

Display

// como o elemento se comporta no fluxo

block
bloco 1
bloco 2
✅ ocupa todo o bloco
✅ width e height funcionam
✅ margin, padding e border completos
inline
inline 1 inline 2
✅ fica na mesma linha
❌ width e height não funcionam
⚠️ padding/margin só nas horizontais
inline-block
IB 1 IB 2
✅ fica na mesma linha
✅ width e height funcionam
✅ margin, padding e border completos
💡 O inline-block resolve o problema dos elementos inline que não respeitam margin/padding vertical. Muito usado em links estilizados como botões.
⚠️ O gap do baseline — o espaço misterioso embaixo de imagens inline
❌ problema — gap aparece sem motivo
container (sem flex)
← gap misterioso
O navegador reserva espaço para letras com descida
(g, p, y, j...) mesmo sem texto nenhum.
por que acontece
🙂
Apg
baseline → descenders →
Elementos inline alinham na baseline.
O espaço abaixo é reservado para os descenders.
3 formas de resolver
✅ opção 1 — mais usada
img {
  display: block;
}
tira do fluxo inline → gap some
✅ opção 2
img {
  vertical-align: bottom;
}
alinha na base → elimina o espaço
✅ opção 3
.container {
  line-height: 0;
}
zera o espaço da linha no pai
💡 Se o container já for display: flex, o problema não ocorre — o flex retira os filhos do fluxo inline automaticamente.
08

Box Model

// todo elemento é uma caixa com 4 camadas

As 4 camadas
content
margin — espaço fora da borda
border — a borda
padding — espaço entre borda e conteúdo
content — o conteúdo em si
Código e comportamento
.container {
  background-color: lightgray; ← mostra margin
  padding: 1px; ← segura margin collapse
}

.boxmodel {
  border: 3px solid red;
  padding: 20px;
  margin: 20px;
  background-color: lightblue; ← padding
}
⚠️ margin collapse — o comportamento que pega todo mundo
Quando dois elementos block têm margem top/bottom, apenas a maior margem é aplicada — elas não somam.

Pai e filho também colapsam se não houver padding ou border no pai.
margin-bottom: 30px
↕ resultado: 30px (não 60px)
margin-top: 30px
⚠️ margin collapse: margin top/bottom de elementos block "colapsa" — vence a maior. Não acontece com flex/grid ou com padding/border no pai.
08.5

Overflow

// o que acontece quando o conteúdo é maior que o container

Os 4 valores principais
visible — padrão
conteúdo transborda visível
O conteúdo sai do container mas continua visível.
hidden
conteúdo cortado
O que sai é cortado — não aparece e não tem scroll.
scroll
linha 1
linha 2
linha 3
linha 4
linha 5
Sempre mostra scrollbar, mesmo sem precisar.
auto ⭐
linha 1
linha 2
linha 3
linha 4
linha 5
Scrollbar só quando precisa — o mais usado.
overflow-x e overflow-y separados
/* controle por eixo */
overflow-x: hidden; /* corta horizontal */
overflow-y: auto; /* scroll vertical */

/* shorthand: vertical / horizontal */
overflow: hidden auto;

/* scroll só no eixo y — padrão de sidebar */
.sidebar {
  height: 100vh;
  overflow-y: auto;
}
overflow: hidden para segurar border-radius
❌ sem overflow: hidden
a imagem vaza nos cantos
✅ com overflow: hidden
cantos arredondados respeitados
.card {
  border-radius: 12px;
  overflow: hidden; /* garante que a img respeite o radius */
}
.card img { width: 100%; display: block; }
⚠️ overflow: hidden e position: absolute — atenção!
Um filho com position: absolute pode sair dos limites do pai.

Colocar overflow: hidden no pai corta esse filho se ele sair da área — isso pode ser o comportamento desejado ou um bug dependendo do contexto.

⚠️ Cuidado: se você tem um tooltip ou dropdown com position absolute dentro de um elemento com overflow: hidden, ele vai ser cortado.
.container {
  position: relative;
  overflow: hidden; /* corta o absolute filho */
}

.badge {
  position: absolute;
  top: -8px;
  right: -8px;
  /* vai ser cortado se sair do container */
}
ValorO que fazQuando usar
visibleConteúdo transborda e fica visível — padrãoQuando não quer nenhum comportamento especial
hiddenCorta tudo que sai do containerSegurar border-radius, esconder conteúdo, efeitos visuais
autoScroll aparece só quando necessárioContainers com conteúdo variável ⭐
scrollScrollbar sempre visível mesmo sem precisarEvite — prefira auto
overflow-x / overflow-yControla cada eixo separadamenteSidebar scrollável, tabelas com scroll horizontal
09

Box Sizing

// como o CSS calcula o tamanho da caixa

🔴 content-box — padrão do CSS
width: 300px · padding: 20px · border: 10px
width: 300px (só conteúdo)
+ padding: 20 + 20px
+ border: 10 + 10px
= Real: 360px 😱
🟢 border-box — recomendado
width: 300px · padding: 20px · border: 10px
width: 300px (tudo incluso)
padding já está dentro
border já está dentro
= Real: 300px ✅
⭐ Reset padrão — todo projeto começa assim
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
→ o que você escreve é o que aparece na tela. Sem surpresas.
10

Background

// controlando imagens e fundos

PropriedadeValorO que faz
background-sizecoverPreenche tudo. Pode cortar a imagem. Sem espaço vazio. ⭐ mais usado
background-sizecontainMostra a imagem inteira. Pode sobrar espaço vazio nas bordas.
background-sizeautoTamanho original. Pode ser cortada se maior que a caixa.
background-repeatno-repeatA imagem aparece uma única vez.
background-repeatrepeatA imagem se repete como ladrilho. Comportamento padrão do CSS.
💡 Combo mais usado: cover + no-repeat → preenche tudo sem repetição. Padrão de banners e hero sections.
10.5

object-fit

// controla como uma imagem preenche o espaço disponível — sem distorcer

O problema — imagens com proporções diferentes quebram o grid
paisagem 16:9
retrato 9:16
quadrado 1:1
→ cada imagem tem altura diferente, o grid fica torto
A solução — height: 100% + object-fit: cover
#featured {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 200px; /* altura da célula */

  img {
    width: 100%;
    height: 100%; /* ocupa a célula inteira */
    object-fit: cover; /* recorta sem distorcer */
    display: block; /* elimina gap do baseline */
  }
}
Visualizando o object-fit: cover
todas com
mesma altura
recorta o
excesso
sem
distorção
→ grid-auto-rows: 140px define a altura fixa das células
Valores do object-fit
ValorComportamentoQuando usar
coverPreenche tudo — recorta o excesso. Mantém proporção.Grids de imagem, thumbnails, banners ⭐ mais usado
containMostra a imagem inteira — pode sobrar espaço vazio.Logos, ícones, imagens que não podem ser cortadas
fillEstica para preencher — distorce a imagem.Quase nunca — só se a proporção não importar
noneTamanho original — pode transbordar ou sobrar espaço.Quando quer o tamanho real da imagem
scale-downMenor entre none e contain — nunca amplia.Logos pequenos que não devem ser ampliados
⚠️ O height: 100% precisa de uma altura de referência na célula. Sem grid-auto-rows ou altura explícita no container, a imagem encolhe para zero. O object-fit funciona igual ao background-size — a diferença é que um é para tags <img> e o outro para imagens de fundo via CSS.
11

Shorthands

// escrever menos, fazer mais

border
sintaxe
border: [largura] · [estilo] · [cor];
border: 2px solid red;
border: 1px dashed #ccc;
// estilo é obrigatório (solid, dashed, dotted...)
font
sintaxe
font: [style] [weight] [size]/[line-height] [family];
/* mínimo obrigatório */
font: 16px Arial;

/* completo */
font: italic bold 16px/1.5 Arial, sans-serif;
// size sempre antes de family · line-height colado no size com /
background
sintaxe
background: [color] [image] [position]/[size] [repeat] [attachment];
background: #fff;
background: url('foto.jpg');
background: #fff url('foto.jpg') center/cover no-repeat;
// size vem DEPOIS da position, separado por /
12

Dicas VS Code

// atalhos para turbinar a produtividade

alt + cliqueCria múltiplos cursores — você digita em vários lugares ao mesmo tempo
alt + shift + arrastoSeleciona múltiplas linhas em coluna — ótimo para editar listas e propriedades CSS alinhadas
shift + ←→↑↓Seleciona texto caractere a caractere ou linha a linha com o teclado
ctrl + setaPula palavra por palavra — combinado com shift seleciona em todas as linhas ativas
ctrl + shift + PAbre a paleta de comandos — acessa qualquer função do VS Code digitando o nome
ctrl + shift + VAbre preview de arquivos .md em tempo real enquanto você escreve
alt + ZConverte px para rem (extensão px to rem instalada)
M01

static — padrão

// Todo elemento já nasce com position: static. É o fluxo normal da página.

Os elementos seguem o fluxo normal — um embaixo do outro
Elemento 1
Elemento 2
Elemento 3
É o padrão. Você não precisa escrever, já vem assim. O elemento segue o fluxo normal da página, um depois do outro. As propriedades top, bottom, left, right não funcionam aqui.
M01

relative — desloca a si mesmo

// O elemento se move em relação à sua posição original. O espaço que ele ocupava continua reservado.

Sem position: relative
Elemento 1
Elemento 2
Elemento 3
Com position: relative + top: 16px left: 24px
Elemento 1
Elemento 2 ← deslocado
Elemento 3
O elemento se desloca da sua posição original usando top, bottom, left, right. Mas o espaço que ele ocupava continua lá — veja que o Elemento 3 não subiu. Muito usado como "âncora" para o absolute.
M01

absolute — sai do fluxo

// O elemento sai do fluxo. Se posiciona em relação ao pai mais próximo com position ≠ static.

Pai com position: relative — filho se posiciona dentro
pai (relative)
top: 12px right: 12px
bottom: 12px left: 12px
O absolute sai do fluxo — outros elementos ignoram ele
Elemento 1
Elemento 2
Absolute
(flutuando)
Ele sai completamente do fluxo — os outros elementos agem como se ele não existisse. Se posiciona usando top, bottom, left, right em relação ao pai com position: relative mais próximo. Se não tiver nenhum pai relative, vai usar o body inteiro como referência.
M01

fixed — fixo na tela

// O elemento fica fixo na janela do navegador. Mesmo rolando a página, ele não se move.

position: fixed — o header fica parado enquanto a página rola
🔒 Navbar Fixa (position: fixed)
O elemento fica preso na janela do navegador (viewport). Mesmo que o usuário role a página, ele continua no mesmo lugar. Muito usado em navbars fixas, botões flutuantes e cookie banners. Se posiciona em relação à janela, não ao pai.
M01

sticky — gruda ao rolar

// Começa no fluxo normal. Quando você rola e ele atinge o limite definido, ele "gruda" e fica fixo.

position: sticky + top: 0 — role o conteúdo abaixo
📌 Header Sticky (gruda ao rolar)
É um meio-termo entre relative e fixed. O elemento começa no fluxo normal, mas quando o usuário rola e ele chega no limite definido (ex: top: 0), ele "gruda" e fica fixo ali. Quando o pai dele sair da tela, ele some junto. Ótimo para headers de seções e menus laterais.

tabela resumo — positions

PositionSai do fluxo?top/left/right/bottom funciona?Referência
static❌ Não❌ Não
relative❌ Não (reserva espaço)✅ SimPosição original do elemento
absolute✅ Sim✅ SimPai com position ≠ static
fixed✅ Sim✅ SimJanela do navegador (viewport)
sticky❌ Não (até grudar)✅ Sim (define o ponto de "grude")Pai + viewport
💡 O combo mais usado no dia a dia:
Colocar position: relative no pai e position: absolute no filho. Isso te dá controle total pra posicionar um elemento em qualquer canto do pai, como um ícone no canto de um card, uma badge em cima de uma imagem, etc.
M01

inset — shorthand de top/right/bottom/left

// inset é apenas um atalho para escrever top, right, bottom e left de uma vez.

Sem inset — 4 linhas de código
pai (relative)
top: 20px
right: 20px
bottom: 20px
left: 20px
Com inset: 20px — 1 linha, mesmo resultado
pai (relative)
inset: 20px
inset: 0 — cobre o pai inteiro (muito usado!)
pai (relative)
inset: 0
top:0 right:0 bottom:0 left:0
inset: 10px 30px 40px 10px — valores diferentes
pai (relative)
top:10 · right:30
bottom:40 · left:10
SintaxeEquivale a
inset: 20pxtop: 20px · right: 20px · bottom: 20px · left: 20px
inset: 10px 20pxtop/bottom: 10px · right/left: 20px
inset: 10px 20px 30px 40pxtop: 10px · right: 20px · bottom: 30px · left: 40px
inset: 0top: 0 · right: 0 · bottom: 0 · left: 0 (cobre o pai todo)
Segue a mesma lógica do margin e padding shorthand: 1 valor = todos os lados, 2 valores = vertical/horizontal, 4 valores = top/right/bottom/left. O uso mais comum é inset: 0 para fazer um elemento cobrir completamente o pai, como em overlays e modais.
M01

z-index — profundidade

// z-index define qual elemento fica na frente quando dois se sobrepõem. Maior número = mais na frente.

Sem z-index — quem vem por último no HTML fica na frente
z-index: auto
HTML: 1º
z-index: auto
HTML: 2º
z-index: auto
HTML: 3º
Com z-index — maior número vence, independente da ordem
z-index: 3 🏆
HTML: 1º
z-index: 1
HTML: 2º
z-index: 2
HTML: 3º
Exemplo real — modal + overlay
🗂️ Modal
z-index: 20
página: z-index padrãooverlay: z-index: 10modal: z-index: 20
⚠️ z-index só funciona com position ≠ static
❌ não funciona:
position: static · z-index: 999
✅ funciona:
position: relative/absolute/fixed/sticky + z-index
Pensa no z-index como a ordem das camadas num editor de imagem (tipo Figma). Quem tem o número maior fica na frente. z-index só funciona em elementos com position diferente de static. Não tem valor certo — o que importa é a ordem relativa entre os elementos.
💡 Combo do dia a dia — overlay que cobre o pai:

inset: 0 + z-index juntos é um dos padrões mais usados em modais, tooltips e overlays:

.overlay {
  position: absolute;
  inset: 0;        /* cobre o pai inteiro */
  z-index: 10;      /* fica na frente de tudo */
  background: rgba(0,0,0,0.5);
}
M02

Variáveis CSS — --custom-properties

// Guarda valores para reutilizar. Define uma vez, usa em qualquer lugar.

Definindo e usando uma variável
:root {
  --cor-principal: lightblue;
  --tamanho: 16px;
}

p {
  color: var(--cor-principal);
  font-size: var(--tamanho);
}
Resultado visual
→ usando --cor-principal
→ usando --cor-principal
→ usando --cor-principal
⭐ Sobrescrevendo a variável em um elemento específico
:root { --bg-color: lightblue; }
body { background: var(--bg-color); }

div {
  --bg-color: lightgreen; /* sobrescreve */
  background: var(--bg-color);
}
→ resultado:
:root → --bg-color: lightblue
body usa lightblue
div → --bg-color: lightgreen (sobrescreveu!)
div usa lightgreen
Variáveis CSS começam com -- e são definidas normalmente no :root (que representa o elemento raiz da página). Para usar, você chama com var(--nome). Você pode sobrescrever a variável em qualquer elemento específico — ela passa a ter aquele novo valor só dentro daquele elemento e dos filhos dele.
M02

Pseudo-classes — :pseudo-class

// Selecionam elementos com base em estado ou posição. Usam : (dois pontos simples).

:hover — passa o mouse em cima
Passe o mouse aqui ✦
:not() — seleciona quem NÃO tem a classe
div:not(.destaque) → opacity: 0.3
item 1
item 2 (.destaque)
item 3
item 4 (.destaque)
:has() — seleciona o pai se o filho corresponder
.card:has(input:checked) → destaca o card
:nth-child(n) — seleciona pelo número
:nth-child(even) → destaca os pares
1
2
3
4
5
6
odd → ímpares (1,3,5...)
even → pares (2,4,6...)
2n+1 → fórmula personalizada
:root — o elemento raiz da página
:root é onde você define suas variáveis globais.
Ele representa o elemento de mais alto nível do documento — na prática equivale ao <html>, mas com especificidade maior.

:root {  --cor: red;  --fonte: 16px;  }
Pseudo-classes usam : (dois pontos simples) e selecionam elementos com base em estado (hover, checked) ou posição estrutural (nth-child, first-child). O :not() e o :has() são funcionais — recebem um seletor como argumento. O :has() é especialmente poderoso pois é o primeiro seletor CSS que "olha para o filho para estilizar o pai".
M02

Pseudo-elements — ::pseudo-element

// Estilizam partes específicas de um elemento. Usam :: (dois pontos duplos).

::first-letter — estiliza a primeira letra

Esse é um exemplo de texto onde apenas a primeira letra recebe um estilo especial com ::first-letter. Muito usado em artigos e textos editoriais.

::before e ::after — insere conteúdo decorativo
::before adiciona conteúdo antes · ::after depois
Item com ::before (seta)
Item com ::before e ::after (check)
Item com ::before (seta)
Uso real — ::before como elemento decorativo (sem conteúdo de texto)
.texto::before {
  content: ''; /* vazio! */
  position: absolute;
  left: 0;
  width: 4px;
  height: 100%;
  background: purple;
}
Isso é um parágrafo com uma barra decorativa criada pelo ::before. Nenhum elemento extra foi adicionado no HTML.
Outro parágrafo com a mesma barra, sem adicionar nada novo no HTML.
Pseudo-elements usam :: (dois pontos duplos) e criam "partes virtuais" de um elemento. O ::before e ::after são os mais usados — eles inserem conteúdo antes ou depois do elemento diretamente pelo CSS. Exigem sempre a propriedade content (pode ser texto, ícone, ou '' vazio quando for só decoração).

tabela resumo — seletores avançados

SeletorTipoO que fazSintaxe
--variavelVariávelGuarda um valor para reutilizar. Sobrescrevível por elemento.var(--nome)
:hoverPseudo-classQuando o mouse passa por cima do elementoa:hover
:not()Pseudo-classSeleciona elementos que NÃO correspondem ao seletordiv:not(.ativo)
:has()Pseudo-classSeleciona o pai se ele contiver o seletor filhodiv:has(img)
:rootPseudo-classElemento raiz da página. Usado para variáveis globais.:root { --x: 1; }
:nth-child(n)Pseudo-classSeleciona pelo número de posição. Aceita odd, even e fórmulas.li:nth-child(2)
::first-letterPseudo-elementEstiliza apenas a primeira letra do elementop::first-letter
::beforePseudo-elementInsere conteúdo antes do elemento via CSS. Precisa de content.div::before
::afterPseudo-elementInsere conteúdo depois do elemento via CSS. Precisa de content.div::after
M03

Flexbox vs Grid — Comportamento padrão

// O que acontece quando você só escreve display: flex ou display: grid

display: flex — os filhos ficam em linha
A
B
C
display: grid + grid-template-columns: repeat(3, 1fr)
A
B
C
→ FlexPensa em 1 dimensão: uma linha OU uma coluna de cada vez. Por padrão, coloca tudo em linha (row). Os itens ocupam só o espaço que precisam.
→ GridPensa em 2 dimensões: linhas E colunas ao mesmo tempo. Você define quantas colunas quer e o grid divide o espaço igualmente.
M03

Direção e proporção

// Flex muda a direção. Grid controla as proporções das colunas.

flex-direction: column — agora empilha na vertical
Item 1
Item 2
Item 3
grid-template-columns: 1fr 2fr — segunda coluna é o dobro
1fr
2fr (dobro)
1fr
2fr (dobro)
→ FlexCom flex-direction você escolhe a direção: row (linha, padrão) ou column (coluna).
→ GridO "fr" é uma unidade de fração. 1fr 2fr: divide o espaço em 3 partes, dá 1 pra primeira coluna e 2 pra segunda.
M03

Quebra de linha e áreas

// Flex quebra linha automaticamente. Grid pode mesclar células.

flex-wrap: wrap — quebra linha quando não cabe
A
B
C
D
E
grid-column: span 2 — item ocupando 2 colunas
A (span 2)
B
C
D
E (span 4)
→ FlexCom flex-wrap: wrap, quando os itens não cabem na linha, eles descem automaticamente para a próxima.
→ GridCom grid-column: span 2, você manda um item ocupar 2 colunas de uma vez, como mesclar células no Excel.
M03

Alinhamento

// Os dois são ótimos para alinhar, mas de formas diferentes.

align-items: center + justify-content: space-between
Alto
Médio
Alto
place-items: center — centraliza em linha e coluna
A
B
C
→ Flexalign-items controla o eixo cruzado (vertical se for row) e justify-content controla o eixo principal (horizontal).
→ Gridplace-items é o shorthand que centraliza nos dois eixos de uma vez. É um atalho pra align-items + justify-items juntos.
M03

Quando usar cada um

// guia rápido de decisão

⚡ Use Flexbox quando...

  • Alinhar itens em uma linha (navbar, botões)
  • Centralizar algo na tela
  • Distribuir espaço entre itens
  • Criar um componente simples (card, header)
  • O layout for em uma só direção

🎯 Use Grid quando...

  • Criar o layout geral da página
  • Precisar de linhas E colunas ao mesmo tempo
  • Quiser que um item ocupe múltiplas colunas/linhas
  • Montar galerias de imagem
  • O layout for complexo e bidimensional
💡 Resumo de uma linha:

Flexbox = 1 dimensão → você pensa em linha OU coluna. Ótimo pra alinhar componentes.
Grid = 2 dimensões → você pensa em linha E coluna ao mesmo tempo. Ótimo pra montar o esqueleto da página.

Na prática você vai usar os dois juntos: Grid pra estrutura geral da página, Flex pra organizar os elementos dentro de cada seção. ✅
M04

Conceitos & Eixos

// o modelo mental do Flexbox — container, itens e os dois eixos

Container vs Itens
CONTAINER — display: flex
item 1
item 2
item 3
O container recebe display: flex
Os itens são os filhos diretos — eles se organizam automaticamente.
Os dois eixos
→ main axis
↓ cross axis
A
B
C
main axis → direção dos itens (horizontal por padrão)
cross axis → perpendicular ao main (vertical por padrão)
Propriedades do container vs propriedades dos itens
CONTAINER (pai)
display: flex
flex-direction
justify-content
align-items
flex-wrap
gap
ITENS (filhos)
flex-basis
flex-grow
flex-shrink
flex (shorthand)
order
align-self
M04

flex-direction

// define a direção do main axis — onde os itens se organizam

row — padrão · horizontal →
1
2
3
row-reverse — horizontal ←
1
2
3
column — vertical ↓
1
2
3
column-reverse — vertical ↑
1
2
3
flex-direction define o main axis. O cross axis é sempre perpendicular a ele — então quando você muda a direção, justify-content e align-items trocam de eixo junto. É um dos pontos que mais confunde no começo.
M04

justify-content

// distribui os itens ao longo do main axis

flex-start — padrão · agrupa no início
A
B
C
flex-end — agrupa no fim
A
B
C
center — centraliza
A
B
C
space-between — primeiro e último nas bordas
A
B
C
space-around — espaço igual ao redor de cada item
A
B
C
space-evenly — espaço idêntico entre todos
A
B
C
💡 space-between vs space-evenly: between encosta o primeiro e o último nas bordas. evenly deixa o mesmo espaço em todos os lados, inclusive nas bordas.
M04

align-items

// alinha os itens no cross axis (perpendicular ao main)

stretch — padrão · estica pra preencher
A
B
C
center — centraliza no eixo cruzado
A
B
C
flex-start — alinha no topo
A
B
C
flex-end — alinha na base
A
B
C
💡 Centralizar na tela (o combo mais usado): display: flex · justify-content: center · align-items: center → centraliza em ambos os eixos ao mesmo tempo.
M04

Gap e Margin

// duas formas de criar espaço entre os itens

gap — espaço entre todos os itens de uma vez
gap: 8px
A
B
C
gap: 24px
A
B
C
margin: auto — empurra itens específicos
último item com margin-left: auto
Logo
Home
Login
→ padrão de navbar: logo + links à esq, botão à dir
Entendendo o auto — o que acontece em cada caso
margin-left: auto
espaço →
.box
→ empurra para a direita
margin-right: auto
.box
← espaço
→ empurra para a esquerda
margin: 0 auto (os dois)
.box
→ centraliza
O auto consome todo o espaço livre disponível no lado em que é aplicado.
Com os dois lados em auto, o espaço é dividido igualmente — resultado: centralizado.
margin: 0 auto — centraliza um elemento block horizontalmente
sem margin: 0 auto
width: 60%
com margin: 0 auto
width: 60% · margin: 0 auto
Como funciona: margin: 0 auto = top/bottom: 0 · left/right: auto
O auto divide o espaço livre igualmente nos dois lados → centraliza.

⚠️ Duas condições obrigatórias:
→ O elemento precisa ser display: block (ou inline-block)
→ O elemento precisa ter um width definido — sem width, ele já ocupa 100% e não tem espaço sobrando
❌ não funciona
display: inline;
margin: 0 auto; ← ignorado
✅ funciona
display: block;
width: 960px;
margin: 0 auto;
💡 Padrão clássico de layout: usado para centralizar o conteúdo principal da página com largura máxima.
.container { max-width: 1200px; margin: 0 auto; padding: 0 24px; }
Como o margin: auto direciona o espaço livre
margin-left: auto → empurra para a direita
espaço livre →
.elemento
margin-right: auto → empurra para a esquerda
.elemento
← espaço livre
margin: 0 auto (os dois juntos) → centraliza
.elemento
dentro do flex — empurra itens específicos (padrão de navbar)
logo
home
margin-left: auto ↓
login
→ margin-left: auto no .login consome todo o espaço livre — empurra só ele para a direita
gap é a forma moderna de espaçar — aplica entre todos os itens sem afetar as bordas externas. margin: auto consome todo o espaço livre disponível, empurrando os outros itens. Combinados, cobrem 99% dos casos de espaçamento em flex layouts.
M04

Multi Line — flex-wrap

// o que acontece quando os itens não cabem em uma linha

nowrap — padrão · os itens encolhem pra caber
Item 1
Item 2
Item 3
Item 4
Item 5
wrap — quebra para a próxima linha
Item 1
Item 2
Item 3
Item 4
Item 5
align-content — alinha as linhas quando há wrap
Quando há múltiplas linhas (com flex-wrap), align-content controla como as linhas se distribuem no cross axis — funciona como um justify-content, mas para as linhas.

align-content: flex-start → linhas agrupadas no topo
align-content: center → linhas centralizadas
align-content: space-between → linhas distribuídas
M04

Flex Basis / Grow / Shrink

// como o espaço disponível é distribuído entre os itens

flex-basis — tamanho inicial do item antes de crescer ou encolher
basis: 120px
basis: 200px
basis: 80px
flex-grow — quanto o item cresce para ocupar espaço livre
grow: 1 / grow: 2 / grow: 1 → o do meio pega o dobro do espaço livre
grow: 1
grow: 2
grow: 1
flex-shrink — quanto o item encolhe quando falta espaço
shrink: 1 (padrão encolhe) vs shrink: 0 (não encolhe)
shrink: 1 → encolhe
shrink: 0 → fixo
flex-basis = ponto de partida do tamanho. flex-grow = como o item usa o espaço que sobrou. flex-shrink = como o item cede quando falta espaço. Os três juntos controlam o comportamento elástico de cada item.
M04

Shorthand Flex

// flex: grow shrink basis — os três em uma linha só

Sintaxe completa
sintaxe
flex: [grow] [shrink] [basis];
flex: 1 1 auto; /* padrão */
flex: 1; /* equivale a: flex-grow:1 · shrink:1 · basis:0 */
flex: 0 0 200px; /* tamanho fixo de 200px, não cresce nem encolhe */
flex: 2; /* cresce o dobro dos itens com flex: 1 */
Os atalhos mais usados no dia a dia
DeclaraçãoGrowShrinkBasisQuando usar
flex: 1110Distribuir espaço igualmente entre os itens
flex: auto11autoCresce e encolhe respeitando o conteúdo
flex: none00autoItem completamente rígido — tamanho do conteúdo
flex: 0 0 Xpx00XpxTamanho fixo — sidebar, avatar, ícones
M04

Order

// reordena visualmente os itens sem mudar o HTML

Sem order — segue a ordem do HTML
Com order — 3º item aparece primeiro visualmente
1º no HTML
2º no HTML
3º no HTML ← aparece primeiro
O padrão de todos os itens é order: 0. Quem tem número menor aparece antes. Valores negativos também funcionam. Útil para reordenar layouts em mobile com media queries sem duplicar HTML.

tabela resumo — flexbox

PropriedadeAplica emO que faz
display: flexcontainerAtiva o flexbox
flex-directioncontainerDefine o main axis: row | row-reverse | column | column-reverse
justify-contentcontainerDistribui itens no main axis: flex-start | flex-end | center | space-between | space-around | space-evenly
align-itemscontainerAlinha itens no cross axis: stretch | center | flex-start | flex-end | baseline
flex-wrapcontainerPermite quebra de linha: nowrap | wrap | wrap-reverse
gapcontainerEspaço entre os itens
flex-basisitemTamanho inicial antes de crescer/encolher
flex-growitemQuanto do espaço livre o item absorve
flex-shrinkitemQuanto o item cede quando falta espaço
flexitemShorthand: grow shrink basis
orderitemOrdem visual do item (padrão: 0)
align-selfitemSobrescreve align-items só para esse item
M05

Conceitos & Fundamentos

// o modelo mental do Grid — linhas, colunas, células e áreas

O que é o Grid
1
2
3
4
5
6
Grid divide o container em linhas e colunas simultaneamente — como uma tabela, mas muito mais poderoso.

display: grid no container → filhos viram células automáticas.
Vocabulário do Grid
célula
área (span 2)
grid line → as linhas que dividem o grid (numeradas de 1)
track → espaço entre duas grid lines (coluna ou linha)
cell → interseção de uma linha e coluna
area → grupo de células adjacentes
Grid vs Flexbox — quando cada um entra
FLEXBOX — 1 dimensão
→ Navbar, botões, cards em linha
→ Centralizar um elemento
→ Componentes simples
→ Quando o conteúdo dita o tamanho
GRID — 2 dimensões
→ Layout geral da página
→ Galerias de imagem
→ Dashboards e painéis
→ Quando o layout dita o tamanho
M05

grid-template-columns

// define quantas colunas existem e qual o tamanho de cada uma

repeat(3, 1fr) — 3 colunas iguais
1fr
1fr
1fr
1fr 2fr 1fr — do meio é o dobro
1fr
2fr
1fr
200px 1fr — coluna fixa + fluida
200px fixo
1fr (resto)
repeat(auto-fill, minmax(120px, 1fr)) — responsivo automático
A
B
C
D
E
💡 minmax(min, max) define um tamanho mínimo e máximo para a coluna. minmax(120px, 1fr) significa: no mínimo 120px, no máximo divide o espaço igualmente. Com auto-fill, o grid cria quantas colunas couberem — layout responsivo sem media query!
M05

grid-template-rows

// define a altura e quantidade de linhas explícitas do grid

Linhas com alturas diferentes
60px
60px
60px
30px
30px
30px
50px
50px
50px
Layout de página — header + main + footer
header — 50px
main — 1fr (resto)
footer — 40px
Funciona exatamente como grid-template-columns, mas para o eixo vertical. Na maioria dos layouts reais você define as colunas e deixa as linhas em auto — elas crescem conforme o conteúdo. Definir rows explicitamente é útil para layouts de altura fixa, como um app de página inteira.
M05

grid-column & grid-row

// posiciona e expande itens usando as grid lines numeradas

Grid lines são numeradas a partir de 1 — você posiciona os itens entre elas
grid-column: 1 / 3
col 3
col 4
grid-column: span 4 (ocupa tudo)
A
grid-column: 2 / 4
D
Sintaxes equivalentes
/* linha inicial / linha final */
grid-column: 1 / 3; /* da line 1 até line 3 */

/* span — quantas colunas ocupa */
grid-column: span 2; /* ocupa 2 colunas */

/* até a última linha */
grid-column: 1 / -1; /* ocupa tudo */

/* funciona igual pra linhas */
grid-row: 1 / 3; /* ocupa 2 linhas verticais */
Posicionamento explícito
col:1
row:1/3
col:2/4 · row:1
2,2
3,2
col: 1/-1 · row: 3
M05

grid-template-areas

// nomeia as áreas do grid com texto — layout visual no CSS

Definindo as áreas no container
.layout {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: 60px 1fr 50px;
  grid-template-areas:
    "header header"
    "sidebar main "
    "footer footer";
}

header { grid-area: header; }
aside { grid-area: sidebar; }
main { grid-area: main; }
footer { grid-area: footer; }
Resultado visual
header
sidebar
main
footer
O grid-template-areas é uma das features mais elegantes do CSS — você desenha o layout com texto no próprio CSS. Cada string entre aspas é uma linha do grid, cada palavra é uma área. Repetir o mesmo nome faz o item ocupar múltiplas células. Use "." para deixar uma célula vazia.
M05

Gap no Grid

// espaçamento entre colunas e linhas — pode ser diferente em cada eixo

gap: 16px — mesmo espaço em todos os lados
A
B
C
D
E
F
gap: 8px 32px — row-gap diferente de column-gap
A
B
C
D
E
F
💡 gap: 8px 32px = row-gap: 8px (vertical) + column-gap: 32px (horizontal). Mesma lógica do padding/margin shorthand — primeiro vertical, depois horizontal.
M05

Shorthand grid-template

// rows e columns em uma linha só

grid-template — rows / columns
sintaxe
grid-template: [rows] / [columns];
/* verboso */
grid-template-rows: 60px 1fr 50px;
grid-template-columns: 200px 1fr;

/* shorthand equivalente */
grid-template: 60px 1fr 50px / 200px 1fr;

/* com areas */
grid-template:
  "header header" 60px
  "sidebar main" 1fr
  "footer footer" 50px
  / 200px 1fr;
M05

Alinhamentos

// content, items e self — três níveis de controle

Os três níveis de alinhamento no Grid
justify/align-content
Distribui as faixas do grid dentro do container quando sobra espaço.

Funciona como justify-content do flex, mas para as trilhas do grid inteiro.
justify/align-items
Alinha o conteúdo dentro de cada célula — aplica para todos os itens ao mesmo tempo.

place-items: center centraliza tudo de uma vez.
justify/align-self
Alinha um item específico dentro da sua célula — sobrescreve o align-items só para aquele item.
place-items: center — centraliza conteúdo em todas as células
A
B
C
align-self — item individual com alinhamento próprio
start
center
end
PropriedadeAplica emControlaValores comuns
justify-contentcontainerFaixas de coluna no eixo horizontalstart · end · center · space-between · space-around
align-contentcontainerFaixas de linha no eixo verticalstart · end · center · space-between · space-around
justify-itemscontainerConteúdo de cada célula — horizontalstart · end · center · stretch
align-itemscontainerConteúdo de cada célula — verticalstart · end · center · stretch
place-itemscontainerShorthand: align-items + justify-itemscenter · start end · etc.
justify-selfitemEsse item no eixo horizontalstart · end · center · stretch
align-selfitemEsse item no eixo verticalstart · end · center · stretch
place-selfitemShorthand: align-self + justify-selfcenter · start end · etc.
M05

Propriedades grid auto

// como o grid lida com itens além das trilhas explícitas

grid-auto-rows e grid-auto-columns
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 80px; /* toda linha implícita terá 80px */
  grid-auto-rows: minmax(80px, auto); /* mínimo 80px, cresce com conteúdo */
}
Quando você tem mais itens do que linhas definidas no grid-template-rows, o grid cria linhas implícitas automaticamente. O grid-auto-rows define o tamanho dessas linhas extras.
grid-auto-flow — direção de preenchimento automático
grid-auto-flow: row (padrão)
1
2
3
4
5
6
preenche linha por linha →
grid-auto-flow: column
1
2
3
4
5
6
preenche coluna por coluna ↓
M05

Grid ou Flex?

// guia de decisão rápida

🎯 Use Grid quando...

  • → O layout é bidimensional (linhas E colunas)
  • → Você precisa de posicionamento preciso das células
  • → Os itens precisam se alinhar entre linhas diferentes
  • → Está montando o esqueleto geral da página
  • → Galerias, dashboards, painéis de cards

⚡ Use Flex quando...

  • → O layout é unidimensional (linha OU coluna)
  • → O conteúdo dita o tamanho dos itens
  • → Quer distribuir espaço ou centralizar algo
  • → Está organizando um componente (navbar, card, botões)
  • → Os itens precisam quebrar linha naturalmente
💡 A resposta certa na maioria dos casos:

Use Grid para o layout da página — a estrutura macro (header, sidebar, main, footer).
Use Flex para os componentes dentro do layout — navbar, cards, listas, botões.

Eles se complementam — um container Grid pode ter filhos Flex, e vice-versa. ✅

tabela resumo — CSS Grid

PropriedadeAplica emO que faz
display: gridcontainerAtiva o CSS Grid
grid-template-columnscontainerDefine número e tamanho das colunas
grid-template-rowscontainerDefine número e tamanho das linhas
grid-template-areascontainerNomeia áreas do grid com texto
grid-templatecontainerShorthand: rows / columns (+ areas)
gapcontainerEspaço entre células — row-gap column-gap
grid-auto-rowscontainerAltura das linhas implícitas (criadas automaticamente)
grid-auto-flowcontainerDireção de preenchimento: row | column | dense
place-itemscontainerAlinha conteúdo dentro de todas as células
grid-columnitemPosição e span horizontal: start / end ou span N
grid-rowitemPosição e span vertical: start / end ou span N
grid-areaitemReferencia uma área nomeada no grid-template-areas
place-selfitemAlinha esse item específico dentro da sua célula
M06

Estrutura & <form>

// o container de todos os campos — atributos essenciais

Anatomia do <form>
<form
  action="/enviar" ← onde os dados vão
  method="post"  ← GET ou POST
  novalidate     ← desativa validação nativa
>
  <!-- campos aqui -->
</form>
GET vs POST
MétodoQuando usar
GETBusca, filtros — dados vão na URL. Visível e compartilhável.
POSTLogin, cadastro, envio de arquivos — dados no corpo da requisição. Seguro para dados sensíveis.
Atributos comuns dos campos do formulário
AtributoO que fazExemplo
nameIdentifica o campo no envio — obrigatório para o dado ser enviadoname="email"
idLiga o campo ao <label> via for=id="email"
valueValor inicial ou valor enviado (em checkbox/radio)value="sim"
placeholderTexto de dica dentro do campo — some ao digitarplaceholder="Digite aqui"
requiredCampo obrigatório — bloqueia envio se vaziorequired
disabledDesativa o campo — não é enviado no formdisabled
readonlySó leitura — é enviado, mas não editávelreadonly
autofocusFoca automaticamente ao carregar a páginaautofocus
autocompleteAtiva ou desativa o preenchimento automático do navegadorautocomplete="off"
M06

Atributos Gerais dos Inputs

// funcionam na maioria dos campos de formulário

value — valor do campo
/* valor inicial preenchido */
<input type="text" value="João">

/* em checkbox/radio — o que é enviado */
<input type="radio" name="plano" value="pro">

/* em button — o texto do botão */
<input type="submit" value="Enviar">
Em inputs de texto → define o valor inicial já preenchido.

Em checkbox e radio → define o que é enviado quando marcado (o usuário não vê esse valor).

Em submit/reset → define o texto do botão.
placeholder — dica dentro do campo
<input
  type="email"
  placeholder="[email protected]"
>
Texto de dica que aparece quando o campo está vazio. Some ao digitar. Não substitui o label — use os dois.
required · disabled · readonly — atributos booleanos
required
<input required>
Bloqueia o envio se vazio. Navegador exibe aviso nativo.
disabled
<input disabled>
Desativa o campo. Não é enviado no form.
readonly
<input readonly>
Não editável, mas é enviado no form.
autofocus · autocomplete
/* foca automaticamente ao carregar */
<input type="text" autofocus>
O cursor já aparece nesse campo quando a página carrega. Use com moderação — só um por página.
/* desativa sugestões do navegador */
<input autocomplete="off">

/* dica semântica para o navegador */
<input autocomplete="email">
<input autocomplete="current-password">
Com valores semânticos, o navegador preenche com o dado certo automaticamente.
size · form — os menos conhecidos
size
/* largura em número de caracteres */
<input type="text" size="10">
<input type="text" size="30">
Define a largura visual em quantidade de caracteres. Não limita o que o usuário pode digitar — use maxlength pra isso. Na prática, prefira controlar largura via CSS (width).
form
<form id="meu-form">
  <button type="submit">Enviar</button>
</form>

/* input FORA do form, mas vinculado */
<input type="text" form="meu-form">
Vincula um campo a um form mesmo estando fora dele no HTML. O valor de form deve bater com o id do form.
AtributoTipoO que fazDetalhe
valuetexto / radio / checkboxValor inicial ou valor enviadoEm checkbox/radio — o que chega no back-end
placeholdertextoDica dentro do campoNão substitui o label
requiredtodosCampo obrigatórioBloqueia envio se vazio
disabledtodosDesativa o campoNão é enviado no form
readonlytextoSó leituraÉ enviado no form
autofocustodosFoca ao carregar a páginaSó um por página
autocompletetextoSugestões do navegadorUse valores semânticos: email, name, tel...
sizetextoLargura em nº de caracteresPrefira controlar via CSS width
formtodosVincula campo a um form externoValor deve ser o id do form
M06

Button

// três tipos de botão — cada um com comportamento diferente

type="submit" — padrão
<button type="submit">
  Enviar
</button>
Envia o formulário ao clicar. É o tipo padrão quando você não especifica — cuidado!
type="reset"
<button type="reset">
  Limpar
</button>
Limpa todos os campos do formulário de volta aos valores iniciais.
type="button"
<button type="button"
  onclick="fn()">
  Clique
</button>
Não faz nada por padrão — usado para ações via JavaScript.
⚠️ Sempre declare o type no botão. Sem ele, o padrão é submit — um botão dentro de um form sem type declarado vai submeter o form ao ser clicado, o que causa bugs difíceis de rastrear.
M06

Input Text, Number, Email, Password

// os inputs de texto mais usados no dia a dia

type="text"
<input
  type="text"
  name="nome"
  placeholder="Seu nome"
  maxlength="50"
>
Campo de texto livre. maxlength limita caracteres.
type="number"
<input
  type="number"
  min="0"
  max="100"
  step="5"
>
Aceita apenas números. step define o incremento das setas.
type="email"
<input
  type="email"
  name="email"
  required
>
Valida formato de e-mail automaticamente. Teclado mobile exibe @ por padrão.
type="password"
<input
  type="password"
  name="senha"
  minlength="8"
>
Oculta os caracteres digitados. minlength exige tamanho mínimo.
💡 O type do input faz muito mais do que parecer — ele muda o teclado no mobile, ativa validação nativa e altera o comportamento de preenchimento automático do navegador.
pattern — validação com regex direto no HTML
POR QUE USAR COM EMAIL
O type="email" valida que existe um @ e um domínio, mas aceita coisas como a@b.

Com pattern você define exatamente o formato que espera — nenhum caractere a mais, nenhum a menos.
/* type="email" aceita — pattern rejeita */
a@b           ← sem .com, .br...
@dominio.com ← sem usuário
usuario@     ← sem domínio

/* com pattern — só aceita o formato certo */
[email protected]
[email protected]
Email com pattern
<input
  type="email"
  pattern="[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,}"
  title="Digite um email válido"
  required
>
O title define a mensagem exibida quando a validação falha.
Outros usos comuns
/* só letras, 3 a 20 chars */
pattern="[A-Za-z]{3,20}"

/* CPF — 000.000.000-00 */
pattern="\d{3}\.\d{3}\.\d{3}-\d{2}"

/* CEP — 00000-000 */
pattern="[0-9]{5}-[0-9]{3}"

/* senha: mín 8 chars, letras e números */
pattern="(?=.*\d)(?=.*[a-z]).{8,}"
⚠️ pattern não dispensa validação no back-end. Qualquer pessoa pode inspecionar o HTML e remover o atributo. O pattern é uma camada de UX — para dar feedback imediato ao usuário — mas a validação real sempre precisa acontecer no servidor também.
M06

File, Range, Color

// inputs com interface visual própria do navegador

type="file"
<input
  type="file"
  accept=".jpg,.png"
  multiple
>
Abre seletor de arquivo.
accept filtra extensões.
multiple permite vários arquivos.
type="range"
<input
  type="range"
  min="0"
  max="100"
  value="50"
>
Slider visual. Bom para volume, brilho, filtros.
type="color"
<input
  type="color"
  value="#34d399"
>
Abre color picker nativo do sistema.
💡 O atributo accent-color no CSS permite colorir a interface nativa desses inputs (range, checkbox, radio) com a cor do seu design: accent-color: #34d399;
M06

Checkbox, Radio & Hidden

// seleção única, múltipla e campos invisíveis

type="checkbox" — múltipla escolha
/* mesmo name, values diferentes */
<input type="checkbox" name="skills" value="html">
<input type="checkbox" name="skills" value="css" checked>
type="radio" — escolha única
/* mesmo name = grupo exclusivo */
<input type="radio" name="plano" value="free">
<input type="radio" name="plano" value="pro" checked>
type="hidden" — campo invisível enviado junto com o form
/* invisível — usuário não vê */
<input
  type="hidden"
  name="user_id"
  value="42"
>
Não aparece na tela, mas é enviado junto com o formulário.

Usado para passar dados que o usuário não precisa ver — como IDs, tokens, origens de página, etc.
💡 Radio: o que agrupa é o atributo name idêntico — apenas um do grupo pode ser selecionado. Checkbox: cada um é independente, mesmo com o mesmo name.
M06

Novos Inputs HTML5

// tipos modernos com validação e interface nativas

typeO que exibeValidação automática
dateSeletor de data nativoFormato de data válido
timeSeletor de horárioFormato de hora válido
datetime-localData + hora juntosData e hora válidas
monthSeletor de mês/anoMês válido
weekSeletor de semana do anoSemana válida
telCampo de telefone — abre teclado numérico no mobileNenhuma por padrão (use pattern)
urlCampo de URLFormato de URL válido (http://...)
searchCampo de busca com botão X nativoNenhuma
Atributo pattern — validação com regex
/* aceita só letras, 3 a 10 chars */
<input type="text"
  pattern="[A-Za-z]{3,10}"
  title="Só letras, 3 a 10 chars"
>
Atributo list — sugestões com datalist
<input list="frutas">
<datalist id="frutas">
  <option value="Maçã">
  <option value="Banana">
</datalist>
M06

Label

// o texto descritivo do campo — essencial para acessibilidade

Associando label ao input via for e id
/* for do label = id do input */
<label for="nome">Seu nome</label>
<input type="text" id="nome">
Clicar no label foca o input automaticamente. Essencial para acessibilidade (leitores de tela).
Label envolvendo o input — associação implícita
/* input dentro do label — sem for/id */
<label>
  Seu nome
  <input type="text">
</label>
Associação automática por hierarquia — mais usado em checkboxes e radios.
💡 Sempre use label. Além da acessibilidade, aumenta a área clicável do campo — especialmente importante em checkbox e radio, onde clicar no texto também deve marcar/desmarcar.
M06

Textarea & Select

// texto longo e lista de opções

<textarea> — campo de texto multilinha
<textarea
  name="mensagem"
  rows="4"
  cols="40"
  placeholder="Sua mensagem..."
  resize="none" ← no CSS
></textarea>
Diferente do input — tem tag de fechamento.
Conteúdo padrão vai entre as tags, não no value.
CSS resize: none impede o usuário de redimensionar.
<select> — lista suspensa
<select name="pais">
  <option value="">Selecione...</option>
  <option value="br" selected>Brasil</option>
  <option value="pt">Portugal</option>
</select>

/* multiple permite selecionar vários */
<select name="skills" multiple>...
<optgroup> — agrupando opções no select
<select name="cidade">
  <optgroup label="Nordeste">
    <option value="rec">Recife</option>
    <option value="for">Fortaleza</option>
  </optgroup>
  <optgroup label="Sudeste">
    <option value="sp">São Paulo</option>
  </optgroup>
</select>
O <optgroup> cria categorias visuais dentro do select — o label do grupo aparece em negrito mas não pode ser selecionado.

Útil para selects longos com muitas opções agrupadas por categoria.
M06

Fieldset & Legend

// agrupa campos relacionados com borda e título semânticos

Código
<fieldset>
  <legend>Dados pessoais</legend>

  <label for="nome">Nome</label>
  <input type="text" id="nome">

  <label for="email">Email</label>
  <input type="email" id="email">
</fieldset>
Resultado visual e comportamento
Dados pessoais
Adicionar disabled no fieldset desativa todos os campos do grupo de uma vez.
<fieldset> agrupa campos relacionados semanticamente — leitores de tela anunciam o grupo ao entrar nele. <legend> é o título do grupo. Apesar do estilo padrão do navegador ser feio, é totalmente customizável no CSS e importante para acessibilidade em formulários longos.
M06

Revisão & Atributos de Validação

// validação nativa do HTML antes de chegar no JavaScript

Atributos de validação nativa
AtributoFunciona emO que valida
requiredtodosCampo não pode estar vazio
minlength / maxlengthtext, password, textareaTamanho mínimo/máximo de caracteres
min / maxnumber, range, dateValor mínimo e máximo
patterntext, email, tel, urlRegex — valida o formato
typeinputValida email, url e outros formatos automaticamente
novalidateformDesativa toda a validação nativa do form

tabela resumo — formulários HTML

Elemento / TypeO que éDetalhe importante
<form>Container do formulárioaction + method definem o destino e o modo de envio
<label>Texto descritivo do campoLiga ao campo via for="id" — essencial para acessibilidade
<input type="text">Campo de texto livremaxlength limita caracteres
<input type="email">Campo de emailValida formato automaticamente
<input type="password">Campo de senhaOculta caracteres — use minlength
<input type="number">Campo numéricomin, max e step controlam o intervalo
<input type="checkbox">Múltipla escolhaMesmo name, values diferentes
<input type="radio">Escolha únicaMesmo name = grupo exclusivo
<input type="file">Upload de arquivoaccept filtra tipos, multiple permite vários
<input type="hidden">Campo invisívelEnviado no form mas não aparece na tela
<textarea>Texto multilinhaConteúdo entre tags, não no value
<select> + <option>Lista suspensaselected define opção padrão, multiple permite vários
<fieldset> + <legend>Grupo de camposdisabled no fieldset desativa todos os filhos
<button type="submit">Envia o formulárioSempre declare o type — padrão é submit
M07

Funções de Transformação

// mover, girar, escalar e distorcer elementos com transform

As funções do transform
/* mover */
transform: translate(20px, 10px);
transform: translateX(20px);
transform: translateY(-50%);

/* girar */
transform: rotate(45deg);
transform: rotate(-90deg);

/* escalar */
transform: scale(1.5); /* 150% */
transform: scale(1, 0.5); /* x, y */

/* distorcer */
transform: skew(10deg, 5deg);

/* combinando */
transform: translateY(-4px) scale(1.02);
normal
rotate
45deg
scale
1.35
skew
15deg
translateY(-50%) é um dos combos mais usados para centralização vertical:

top: 50%; transform: translateY(-50%)
→ move o elemento 50% para baixo, depois volta metade da sua própria altura = centralizado.
💡 transform não tira o elemento do fluxo — ao contrário de position, o espaço original do elemento continua reservado. Os outros elementos não são afetados pela transformação.
M07

Funções Matemáticas

// calc(), min(), max(), clamp() — valores dinâmicos no CSS

calc() — cálculo entre unidades diferentes
/* mistura unidades — impossível sem calc */
width: calc(100% - 32px);
height: calc(100vh - 60px);
margin-left: calc(var(--sidebar-w) + 24px);

/* operadores: + - * / */
font-size: calc(1rem * 1.25);
padding: calc(var(--spacing) / 2);
O poder do calc() está em misturar unidades que o CSS não consegue resolver sozinho — como subtrair pixels de uma porcentagem.

⚠️ Espaço obrigatório em volta dos operadores + e -:
calc(100%-32px) → erro
calc(100% - 32px) → correto
min() · max() · clamp() — limites de valor
/* min() — usa o menor valor */
width: min(500px, 90%); /* nunca passa de 500px */

/* max() — usa o maior valor */
width: max(300px, 50%); /* nunca fica menor que 300px */

/* clamp(min, ideal, max) — os três limites */
font-size: clamp(1rem, 2.5vw, 2rem);
/* mínimo 1rem · cresce com vw · máximo 2rem */

width: clamp(280px, 50%, 800px);
clamp() é a função mais poderosa — substitui media queries para tipografia e larguras fluidas. O font-size: clamp(1rem, 2.5vw, 2rem) cria texto que cresce com a tela, mas nunca sai dos limites.
M07

Funções de Filtro

// efeitos visuais aplicados a elementos e fundos

filter vs backdrop-filter
filter — aplica no elemento
filter: blur(4px);
filter: brightness(0.5); /* 50% brilho */
filter: contrast(1.5);
filter: grayscale(100%);
filter: saturate(2);
filter: sepia(80%);
filter: drop-shadow(0 4px 8px rgba(0,0,0,0.3));

/* combinando */
filter: brightness(0.8) contrast(1.2);
backdrop-filter — aplica no fundo atrás
/* glass morphism — efeito de vidro */
.card {
  background: rgba(255,255,255,0.1);
  backdrop-filter: blur(12px);
  border: 1px solid rgba(255,255,255,0.2);
}
O backdrop-filter desfoca o que está atrás do elemento — o elemento em si continua nítido. Muito usado em navbars translúcidas e modais com blur.
M07

Funções de Cores

// rgb(), hsl(), oklch() e como usar transparência

Os formatos de cor em CSS
FunçãoSintaxeQuando usar
rgb()rgb(255, 99, 71) ou rgb(255 99 71)Quando você tem os valores R G B em mãos
rgba()rgba(255, 99, 71, 0.5)RGB com transparência — o 4º valor é o alpha (0-1)
hsl()hsl(9, 100%, 64%)Matiz / Saturação / Luminosidade — mais intuitivo para criar paletas
hsla()hsla(9, 100%, 64%, 0.5)HSL com transparência
oklch()oklch(0.7 0.2 30)Formato moderno — percepção de cor mais uniforme entre tons
Transparência moderna — canal alpha direto
/* forma antiga */
color: rgba(255, 99, 71, 0.5);

/* forma moderna — barra separando alpha */
color: rgb(255 99 71 / 50%);
color: hsl(9 100% 64% / 0.5);

/* hex com transparência — últimos 2 dígitos */
color: #ff634780; /* 80 hex = 50% alpha */
color: #ff6347ff; /* ff = 100% opaco */
color: #ff634700; /* 00 = 100% transparente */
Por que hsl() é mais intuitivo para criar paletas
30%
45%
60%
75%
90%
/* mesma matiz (220), mesma saturação (80%)
só muda a luminosidade → paleta coesa */
--cor-900: hsl(220, 80%, 30%);
--cor-500: hsl(220, 80%, 60%);
--cor-100: hsl(220, 80%, 90%);
M07

Funções de Degradê

// linear-gradient, radial-gradient e conic-gradient

linear-gradient()
/* direção + cores */
background: linear-gradient(to right, purple, cyan);
background: linear-gradient(45deg, #f97316, #6366f1);
background: linear-gradient(to bottom, black, transparent);

/* múltiplas paradas */
background: linear-gradient(to right, red, yellow 50%, green);
radial-gradient()
background: radial-gradient(circle, purple, transparent);

/* posição do centro */
background: radial-gradient(circle at top left, cyan, transparent);

/* muito usado para "glows" e halos de luz */
background: radial-gradient(ellipse at 50% 0%, rgba(99,102,241,0.15) 0%, transparent 70%);
conic-gradient()
/* gira ao redor de um ponto */
background: conic-gradient(red, yellow, green, red);

/* gráfico de pizza */
background: conic-gradient(
  blue 0% 30%,
  orange 30% 60%,
  green 60% 100%
);
Gradientes como overlay — padrão muito usado
/* texto sobre imagem — escurece a base */
.hero {
  background-image:
    linear-gradient(to bottom, transparent, rgba(0,0,0,0.8)),
    url('foto.jpg');
  background-size: cover;
}
Colocando o gradiente antes da imagem no background-image, ele fica como uma camada por cima — criando um fade que facilita a leitura de texto sobre a foto.
M07

Funções de Formas

// clip-path para recortar elementos em qualquer forma

clip-path — recorta o elemento na forma definida
circle(50%)
ellipse(40% 50%)
polygon(triângulo)
polygon(custom)
Código das formas
clip-path: circle(50%); /* círculo */
clip-path: ellipse(40% 50% at center); /* elipse */
clip-path: inset(10px 20px round 8px); /* retângulo recortado */
clip-path: polygon(50% 0%, 100% 100%, 0% 100%); /* triângulo */

/* dica: use https://bennettfeely.com/clippy para gerar o polygon */
💡 O clip-path recorta o elemento — tudo fora da forma some, incluindo sombras e bordas. Combine com transition para animações de reveal interessantes.
M07

Funções de Referência

// var(), env(), url() e attr() — referenciar valores externos

var() — variáveis CSS (já vimos, mas com mais detalhe)
/* valor de fallback — se a variável não existir */
color: var(--cor-primaria, blue); ← usa blue se --cor-primaria não existir

/* fallback em cadeia */
color: var(--cor-primaria, var(--cor-secundaria, black));

/* var() dentro de calc() */
width: calc(var(--sidebar-w) + 24px);
url() · env() · attr()
/* url() — referencia arquivos externos */
background-image: url('foto.jpg');
background-image: url('../assets/bg.png');

/* env() — variáveis do ambiente do dispositivo */
padding-bottom: env(safe-area-inset-bottom); ← safe area iPhone
padding-top: env(safe-area-inset-top);

/* attr() — lê atributo HTML do elemento */
[data-tooltip]::after {
  content: attr(data-tooltip); ← lê o atributo data-tooltip
}

tabela resumo — CSS Functions

FunçãoCategoriaPara que serve
translate() rotate() scale()TransformMover, girar e escalar sem afetar o fluxo
calc()MatemáticaCalcular com unidades diferentes misturadas
min() max()MatemáticaDefinir limites de valor responsivos
clamp(min, val, max)MatemáticaValor fluido com mínimo e máximo — tipografia responsiva
blur() brightness() contrast()FiltroEfeitos visuais em elementos
backdrop-filter: blur()FiltroDesfoca o conteúdo atrás do elemento
rgb() rgba() hsl() hsla()CorDefinir cores com canal alpha para transparência
linear-gradient()DegradêGradiente em linha reta
radial-gradient()DegradêGradiente circular — glows e halos
conic-gradient()DegradêGradiente cônico — gráficos de pizza
clip-path: circle() polygon()FormaRecortar elemento em qualquer forma
var()ReferênciaUsar variáveis CSS com fallback
url()ReferênciaReferenciar arquivos externos
env()ReferênciaVariáveis do dispositivo (safe area, etc.)
attr()ReferênciaLer atributo HTML do elemento no CSS
M08

O que são Media Queries

// condicionais CSS — aplica estilos dependendo do contexto

Media Query é uma condicional CSS
/* SE a tela for menor que 768px */
@media (max-width: 768px) {
  .menu { display: none; }
}

/* SE a tela for maior que 1024px */
@media (min-width: 1024px) {
  .sidebar { display: block; }
}
3 formas de aplicar
/* 1. No CSS — a mais comum */
@media (max-width: 768px) { ... }

/* 2. No @import */
@import url("mobile.css")
  screen and (max-width: 768px);

/* 3. Na tag link do HTML */
<link rel="stylesheet" href="mobile.css"
  media="screen and (max-width: 768px)">
Contextos que uma media query pode checar
TELA
Largura e altura da viewport
Orientação (portrait/landscape)
Resolução e DPI
PREFERÊNCIAS
Tema escuro/claro
Modo de alto contraste
Animações reduzidas
MÍDIA
screen → telas digitais
print → impressão
all → todos (padrão)
M08

Sintaxe & screen

// anatomia de uma media query e o papel do screen

Anatomia completa
@media screen and (min-width: 768px) {
  /* estilos aqui */
}

/* ↑ tipo ↑ operador ↑ condição */
O screen é opcional — mas faz diferença?
/* sem screen — aplica em todos os tipos */
@media (max-width: 768px) { ... }

/* com screen — só em telas digitais */
@media screen and (max-width: 768px) { ... }
Na prática para projetos web, não muda nada — quase ninguém usa estilos separados para impressão.

Sem screen o padrão é all, que inclui screen e print.

Use print explicitamente quando quiser estilos específicos para quando o usuário imprimir a página.
Operadores — and · not · , (ou)
/* and — as duas condições precisam ser verdadeiras */
@media screen and (min-width: 768px) and (max-width: 1200px) { ... }

/* , (vírgula) — funciona como OR — uma ou outra */
@media (max-width: 480px), (orientation: landscape) { ... }

/* not — inverte a condição */
@media not screen { ... } /* tudo exceto telas */
M08

Rules — min-width, max-width e orientation

// as condições mais usadas no dia a dia

min-width — Mobile First
/* base: mobile */
.container { padding: 16px; }

/* tablet e acima */
@media (min-width: 768px) {
  .container { padding: 32px; }
}

/* desktop e acima */
@media (min-width: 1200px) {
  .container { padding: 48px; }
}
→ começa pelo menor e vai adicionando
max-width — Desktop First
/* base: desktop */
.container { padding: 48px; }

/* tablet e abaixo */
@media (max-width: 1199px) {
  .container { padding: 32px; }
}

/* mobile e abaixo */
@media (max-width: 767px) {
  .container { padding: 16px; }
}
→ começa pelo maior e vai reduzindo
orientation
/* portrait — altura maior que largura */
@media (orientation: portrait) {
  /* celular na vertical */
}

/* landscape — largura maior que altura */
@media (orientation: landscape) {
  /* celular na horizontal */
}
prefers-color-scheme
/* detecta o tema do sistema */
@media (prefers-color-scheme: dark) {
  body { background: #0f0f0f; }
}

@media (prefers-color-scheme: light) {
  body { background: white; }
}

/* prefers-reduced-motion — acessibilidade */
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; }
}
BreakpointValor comumContexto
Mobileaté 767pxCelulares na vertical
Tablet768px – 1023pxTablets e celulares na horizontal
Desktop1024px – 1279pxLaptops e monitores menores
Wide1280px+Monitores grandes
M08

Range Syntax — a forma moderna

// usar operadores matemáticos ao invés de min/max

Sintaxe clássica vs sintaxe range
/* clássico */
@media (min-width: 600px) { ... }
@media (max-width: 800px) { ... }

/* range — mais legível */
@media (width >= 600px) { ... }
@media (width <= 800px) { ... }

/* range entre dois valores */
@media (600px <= width <= 800px) { ... }

/* operadores disponíveis */
/* > >= < <= */
Vantagem do range — intervalo em uma linha
/* clássico — precisa de dois @media */
@media (min-width: 600px) and (max-width: 800px) {
  /* só tablet */
}

/* range — bem mais limpo */
@media (600px <= width <= 800px) {
  /* só tablet */
}
Suporte moderno — Chrome 104+, Firefox 63+, Safari 16.4+. Para projetos que precisam suportar browsers antigos, use a sintaxe clássica.
M08

Mobile-first vs Desktop-first

// qual estratégia adotar e quando

A diferença na prática
MOBILE-FIRST — min-width
/* base = mobile */
.cols { grid-template-columns: 1fr; }

/* adiciona complexidade */
@media (min-width: 768px) {
  .cols { grid-template-columns: 1fr 1fr; }
}
@media (min-width: 1200px) {
  .cols { grid-template-columns: repeat(4,1fr); }
}
✅ Recomendado — começa simples e adiciona. CSS base menor, melhor performance no mobile.
DESKTOP-FIRST — max-width
/* base = desktop */
.cols { grid-template-columns: repeat(4,1fr); }

/* reduz complexidade */
@media (max-width: 1199px) {
  .cols { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 767px) {
  .cols { grid-template-columns: 1fr; }
}
⚠️ Mais intuitivo no início mas tende a gerar mais overrides e CSS mais pesado.
Faz sentido misturar os dois? Por seção?
Tecnicamente funciona, mas não é recomendado misturar no mesmo projeto — fica difícil de manter e entender qual breakpoint sobrescreve qual.

O ideal é escolher uma estratégia e manter consistente ao longo de todo o projeto. Para projetos novos, mobile-first é o padrão do mercado hoje.
✅ Use mobile-first quando
Projeto novo · maioria dos usuários é mobile · quer melhor performance · padrão do mercado
⚠️ Desktop-first faz sentido quando
Projeto legado · usuários predominantemente desktop · adaptando um site que nasceu desktop
M08

Rem & a dica do 62.5%

// usar unidades relativas e simplificar a conversão px → rem

Por que usar rem ao invés de px?
/* px — valor fixo, não escala */
h1 { font-size: 32px; }

/* rem — relativo ao root */
h1 { font-size: 2rem; }

/* root padrão do browser = 16px
2rem = 2 × 16 = 32px */
Se o usuário aumentou o tamanho da fonte nas configurações do navegador, rem respeita essa preferência — px ignora.

Isso melhora a acessibilidade e faz o layout escalar de forma mais natural entre diferentes dispositivos.
⭐ A dica do 62.5% — conversão fácil de px para rem
/* root padrão = 16px */
/* 24px ÷ 16 = 1.5rem — difícil de cabeça */

/* com 62.5% → root = 10px */
:root {
  font-size: 62.5%; /* 10px */
}

body {
  font-size: 1.6rem; /* volta para 16px */
}

/* agora: 24px = 2.4rem 🎉 */
/* 32px = 3.2rem */
/* 14px = 1.4rem */
O root padrão do navegador é 16px. Dividir por 16 para converter para rem é trabalhoso.

Com font-size: 62.5% no `:root`, o root vira 10px. A conversão fica simplesmente mover a vírgula:
SEM a dica
16px = 1rem
24px = 1.5rem
32px = 2rem
COM 62.5%
16px = 1.6rem
24px = 2.4rem
32px = 3.2rem
⚠️ Atenção: se você usar a dica do 62.5%, lembre de redefinir o font-size no body para 1.6rem — caso contrário, todo o texto da página vai aparecer com 10px. Algumas pessoas preferem não usar essa técnica e utilizar a extensão px to rem do VS Code (atalho alt + Z).
M08

Arquivos separados & Bundler

// organização vs performance — e como resolver o conflito

O problema de separar CSS em múltiplos arquivos
✅ VANTAGEM — organização
styles/
  global.css
  layout.css
  components/
    button.css
    card.css
  pages/
    home.css
Código organizado, fácil de manter e encontrar o que precisa.
⚠️ PROBLEMA — carregamento
/* cada @import = request HTTP */
@import url("global.css");
@import url("layout.css");
@import url("button.css");
@import url("card.css");
/* 4 requests separados = lento */
Cada arquivo CSS é uma request extra ao servidor — muitos arquivos = página mais lenta.
✅ A solução — Bundler
Um bundler (como Vite, Webpack, Parcel) processa todos os arquivos CSS separados e os une em um único arquivo na hora de fazer o build para produção.

Você escreve organizado → o bundler entrega otimizado.
global.css
layout.css
button.css
card.css
main.min.css
1 arquivo · minificado · rápido
Bundlers mais usados
Vite → padrão atual, rápido, usado com React/Vue
Webpack → mais antigo, muito configurável
Parcel → zero config, bom para aprender
esbuild → extremamente rápido, base do Vite
💡 Você vai usar bundler naturalmente quando entrar no React/Next.js — eles já vêm configurados. Por enquanto, organize bem os arquivos e use @import para estudo.
🛠️ Ferramenta recomendada — Responsively App
O Responsively App é um browser focado em desenvolvimento responsivo — ele mostra vários tamanhos de tela ao mesmo tempo, sincronizados.

Ao clicar em um elemento em um breakpoint, todos os outros também respondem. Economiza muito tempo comparado a ficar redimensionando o DevTools.
/* download */
https://responsively.app/

/* gratuito e open source */
/* Windows · Mac · Linux */
M09

Transition

// suavidade ao mudar o valor de uma propriedade

As 4 propriedades do transition
/* qual propriedade animar */
transition-property: background-color;
transition-property: all; /* ⚠️ evite */

/* quanto tempo dura */
transition-duration: 0.3s;
transition-duration: 300ms;

/* quanto tempo esperar antes de iniciar */
transition-delay: 0.1s;

/* curva de aceleração */
transition-timing-function: ease;
O transition não cria animação sozinho — ele só suaviza a mudança de uma propriedade que já vai acontecer (via :hover, :focus, classe adicionada pelo JS, etc.).
⚠️ Evite transition: all
Em projetos grandes, all monitora toda e qualquer mudança de propriedade — pode causar transições indesejadas, bugs difíceis de rastrear e afetar performance. Seja específico.
/* ❌ evite */
transition: all 0.3s ease;

/* ✅ prefira */
transition: background-color 0.3s ease,
            transform 0.2s ease;
⭐ Transição no elemento, não no estado
❌ só anima na entrada — volta instantânea
.btn:hover {
  transition: background-color 0.3s; ← errado
  background-color: blue;
}
✅ anima nos dois sentidos — indo e voltando
.btn {
  transition: background-color 0.3s; ← aqui
}
.btn:hover {
  background-color: blue;
}
💡 A exceção é quando você quer animações diferentes de entrada e saída — nesse caso faz sentido ter transition nos dois, com valores diferentes.
M09

Timing Function & cubic-bezier

// a curva de aceleração — como a animação se move do início ao fim

Valores predefinidos
linear
Velocidade constante do início ao fim. Parece mecânico — raramente usado para elementos de UI.
ease — padrão
Começa rápido, desacelera no fim. Sensação natural para a maioria dos elementos.
ease-in
Começa devagar, acelera no fim. Boa para elementos que saem da tela.
ease-out
Começa rápido, chega devagar. Boa para elementos que entram na tela — chegada suave.
ease-in-out
Começa e termina devagar, rápido no meio. Boa para elementos que vão e voltam.
steps(n)
Animação em etapas discretas — sem suavização. Útil para sprites e efeitos digitais.
cubic-bezier() — curva totalmente customizada
/* os predefinidos são cubic-bezier por baixo */
ease        → cubic-bezier(0.25, 0.1, 0.25, 1)
ease-in     → cubic-bezier(0.42, 0, 1, 1)
ease-out    → cubic-bezier(0, 0, 0.58, 1)
ease-in-out → cubic-bezier(0.42, 0, 0.58, 1)
linear      → cubic-bezier(0, 0, 1, 1)

/* customizado — você define os 4 pontos */
transition-timing-function:
  cubic-bezier(.17, .67, .83, .67);
Os 4 valores são as coordenadas x1, y1, x2, y2 das alças de controle da curva.

Ninguém decora esses valores — todo mundo usa o site:
cubic-bezier.com

Você arrasta os pontos, vê a curva em tempo real e copia o valor gerado direto para o CSS.
🛠️ Ferramenta recomendada: animista.net — biblioteca de animações CSS prontas. Você escolhe o efeito, customiza os parâmetros e copia o @keyframes gerado.
M09

Shorthand & Boas Práticas

// transition em uma linha e acessibilidade

Shorthand — transition
sintaxe
transition: [property] [duration] [timing-function] [delay];
transition: background-color 0.3s ease;
transition: transform 0.2s ease-in-out 0.1s; /* com delay */

/* múltiplas — separadas por vírgula */
transition: background-color 0.3s ease,
            transform 0.2s ease-in-out,
            opacity 0.15s linear;
prefers-reduced-motion — acessibilidade
@media (prefers-reduced-motion: reduce) {
  * {
    transition: none !important;
    animation: none !important;
  }
}
Usuários com epilepsia ou sensibilidade a movimento podem configurar o sistema para reduzir animações.

Respeitar essa preferência é acessibilidade básica — e boa prática em qualquer projeto.
M09

@keyframes — construindo a linha do tempo

// definindo os estados em cada ponto da animação

from / to — início e fim
@keyframes aparecer {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* usando a animação */
.card {
  animation: aparecer 0.5s ease;
}
from = 0% e to = 100% — são atalhos.

O from pode ser omitido — se você não declarar o estado inicial, a animação começa do estado atual do elemento.

⚠️ Ao terminar, o elemento volta ao estado inicial por padrão — a menos que você use animation-fill-mode: forwards.
Porcentagens — múltiplos pontos na linha do tempo
@keyframes pulsar {
  0% { transform: scale(1); }
  50% { transform: scale(1.1); }
  100% { transform: scale(1); }
}

/* múltiplas porcentagens juntas */
@keyframes piscar {
  0%, 100% { opacity: 1; }
  50% { opacity: 0; }
}

/* elemento fica no estado final */
@keyframes entrar {
  0% { opacity: 0; }
  80% { opacity: 1; }
  /* sem 100% → fica em opacity: 1 */
}
Porcentagens são mais flexíveis que from/to — permitem quantos pontos você quiser na linha do tempo.

Múltiplas porcentagens com vírgula aplicam o mesmo estado em vários pontos — útil para loops e pulsações.

Se o último keyframe for menor que 100%, o elemento chega ao estado final antes da animação acabar e já fica lá — evitando o retorno.
M09

Propriedades da animation

// controlando cada aspecto da animação

PropriedadeValores comunsO que controla
animation-namenome do @keyframesQual animação usar
animation-duration0.5s · 300msQuanto tempo dura cada ciclo
animation-delay0.1s · 500msQuanto esperar antes de começar
animation-timing-functionease · linear · cubic-bezier()Curva de aceleração
animation-iteration-count1 · 3 · infiniteQuantas vezes repetir
animation-directionnormal · reverse · alternate · alternate-reverseSentido da animação — vai, volta ou alterna
animation-fill-modenone · forwards · backwards · bothEstado do elemento antes e depois da animação
animation-play-staterunning · pausedPausar ou retomar a animação
Detalhando os mais importantes
animation-fill-mode
/* none — volta ao estado original */
animation-fill-mode: none;

/* forwards — fica no estado final ⭐ */
animation-fill-mode: forwards;

/* backwards — aplica from antes de começar */
animation-fill-mode: backwards;

/* both — forwards + backwards */
animation-fill-mode: both;
Shorthand — animation
animation: [name] [duration] [timing] [delay] [iteration] [direction] [fill-mode];
/* simples */
animation: aparecer 0.5s ease forwards;

/* completo */
animation: pulsar 1s ease-in-out 0.2s infinite alternate both;

/* múltiplas animações */
animation: aparecer 0.5s ease forwards,
           pulsar 2s ease infinite 0.5s;
M09

animation-timeline — o futuro das animações

// vincular animações ao scroll da página ou à visibilidade do elemento

scroll() — progride com o scroll da página
@keyframes progresso {
  from { width: 0%; }
  to { width: 100%; }
}

.barra-progresso {
  animation: progresso linear;
  animation-timeline: scroll();
}
Rolar a página = avançar a animação. Ideal para barras de progresso de leitura.
view() — progride conforme o elemento entra na viewport ⭐
.card {
  animation: fade-up linear both;
  animation-timeline: view();
  animation-range: entry 0% entry 100%;
}

/* argumentos: deslocamento topo / fundo */
animation-timeline: view(100px 200px);
animation-timeline: view(10%);
O mais versátil — o efeito de "aparecer conforme rola" que você vê em todo site moderno.
animation-range — qual parte da visibilidade aciona a animação
/* entry — elemento entrando na viewport ⭐ */
animation-range: entry 0% entry 100%;

/* exit — elemento saindo da viewport */
animation-range: exit 0% exit 100%;

/* entry + exit juntos — aparece e some */
animation-range: entry 0% exit 100%;

/* cover — elemento cobrindo a viewport */
animation-range: cover 0% cover 100%;

/* contain — elemento totalmente visível */
animation-range: contain 0% contain 100%;
entry é de longe o mais usado — elementos que animam ao entrar na tela ao rolar.

entry + exit cria efeitos elegantes onde o elemento aparece e desaparece conforme passa pela viewport.

cover e contain são mais usados em efeitos de parallax e animações mais elaboradas.
/* exemplo completo — fade-up ao entrar */
@keyframes fade-up {
  from {
    opacity: 0;
    transform: translateY(40px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.elemento {
  animation: fade-up linear both;
  animation-timeline: view();
  animation-range: entry 0% entry 100%;
}
💡 Suporte atual (2025): Chrome/Edge completo, Firefox 110+, Safari ainda limitado. Verifique o caniuse.com antes de usar em produção se precisar suportar Safari.
M09

Scroll animations & JavaScript

// antes do animation-timeline, era tudo JS — e ainda tem espaço

As abordagens com JavaScript
Intersection Observer API
JS nativo sem biblioteca. Detecta quando o elemento entra na viewport e adiciona uma classe CSS com a animação.
/* JS adiciona .visivel */
.fade-up.visivel {
  opacity: 1;
  transform: none;
}
AOS — Animate On Scroll
A biblioteca mais simples. Só adiciona atributos no HTML e importa o CSS/JS.
<div
  data-aos="fade-up"
  data-aos-delay="200"
>
GSAP + ScrollTrigger
A mais poderosa — usada em sites de alto impacto. Animações complexas, sequenciadas e precisas. Você vai encontrar em projetos React avançados.
gsap.from(".card", {
  scrollTrigger: ".card",
  y: 40, opacity: 0
});
CSS puro vs JavaScript — quando usar cada um
✅ CSS puro — animation-timeline
→ Animações simples de entrada/saída
→ Fade, slide, scale ao rolar
→ Sem dependências externas
→ Melhor performance (roda na GPU)
→ Projetos sem necessidade de Safari antigo
🎯 JavaScript ainda faz sentido quando
→ Animações complexas e sequenciadas
→ Controle preciso por JS (pausar, retomar)
→ Compatibilidade com Safari antigo
→ Projetos com GSAP já integrado
→ Efeitos além do que CSS oferece

tabela resumo — transitions vs animations

CaracterísticaTransitionAnimation
Como funcionaSuaviza a mudança de uma propriedadeExecuta uma sequência definida no @keyframes
Precisa de gatilho✅ Sim — :hover, :focus, classe via JS❌ Não — começa automaticamente
Múltiplos estados❌ Só início e fim✅ Quantos quiser com %
Loop❌ Não tem✅ animation-iteration-count: infinite
ControleSimplesCompleto — direção, delay, fill-mode, etc.
Quando usarHover states, feedback de UILoading, entrada de elementos, efeitos visuais