HTML
&
CSS
Guia de Estudo
// Rocketseat Fullstack · Nível 3 · v3.0 — material completo ✅
Tags & Anatomia
// como o HTML é estruturado
// tag de abertura → <h1>
// atributo → id="titulo"
// conteúdo → Olá Mundo
// tag de fechamento → </h1>
// elemento = tudo isso junto
<img src="" alt=""> ← sem conteúdo
<br/>
< → < > → > & → &
→ espaço <br/> → quebra linha
<i> → itálico visual — não diz que é ênfase
<u> → sublinhado — sem significado extra
<s> →
<sup> → sobrescrito: x2 · emc²
<sub> → subscrito: H2O · CO2
<em> → ênfase — entonação diferente para leitores
<del> →
<ins> → inserido — conteúdo adicionado semanticamente
<mark> → destacado — relevante no contexto
<abbr> → abreviação com title explicativo
<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.
<p> texto 1 </p>
<p> texto 2 </p>
Atributos Globais
// funcionam em qualquer elemento HTML
| Atributo | Uso | Exemplo |
|---|---|---|
| id | Identificador único — só pode existir uma vez na página | <div id="menu"> |
| class | Agrupa elementos — vários elementos podem ter a mesma classe | <div class="card"> |
| style | CSS inline diretamente no elemento (evite no dia a dia) | <p style="color:red"> |
| title | Tooltip ao passar o mouse | <img title="Logo"> |
| hidden | Esconde o elemento (como display:none) | <div hidden> |
| data-* | Atributos personalizados para armazenar dados | <div data-id="42"> |
| lang | Define o idioma do conteúdo | <html lang="pt-BR"> |
| tabindex | Controla a ordem de foco com Tab | <div tabindex="0"> |
id quando o elemento é único na página (âncora, JS). Use class quando vai repetir o estilo em vários elementos.Elementos Semânticos
// tags com significado para o navegador e buscadores
<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é
→ 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.
<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
// listas não-ordenada, ordenada, item
<figure> + <figcaption>
// imagem + legenda semântica
<details> + <summary>
// accordion nativo sem JS
Estrutura & Caminhos
// anatomia do documento e como referenciar arquivos
<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>
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
| Tag | O 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) |
Anatomia & Cascata
// como o CSS é escrito e qual regra vence
color: red; ← propriedade: valor
font-size: 24px;
} ← declaração
// seletor = quem recebe o estilo
// propriedade = o que muda
// valor = como muda
<link rel="stylesheet" href="style.css">
// 2. Interno (no <head>)
<style> h1 { color: red; } </style>
// 3. Inline (evite — alta especificidade)
<h1 style="color:red">
!important sempre vence (use raramente)
2. Especificidade
inline > #id > .class > tag
3. Ordem de aparição
a última regra declarada vence
p { color: gray; } ← (0,0,1)
.texto { color: blue; } ← (0,1,0)
#titulo { color: red; } ← (1,0,0)
/* o #id vence, cor = red */
Seletores & Combinators
// como mirar em elementos específicos
div
p ← selecionado
p
mark ← selecionado
p ← selecionado
p ← não
Seletores especiais — ( ) vs [ ]
// pseudo-classes funcionais vs seletores de atributo
input:focus
li:first-child
p:last-child
: antes do nome.:has(input:checked)
:nth-child(2n+1)
:is(h1, h2, h3)
() contêm um seletor ou expressão que o CSS avalia.[disabled]
[href^="https"]
input[required]
[] contêm o nome do atributo e opcionalmente o valor.| Sintaxe | Seleciona |
|---|---|
| [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 |
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;
}
: para estados e posições, () quando a pseudo-class precisa de um argumento, e [] quando quer selecionar pelo atributo HTML.&.classe vs & .classe — o espaço que muda tudo
// modificar o próprio elemento vs selecionar um filho
&.btn-primary { background: blue; }
}
/* compila para: .btn.btn-primary */
/* elemento com as DUAS classes */
<button class="btn btn-primary">
/* ❌ não funciona */
<div class="btn">
<span class="btn-primary">
& .btn-primary { background: blue; }
}
/* compila para: .btn .btn-primary */
/* .btn-primary DENTRO de .btn */
<div class="btn">
<span class="btn-primary">
/* ❌ não funciona */
<button class="btn btn-primary">
&.primary { background: blue; }
&.danger { background: red; }
&.large { padding: 12px 24px; }
&:hover { opacity: 0.8; }
&:disabled { opacity: 0.4; }
}
& h2 { font-size: 1.4rem; }
& p { color: gray; }
& .badge { color: cyan; }
& img { width: 100%; }
}
&.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
CSS Nesting
// seletores filhos dentro do pai — sem repetição, sem pré-processador
.card h2 { color: white; }
.card p { color: gray; }
.card:hover { background: #222; }
.card .badge { color: red; }
/* .card repetido em todo lugar 😩 */
background: #111;
h2 { color: white; }
p { color: gray; }
&:hover { background: #222; }
.badge { color: red; }
}
/* tudo agrupado, sem repetir .card ✅ */
&:hover { } /* .btn:hover */
&::after { } /* .btn::after */
&.ativo { } /* .btn.ativo */
&.large { } /* .btn.large */
& + & { } /* .btn + .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 */
font-size: 3rem;
padding: 80px;
@media (max-width: 768px) {
font-size: 1.8rem;
padding: 40px;
}
}
/* responsivo dentro do próprio componente */
ul {
li {
a {
color: white;
&:hover { color: cyan; }
}
}
}
}
/* funciona — mas evite mais de 3 níveis */
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;
}
}
⚠️ 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.
Display
// como o elemento se comporta no fluxo
✅ width e height funcionam
✅ margin, padding e border completos
❌ width e height não funcionam
⚠️ padding/margin só nas horizontais
✅ width e height funcionam
✅ margin, padding e border completos
(g, p, y, j...) mesmo sem texto nenhum.
O espaço abaixo é reservado para os descenders.
display: block;
}
vertical-align: bottom;
}
line-height: 0;
}
Box Model
// todo elemento é uma caixa com 4 camadas
background-color: lightgray; ← mostra margin
padding: 1px; ← segura margin collapse
}
.boxmodel {
border: 3px solid red;
padding: 20px;
margin: 20px;
background-color: lightblue; ← padding
}
Pai e filho também colapsam se não houver padding ou border no pai.
Overflow
// o que acontece quando o conteúdo é maior que o container
linha 2
linha 3
linha 4
linha 5
linha 2
linha 3
linha 4
linha 5
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;
}
border-radius: 12px;
overflow: hidden; /* garante que a img respeite o radius */
}
.card img { width: 100%; display: block; }
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.
position: relative;
overflow: hidden; /* corta o absolute filho */
}
.badge {
position: absolute;
top: -8px;
right: -8px;
/* vai ser cortado se sair do container */
}
| Valor | O que faz | Quando usar |
|---|---|---|
| visible | Conteúdo transborda e fica visível — padrão | Quando não quer nenhum comportamento especial |
| hidden | Corta tudo que sai do container | Segurar border-radius, esconder conteúdo, efeitos visuais |
| auto | Scroll aparece só quando necessário | Containers com conteúdo variável ⭐ |
| scroll | Scrollbar sempre visível mesmo sem precisar | Evite — prefira auto |
| overflow-x / overflow-y | Controla cada eixo separadamente | Sidebar scrollável, tabelas com scroll horizontal |
Box Sizing
// como o CSS calcula o tamanho da caixa
+ padding: 20 + 20px
+ border: 10 + 10px
= Real: 360px 😱
padding já está dentro
border já está dentro
= Real: 300px ✅
box-sizing: border-box;
margin: 0;
padding: 0;
}
Background
// controlando imagens e fundos
| Propriedade | Valor | O que faz |
|---|---|---|
| background-size | cover | Preenche tudo. Pode cortar a imagem. Sem espaço vazio. ⭐ mais usado |
| background-size | contain | Mostra a imagem inteira. Pode sobrar espaço vazio nas bordas. |
| background-size | auto | Tamanho original. Pode ser cortada se maior que a caixa. |
| background-repeat | no-repeat | A imagem aparece uma única vez. |
| background-repeat | repeat | A imagem se repete como ladrilho. Comportamento padrão do CSS. |
cover + no-repeat → preenche tudo sem repetição. Padrão de banners e hero sections.object-fit
// controla como uma imagem preenche o espaço disponível — sem distorcer
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 */
}
}
| Valor | Comportamento | Quando usar |
|---|---|---|
| cover | Preenche tudo — recorta o excesso. Mantém proporção. | Grids de imagem, thumbnails, banners ⭐ mais usado |
| contain | Mostra a imagem inteira — pode sobrar espaço vazio. | Logos, ícones, imagens que não podem ser cortadas |
| fill | Estica para preencher — distorce a imagem. | Quase nunca — só se a proporção não importar |
| none | Tamanho original — pode transbordar ou sobrar espaço. | Quando quer o tamanho real da imagem |
| scale-down | Menor entre none e contain — nunca amplia. | Logos pequenos que não devem ser ampliados |
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.Shorthands
// escrever menos, fazer mais
border: 1px dashed #ccc;
// estilo é obrigatório (solid, dashed, dotted...)
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: url('foto.jpg');
background: #fff url('foto.jpg') center/cover no-repeat;
// size vem DEPOIS da position, separado por /
Dicas VS Code
// atalhos para turbinar a produtividade
static — padrão
// Todo elemento já nasce com position: static. É o fluxo normal da página.
relative — desloca a si mesmo
// O elemento se move em relação à sua posição original. O espaço que ele ocupava continua reservado.
absolute — sai do fluxo
// O elemento sai do fluxo. Se posiciona em relação ao pai mais próximo com position ≠ static.
(flutuando)
fixed — fixo na tela
// O elemento fica fixo na janela do navegador. Mesmo rolando a página, ele não se move.
sticky — gruda ao rolar
// Começa no fluxo normal. Quando você rola e ele atinge o limite definido, ele "gruda" e fica fixo.
tabela resumo — positions
| Position | Sai do fluxo? | top/left/right/bottom funciona? | Referência |
|---|---|---|---|
| static | ❌ Não | ❌ Não | — |
| relative | ❌ Não (reserva espaço) | ✅ Sim | Posição original do elemento |
| absolute | ✅ Sim | ✅ Sim | Pai com position ≠ static |
| fixed | ✅ Sim | ✅ Sim | Janela do navegador (viewport) |
| sticky | ❌ Não (até grudar) | ✅ Sim (define o ponto de "grude") | Pai + viewport |
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.
inset — shorthand de top/right/bottom/left
// inset é apenas um atalho para escrever top, right, bottom e left de uma vez.
right: 20px
bottom: 20px
left: 20px
top:0 right:0 bottom:0 left:0
bottom:40 · left:10
| Sintaxe | Equivale a |
|---|---|
| inset: 20px | top: 20px · right: 20px · bottom: 20px · left: 20px |
| inset: 10px 20px | top/bottom: 10px · right/left: 20px |
| inset: 10px 20px 30px 40px | top: 10px · right: 20px · bottom: 30px · left: 40px |
| inset: 0 | top: 0 · right: 0 · bottom: 0 · left: 0 (cobre o pai todo) |
z-index — profundidade
// z-index define qual elemento fica na frente quando dois se sobrepõem. Maior número = mais na frente.
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);
}
Variáveis CSS — --custom-properties
// Guarda valores para reutilizar. Define uma vez, usa em qualquer lugar.
--cor-principal: lightblue;
--tamanho: 16px;
}
p {
color: var(--cor-principal);
font-size: var(--tamanho);
}
body { background: var(--bg-color); }
div {
--bg-color: lightgreen; /* sobrescreve */
background: var(--bg-color);
}
Pseudo-classes — :pseudo-class
// Selecionam elementos com base em estado ou posição. Usam : (dois pontos simples).
even → pares (2,4,6...)
2n+1 → fórmula personalizada
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-elements — ::pseudo-element
// Estilizam partes específicas de um elemento. Usam :: (dois pontos duplos).
Esse é um exemplo de texto onde apenas a primeira letra recebe um estilo especial com ::first-letter. Muito usado em artigos e textos editoriais.
content: ''; /* vazio! */
position: absolute;
left: 0;
width: 4px;
height: 100%;
background: purple;
}
tabela resumo — seletores avançados
| Seletor | Tipo | O que faz | Sintaxe |
|---|---|---|---|
| --variavel | Variável | Guarda um valor para reutilizar. Sobrescrevível por elemento. | var(--nome) |
| :hover | Pseudo-class | Quando o mouse passa por cima do elemento | a:hover |
| :not() | Pseudo-class | Seleciona elementos que NÃO correspondem ao seletor | div:not(.ativo) |
| :has() | Pseudo-class | Seleciona o pai se ele contiver o seletor filho | div:has(img) |
| :root | Pseudo-class | Elemento raiz da página. Usado para variáveis globais. | :root { --x: 1; } |
| :nth-child(n) | Pseudo-class | Seleciona pelo número de posição. Aceita odd, even e fórmulas. | li:nth-child(2) |
| ::first-letter | Pseudo-element | Estiliza apenas a primeira letra do elemento | p::first-letter |
| ::before | Pseudo-element | Insere conteúdo antes do elemento via CSS. Precisa de content. | div::before |
| ::after | Pseudo-element | Insere conteúdo depois do elemento via CSS. Precisa de content. | div::after |
Flexbox vs Grid — Comportamento padrão
// O que acontece quando você só escreve display: flex ou display: grid
Direção e proporção
// Flex muda a direção. Grid controla as proporções das colunas.
Quebra de linha e áreas
// Flex quebra linha automaticamente. Grid pode mesclar células.
Alinhamento
// Os dois são ótimos para alinhar, mas de formas diferentes.
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
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. ✅
Conceitos & Eixos
// o modelo mental do Flexbox — container, itens e os dois eixos
display: flexOs itens são os filhos diretos — eles se organizam automaticamente.
cross axis → perpendicular ao main (vertical por padrão)
flex-direction
justify-content
align-items
flex-wrap
gap
flex-grow
flex-shrink
flex (shorthand)
order
align-self
flex-direction
// define a direção do main axis — onde os itens se organizam
justify-content
// distribui os itens ao longo do main axis
align-items
// alinha os itens no cross axis (perpendicular ao main)
display: flex · justify-content: center · align-items: center → centraliza em ambos os eixos ao mesmo tempo.Gap e Margin
// duas formas de criar espaço entre os itens
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 = top/bottom: 0 · left/right: autoO
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
margin: 0 auto; ← ignorado
width: 960px;
margin: 0 auto;
.container { max-width: 1200px; margin: 0 auto; padding: 0 24px; }
Multi Line — flex-wrap
// o que acontece quando os itens não cabem em uma linha
align-content: flex-start → linhas agrupadas no topo
align-content: center → linhas centralizadas
align-content: space-between → linhas distribuídas
Flex Basis / Grow / Shrink
// como o espaço disponível é distribuído entre os itens
Shorthand Flex
// flex: grow shrink basis — os três em uma linha só
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 */
| Declaração | Grow | Shrink | Basis | Quando usar |
|---|---|---|---|---|
| flex: 1 | 1 | 1 | 0 | Distribuir espaço igualmente entre os itens |
| flex: auto | 1 | 1 | auto | Cresce e encolhe respeitando o conteúdo |
| flex: none | 0 | 0 | auto | Item completamente rígido — tamanho do conteúdo |
| flex: 0 0 Xpx | 0 | 0 | Xpx | Tamanho fixo — sidebar, avatar, ícones |
Order
// reordena visualmente os itens sem mudar o HTML
tabela resumo — flexbox
| Propriedade | Aplica em | O que faz |
|---|---|---|
| display: flex | container | Ativa o flexbox |
| flex-direction | container | Define o main axis: row | row-reverse | column | column-reverse |
| justify-content | container | Distribui itens no main axis: flex-start | flex-end | center | space-between | space-around | space-evenly |
| align-items | container | Alinha itens no cross axis: stretch | center | flex-start | flex-end | baseline |
| flex-wrap | container | Permite quebra de linha: nowrap | wrap | wrap-reverse |
| gap | container | Espaço entre os itens |
| flex-basis | item | Tamanho inicial antes de crescer/encolher |
| flex-grow | item | Quanto do espaço livre o item absorve |
| flex-shrink | item | Quanto o item cede quando falta espaço |
| flex | item | Shorthand: grow shrink basis |
| order | item | Ordem visual do item (padrão: 0) |
| align-self | item | Sobrescreve align-items só para esse item |
Conceitos & Fundamentos
// o modelo mental do Grid — linhas, colunas, células e áreas
display: grid no container → filhos viram células automáticas.
track → espaço entre duas grid lines (coluna ou linha)
cell → interseção de uma linha e coluna
area → grupo de células adjacentes
→ Centralizar um elemento
→ Componentes simples
→ Quando o conteúdo dita o tamanho
→ Galerias de imagem
→ Dashboards e painéis
→ Quando o layout dita o tamanho
grid-template-columns
// define quantas colunas existem e qual o tamanho de cada uma
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!grid-template-rows
// define a altura e quantidade de linhas explícitas do grid
grid-column & grid-row
// posiciona e expande itens usando as grid lines numeradas
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 */
row:1/3
grid-template-areas
// nomeia as áreas do grid com texto — layout visual no CSS
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; }
Gap no Grid
// espaçamento entre colunas e linhas — pode ser diferente em cada eixo
gap: 8px 32px = row-gap: 8px (vertical) + column-gap: 32px (horizontal). Mesma lógica do padding/margin shorthand — primeiro vertical, depois horizontal.Shorthand grid-template
// rows e columns em uma linha só
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;
Alinhamentos
// content, items e self — três níveis de controle
Funciona como justify-content do flex, mas para as trilhas do grid inteiro.
place-items: center centraliza tudo de uma vez.
| Propriedade | Aplica em | Controla | Valores comuns |
|---|---|---|---|
| justify-content | container | Faixas de coluna no eixo horizontal | start · end · center · space-between · space-around |
| align-content | container | Faixas de linha no eixo vertical | start · end · center · space-between · space-around |
| justify-items | container | Conteúdo de cada célula — horizontal | start · end · center · stretch |
| align-items | container | Conteúdo de cada célula — vertical | start · end · center · stretch |
| place-items | container | Shorthand: align-items + justify-items | center · start end · etc. |
| justify-self | item | Esse item no eixo horizontal | start · end · center · stretch |
| align-self | item | Esse item no eixo vertical | start · end · center · stretch |
| place-self | item | Shorthand: align-self + justify-self | center · start end · etc. |
Propriedades grid auto
// como o grid lida com itens além das trilhas explícitas
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 */
}
grid-template-rows, o grid cria linhas implícitas automaticamente. O grid-auto-rows define o tamanho dessas linhas extras.
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
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
| Propriedade | Aplica em | O que faz |
|---|---|---|
| display: grid | container | Ativa o CSS Grid |
| grid-template-columns | container | Define número e tamanho das colunas |
| grid-template-rows | container | Define número e tamanho das linhas |
| grid-template-areas | container | Nomeia áreas do grid com texto |
| grid-template | container | Shorthand: rows / columns (+ areas) |
| gap | container | Espaço entre células — row-gap column-gap |
| grid-auto-rows | container | Altura das linhas implícitas (criadas automaticamente) |
| grid-auto-flow | container | Direção de preenchimento: row | column | dense |
| place-items | container | Alinha conteúdo dentro de todas as células |
| grid-column | item | Posição e span horizontal: start / end ou span N |
| grid-row | item | Posição e span vertical: start / end ou span N |
| grid-area | item | Referencia uma área nomeada no grid-template-areas |
| place-self | item | Alinha esse item específico dentro da sua célula |
Estrutura & <form>
// o container de todos os campos — atributos essenciais
action="/enviar" ← onde os dados vão
method="post" ← GET ou POST
novalidate ← desativa validação nativa
>
<!-- campos aqui -->
</form>
| Método | Quando usar |
|---|---|
| GET | Busca, filtros — dados vão na URL. Visível e compartilhável. |
| POST | Login, cadastro, envio de arquivos — dados no corpo da requisição. Seguro para dados sensíveis. |
| Atributo | O que faz | Exemplo |
|---|---|---|
| name | Identifica o campo no envio — obrigatório para o dado ser enviado | name="email" |
| id | Liga o campo ao <label> via for= | id="email" |
| value | Valor inicial ou valor enviado (em checkbox/radio) | value="sim" |
| placeholder | Texto de dica dentro do campo — some ao digitar | placeholder="Digite aqui" |
| required | Campo obrigatório — bloqueia envio se vazio | required |
| disabled | Desativa o campo — não é enviado no form | disabled |
| readonly | Só leitura — é enviado, mas não editável | readonly |
| autofocus | Foca automaticamente ao carregar a página | autofocus |
| autocomplete | Ativa ou desativa o preenchimento automático do navegador | autocomplete="off" |
Atributos Gerais dos Inputs
// funcionam na maioria dos campos de formulário
<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 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.
<input type="text" autofocus>
<input autocomplete="off">
/* dica semântica para o navegador */
<input autocomplete="email">
<input autocomplete="current-password">
<input type="text" size="10">
<input type="text" size="30">
maxlength pra isso. Na prática, prefira controlar largura via CSS (width).<button type="submit">Enviar</button>
</form>
/* input FORA do form, mas vinculado */
<input type="text" form="meu-form">
form deve bater com o id do form.| Atributo | Tipo | O que faz | Detalhe |
|---|---|---|---|
| value | texto / radio / checkbox | Valor inicial ou valor enviado | Em checkbox/radio — o que chega no back-end |
| placeholder | texto | Dica dentro do campo | Não substitui o label |
| required | todos | Campo obrigatório | Bloqueia envio se vazio |
| disabled | todos | Desativa o campo | Não é enviado no form |
| readonly | texto | Só leitura | É enviado no form |
| autofocus | todos | Foca ao carregar a página | Só um por página |
| autocomplete | texto | Sugestões do navegador | Use valores semânticos: email, name, tel... |
| size | texto | Largura em nº de caracteres | Prefira controlar via CSS width |
| form | todos | Vincula campo a um form externo | Valor deve ser o id do form |
Button
// três tipos de botão — cada um com comportamento diferente
Enviar
</button>
Limpar
</button>
onclick="fn()">
Clique
</button>
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.Input Text, Number, Email, Password
// os inputs de texto mais usados no dia a dia
type="text"
name="nome"
placeholder="Seu nome"
maxlength="50"
>
maxlength limita caracteres.type="number"
min="0"
max="100"
step="5"
>
step define o incremento das setas.type="email"
name="email"
required
>
type="password"
name="senha"
minlength="8"
>
minlength exige tamanho mínimo.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.
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] ✅
type="email"
pattern="[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,}"
title="Digite um email válido"
required
>
title define a mensagem exibida quando a validação falha.
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,}"
File, Range, Color
// inputs com interface visual própria do navegador
type="file"
accept=".jpg,.png"
multiple
>
accept filtra extensões.multiple permite vários arquivos.
type="range"
min="0"
max="100"
value="50"
>
type="color"
value="#34d399"
>
accent-color: #34d399;Checkbox, Radio & Hidden
// seleção única, múltipla e campos invisíveis
<input type="checkbox" name="skills" value="html">
<input type="checkbox" name="skills" value="css" checked>
<input type="radio" name="plano" value="free">
<input type="radio" name="plano" value="pro" checked>
<input
type="hidden"
name="user_id"
value="42"
>
Usado para passar dados que o usuário não precisa ver — como IDs, tokens, origens de página, etc.
name idêntico — apenas um do grupo pode ser selecionado. Checkbox: cada um é independente, mesmo com o mesmo name.Novos Inputs HTML5
// tipos modernos com validação e interface nativas
| type | O que exibe | Validação automática |
|---|---|---|
| date | Seletor de data nativo | Formato de data válido |
| time | Seletor de horário | Formato de hora válido |
| datetime-local | Data + hora juntos | Data e hora válidas |
| month | Seletor de mês/ano | Mês válido |
| week | Seletor de semana do ano | Semana válida |
| tel | Campo de telefone — abre teclado numérico no mobile | Nenhuma por padrão (use pattern) |
| url | Campo de URL | Formato de URL válido (http://...) |
| search | Campo de busca com botão X nativo | Nenhuma |
<input type="text"
pattern="[A-Za-z]{3,10}"
title="Só letras, 3 a 10 chars"
>
<datalist id="frutas">
<option value="Maçã">
<option value="Banana">
</datalist>
Label
// o texto descritivo do campo — essencial para acessibilidade
<label for="nome">Seu nome</label>
<input type="text" id="nome">
<label>
Seu nome
<input type="text">
</label>
Textarea & Select
// texto longo e lista de opções
name="mensagem"
rows="4"
cols="40"
placeholder="Sua mensagem..."
resize="none" ← no CSS
></textarea>
Conteúdo padrão vai entre as tags, não no value.
CSS
resize: none impede o usuário de redimensionar.
<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 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>
Útil para selects longos com muitas opções agrupadas por categoria.
Fieldset & Legend
// agrupa campos relacionados com borda e título semânticos
<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>
disabled no fieldset desativa todos os campos do grupo de uma vez.Revisão & Atributos de Validação
// validação nativa do HTML antes de chegar no JavaScript
| Atributo | Funciona em | O que valida |
|---|---|---|
| required | todos | Campo não pode estar vazio |
| minlength / maxlength | text, password, textarea | Tamanho mínimo/máximo de caracteres |
| min / max | number, range, date | Valor mínimo e máximo |
| pattern | text, email, tel, url | Regex — valida o formato |
| type | input | Valida email, url e outros formatos automaticamente |
| novalidate | form | Desativa toda a validação nativa do form |
tabela resumo — formulários HTML
| Elemento / Type | O que é | Detalhe importante |
|---|---|---|
| <form> | Container do formulário | action + method definem o destino e o modo de envio |
| <label> | Texto descritivo do campo | Liga ao campo via for="id" — essencial para acessibilidade |
| <input type="text"> | Campo de texto livre | maxlength limita caracteres |
| <input type="email"> | Campo de email | Valida formato automaticamente |
| <input type="password"> | Campo de senha | Oculta caracteres — use minlength |
| <input type="number"> | Campo numérico | min, max e step controlam o intervalo |
| <input type="checkbox"> | Múltipla escolha | Mesmo name, values diferentes |
| <input type="radio"> | Escolha única | Mesmo name = grupo exclusivo |
| <input type="file"> | Upload de arquivo | accept filtra tipos, multiple permite vários |
| <input type="hidden"> | Campo invisível | Enviado no form mas não aparece na tela |
| <textarea> | Texto multilinha | Conteúdo entre tags, não no value |
| <select> + <option> | Lista suspensa | selected define opção padrão, multiple permite vários |
| <fieldset> + <legend> | Grupo de campos | disabled no fieldset desativa todos os filhos |
| <button type="submit"> | Envia o formulário | Sempre declare o type — padrão é submit |
Funções de Transformação
// mover, girar, escalar e distorcer elementos com transform
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);
45deg
1.35
15deg
top: 50%; transform: translateY(-50%)
→ move o elemento 50% para baixo, depois volta metade da sua própria altura = centralizado.
Funções Matemáticas
// calc(), min(), max(), clamp() — valores dinâmicos no CSS
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);
⚠️ Espaço obrigatório em volta dos operadores
+ e -:calc(100%-32px) → erro
calc(100% - 32px) → correto
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);
font-size: clamp(1rem, 2.5vw, 2rem) cria texto que cresce com a tela, mas nunca sai dos limites.
Funções de Filtro
// efeitos visuais aplicados a elementos e fundos
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);
.card {
background: rgba(255,255,255,0.1);
backdrop-filter: blur(12px);
border: 1px solid rgba(255,255,255,0.2);
}
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.
Funções de Cores
// rgb(), hsl(), oklch() e como usar transparência
| Função | Sintaxe | Quando 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 |
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 */
só muda a luminosidade → paleta coesa */
--cor-900: hsl(220, 80%, 30%);
--cor-500: hsl(220, 80%, 60%);
--cor-100: hsl(220, 80%, 90%);
Funções de Degradê
// linear-gradient, radial-gradient e conic-gradient
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);
/* 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%);
background: conic-gradient(red, yellow, green, red);
/* gráfico de pizza */
background: conic-gradient(
blue 0% 30%,
orange 30% 60%,
green 60% 100%
);
.hero {
background-image:
linear-gradient(to bottom, transparent, rgba(0,0,0,0.8)),
url('foto.jpg');
background-size: cover;
}
background-image, ele fica como uma camada por cima — criando um fade que facilita a leitura de texto sobre a foto.
Funções de Formas
// clip-path para recortar elementos em qualquer forma
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 */
clip-path recorta o elemento — tudo fora da forma some, incluindo sombras e bordas. Combine com transition para animações de reveal interessantes.Funções de Referência
// var(), env(), url() e attr() — referenciar valores externos
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);
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ção | Categoria | Para que serve |
|---|---|---|
| translate() rotate() scale() | Transform | Mover, girar e escalar sem afetar o fluxo |
| calc() | Matemática | Calcular com unidades diferentes misturadas |
| min() max() | Matemática | Definir limites de valor responsivos |
| clamp(min, val, max) | Matemática | Valor fluido com mínimo e máximo — tipografia responsiva |
| blur() brightness() contrast() | Filtro | Efeitos visuais em elementos |
| backdrop-filter: blur() | Filtro | Desfoca o conteúdo atrás do elemento |
| rgb() rgba() hsl() hsla() | Cor | Definir 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() | Forma | Recortar elemento em qualquer forma |
| var() | Referência | Usar variáveis CSS com fallback |
| url() | Referência | Referenciar arquivos externos |
| env() | Referência | Variáveis do dispositivo (safe area, etc.) |
| attr() | Referência | Ler atributo HTML do elemento no CSS |
O que são Media Queries
// condicionais CSS — aplica estilos dependendo do contexto
@media (max-width: 768px) {
.menu { display: none; }
}
/* SE a tela for maior que 1024px */
@media (min-width: 1024px) {
.sidebar { display: block; }
}
@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)">
Orientação (portrait/landscape)
Resolução e DPI
Modo de alto contraste
Animações reduzidas
screen → telas digitaisprint → impressãoall → todos (padrão)
Sintaxe & screen
// anatomia de uma media query e o papel do screen
/* estilos aqui */
}
/* ↑ tipo ↑ operador ↑ condição */
@media (max-width: 768px) { ... }
/* com screen — só em telas digitais */
@media screen and (max-width: 768px) { ... }
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.
@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 */
Rules — min-width, max-width e orientation
// as condições mais usadas no dia a dia
.container { padding: 16px; }
/* tablet e acima */
@media (min-width: 768px) {
.container { padding: 32px; }
}
/* desktop e acima */
@media (min-width: 1200px) {
.container { padding: 48px; }
}
.container { padding: 48px; }
/* tablet e abaixo */
@media (max-width: 1199px) {
.container { padding: 32px; }
}
/* mobile e abaixo */
@media (max-width: 767px) {
.container { padding: 16px; }
}
@media (orientation: portrait) {
/* celular na vertical */
}
/* landscape — largura maior que altura */
@media (orientation: landscape) {
/* celular na horizontal */
}
@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; }
}
| Breakpoint | Valor comum | Contexto |
|---|---|---|
| Mobile | até 767px | Celulares na vertical |
| Tablet | 768px – 1023px | Tablets e celulares na horizontal |
| Desktop | 1024px – 1279px | Laptops e monitores menores |
| Wide | 1280px+ | Monitores grandes |
Range Syntax — a forma moderna
// usar operadores matemáticos ao invés de min/max
@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 */
/* > >= < <= */
@media (min-width: 600px) and (max-width: 800px) {
/* só tablet */
}
/* range — bem mais limpo */
@media (600px <= width <= 800px) {
/* só tablet */
}
Mobile-first vs Desktop-first
// qual estratégia adotar e quando
.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); }
}
.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; }
}
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.
Rem & a dica do 62.5%
// usar unidades relativas e simplificar a conversão px → rem
h1 { font-size: 32px; }
/* rem — relativo ao root */
h1 { font-size: 2rem; }
/* root padrão do browser = 16px
2rem = 2 × 16 = 32px */
Isso melhora a acessibilidade e faz o layout escalar de forma mais natural entre diferentes dispositivos.
/* 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 */
Com
font-size: 62.5% no `:root`, o root vira 10px. A conversão fica simplesmente mover a vírgula:24px = 1.5rem
32px = 2rem
24px = 2.4rem
32px = 3.2rem
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).Arquivos separados & Bundler
// organização vs performance — e como resolver o conflito
global.css
layout.css
components/
button.css
card.css
pages/
home.css
@import url("global.css");
@import url("layout.css");
@import url("button.css");
@import url("card.css");
/* 4 requests separados = lento */
Você escreve organizado → o bundler entrega otimizado.
layout.css
button.css
card.css
1 arquivo · minificado · rápido
Webpack → mais antigo, muito configurável
Parcel → zero config, bom para aprender
esbuild → extremamente rápido, base do Vite
@import para estudo.
Ao clicar em um elemento em um breakpoint, todos os outros também respondem. Economiza muito tempo comparado a ficar redimensionando o DevTools.
https://responsively.app/
/* gratuito e open source */
/* Windows · Mac · Linux */
Transition
// suavidade ao mudar o valor de uma propriedade
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;
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.transition: all 0.3s ease;
/* ✅ prefira */
transition: background-color 0.3s ease,
transform 0.2s ease;
transition: background-color 0.3s; ← errado
background-color: blue;
}
transition: background-color 0.3s; ← aqui
}
.btn:hover {
background-color: blue;
}
transition nos dois, com valores diferentes.
Timing Function & cubic-bezier
// a curva de aceleração — como a animação se move do início ao fim
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);
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.
animista.net — biblioteca de animações CSS prontas. Você escolhe o efeito, customiza os parâmetros e copia o @keyframes gerado.Shorthand & Boas Práticas
// transition em uma linha e acessibilidade
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;
* {
transition: none !important;
animation: none !important;
}
}
Respeitar essa preferência é acessibilidade básica — e boa prática em qualquer projeto.
@keyframes — construindo a linha do tempo
// definindo os estados em cada ponto da animação
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* usando a animação */
.card {
animation: aparecer 0.5s ease;
}
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.
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 */
}
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.
Propriedades da animation
// controlando cada aspecto da animação
| Propriedade | Valores comuns | O que controla |
|---|---|---|
| animation-name | nome do @keyframes | Qual animação usar |
| animation-duration | 0.5s · 300ms | Quanto tempo dura cada ciclo |
| animation-delay | 0.1s · 500ms | Quanto esperar antes de começar |
| animation-timing-function | ease · linear · cubic-bezier() | Curva de aceleração |
| animation-iteration-count | 1 · 3 · infinite | Quantas vezes repetir |
| animation-direction | normal · reverse · alternate · alternate-reverse | Sentido da animação — vai, volta ou alterna |
| animation-fill-mode | none · forwards · backwards · both | Estado do elemento antes e depois da animação |
| animation-play-state | running · paused | Pausar ou retomar a animação |
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;
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;
animation-timeline — o futuro das animações
// vincular animações ao scroll da página ou à visibilidade do elemento
from { width: 0%; }
to { width: 100%; }
}
.barra-progresso {
animation: progresso linear;
animation-timeline: scroll();
}
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%);
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 + 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.
@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%;
}
Scroll animations & JavaScript
// antes do animation-timeline, era tudo JS — e ainda tem espaço
.fade-up.visivel {
opacity: 1;
transform: none;
}
data-aos="fade-up"
data-aos-delay="200"
>
scrollTrigger: ".card",
y: 40, opacity: 0
});
→ Fade, slide, scale ao rolar
→ Sem dependências externas
→ Melhor performance (roda na GPU)
→ Projetos sem necessidade de Safari antigo
→ 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ística | Transition | Animation |
|---|---|---|
| Como funciona | Suaviza a mudança de uma propriedade | Executa 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 |
| Controle | Simples | Completo — direção, delay, fill-mode, etc. |
| Quando usar | Hover states, feedback de UI | Loading, entrada de elementos, efeitos visuais |