apostila_css_avancado.html · v1.0 · 2026

CSS do básico ao muito avançado

Animações, SVG, o que há de mais moderno na plataforma web — e como a inteligência artificial está mudando (e não mudando) esse trabalho.

16 módulos Demos ao vivo em cada capítulo 2 playgrounds editáveis Foco em mercado de trabalho

Módulo 0

Como usar esta apostila para todos

Esta apostila foi desenhada para levar você do básico ao muito avançado em CSS, com um objetivo prático: tornar você contratável e produtivo em times reais de front-end. Ela segue três regras:

  1. Tudo tem demonstração ao vivo. As caixas marcadas com ▶ demo ao vivo são renderizadas pelo próprio CSS que você acabou de ler. Redimensione, passe o mouse, interaja.
  2. O arquivo é o material. Abra o código-fonte desta página (Ctrl+U ou botão direito → "Exibir código-fonte"). A apostila usa as técnicas que ensina: @layer, oklch(), light-dark(), container queries, scroll-driven animations, SVG animado…
  3. Cada módulo termina em prática. Os desafios do Módulo 15 simulam tarefas reais de vaga júnior/pleno.
Dica de estudo Não leia tudo de uma vez. Um módulo por dia, reproduzindo os exemplos digitando (não copiando), fixa muito mais. Crie um arquivo laboratorio.html e teste cada conceito nele.

Legenda de níveis

básico fundação obrigatória · intermediário o dia a dia do mercado · avançado diferencia candidatos · fronteira recém-chegado à plataforma web

Módulo 1

A base que sustenta tudo básico

CSS avançado quebra na mão de quem não domina três mecanismos: cascata, especificidade e herança. Praticamente todo bug de "meu estilo não aplica" nasce aqui — e é pergunta clássica de entrevista.

1.1 A cascata: quem ganha quando duas regras brigam?

Quando duas declarações miram o mesmo elemento e a mesma propriedade, o navegador decide nesta ordem (a primeira diferença resolve a disputa):

  1. Origem e importância — estilos do usuário/navegador vs. do autor; !important inverte a ordem das origens.
  2. Camadas (@layer) — camadas declaradas depois vencem as anteriores (veja o Módulo 5).
  3. Especificidade — o "peso" do seletor.
  4. Ordem no código — em empate total, a última regra escrita vence.

1.2 Especificidade na prática

Conte como um placar de três colunas (ID, classe, elemento):

SeletorPlacarObservação
p0-0-1elemento
.card p0-1-1classe + elemento
.card .titulo0-2-0duas classes
#app .card1-1-0ID pesa mais que qualquer nº de classes
:where(.card)0-0-0:where() zera a especificidade!
style="…" (inline)vence tudo, exceto !important
No mercado Times profissionais evitam IDs e !important em estilos, justamente para manter a especificidade baixa e previsível. Se você precisa de !important para "ganhar" de outra regra, o problema quase sempre é de arquitetura — e hoje se resolve com @layer.

1.3 Herança

Propriedades de texto (color, font-*, line-height, letter-spacing) descem para os filhos automaticamente. Propriedades de caixa (margin, padding, border, background) não. Você pode forçar comportamentos com as palavras-chave inherit, initial, unset e revert.

1.4 Box model e o reset essencial

/* Faz width/height incluírem padding e borda — indispensável */
*, *::before, *::after { box-sizing: border-box; }

/* Remove margens-padrão imprevisíveis do navegador */
* { margin: 0; }

/* Mídia nunca estoura o contêiner */
img, svg, video { display: block; max-width: 100%; }

/* Formulários herdam a tipografia da página */
input, button, textarea, select { font: inherit; }

1.5 Unidades: quando usar cada uma

UnidadeRelativa a…Use para…
remfonte da raiz (html)fontes, espaçamentos, quase tudo (respeita zoom/acessibilidade)
emfonte do próprio elementopadding de botões, ícones que escalam com o texto
%o elemento pailarguras fluidas
vw / vhviewportseções de tela cheia (prefira dvh no mobile — Módulo 4)
chlargura do caractere "0"limitar linhas de texto: max-width: 65ch
pxfixabordas, sombras, detalhes que não devem escalar

1.6 Propriedades lógicas intermediário

Em vez de margin-left, o CSS moderno usa margin-inline-start: os estilos se adaptam sozinhos a idiomas RTL (árabe, hebraico) e a modos de escrita verticais. Produtos internacionais exigem isso.

/* Antes (físico)          →  Agora (lógico)               */
margin-left: auto;          margin-inline-start: auto;
padding: 8px 16px;          padding-block: 8px;
                            padding-inline: 16px;
width / height;             inline-size / block-size;
border-bottom: …;           border-block-end: …;

Módulo 2

Flexbox: layout em uma dimensão básico

Flexbox distribui itens ao longo de um eixo (linha ou coluna). É a ferramenta certa para barras de navegação, grupos de botões, alinhamento de qualquer coisa.

2.1 O modelo mental

Ao declarar display: flex, o contêiner ganha um eixo principal (controlado por flex-direction) e um eixo transversal. Memorize o mapa:

  • justify-content → distribui no eixo principal
  • align-items → alinha no eixo transversal
  • gap → espaço entre itens (esqueça margens entre irmãos)
  • flex-wrap: wrap → permite quebrar linha

2.2 flex-grow, flex-shrink, flex-basis

O atalho flex: 1 significa flex: 1 1 0 — o item pode crescer, encolher, e parte de uma base de tamanho zero. Três padrões cobrem 90% do uso real:

.item-fluido   { flex: 1; }          /* divide o espaço igualmente   */
.item-fixo     { flex: 0 0 240px; }  /* trava em 240px, nunca cresce */
.item-conteudo { flex: 0 1 auto; }   /* padrão: encolhe se preciso   */

2.3 O truque do margin: auto

Dentro de um flex container, margin-inline-start: auto "empurra" o item para o outro lado — o segredo de toda navbar:

.navbar        { display: flex; align-items: center; gap: 1rem; }
.navbar .links { margin-inline-start: auto; display: flex; gap: 1rem; }
demo ao vivo — navbar com margin auto

2.4 Centralização perfeita (pergunta de entrevista!)

/* Resposta moderna nº 1 */
.pai { display: flex; justify-content: center; align-items: center; }

/* Resposta moderna nº 2 — ainda mais curta, com Grid */
.pai { display: grid; place-items: center; }

2.5 Playground: experimente Flexbox

Edite o CSS à esquerda e veja o resultado na hora. Teste trocar row por column, center por space-between, adicionar flex-wrap: wrap

A
B
C

Módulo 3

Grid e Subgrid: layout em duas dimensões intermediário

Grid controla linhas e colunas ao mesmo tempo. Regra de bolso do mercado: Flexbox para componentes, Grid para páginas — mas não é dogma; use o que expressar melhor a intenção.

3.1 Vocabulário essencial

.pagina {
  display: grid;
  grid-template-columns: 280px 1fr;      /* sidebar fixa + resto  */
  grid-template-rows: auto 1fr auto;     /* header, main, footer  */
  gap: 1.5rem;
  min-height: 100dvh;
}

A unidade fr ("fração") distribui o espaço restante. minmax(min, max) define limites, e auto dimensiona pelo conteúdo.

3.2 O padrão mais valioso do CSS: galeria sem media query

.galeria {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: .7rem;
}

Leia assim: "crie quantas colunas couberem (auto-fit), cada uma com no mínimo 120px, dividindo a sobra igualmente (1fr)". Redimensione a janela e observe:

demo ao vivo — auto-fit + minmax (redimensione a janela)
foto 1
foto 2
foto 3
foto 4
foto 5
foto 6
auto-fit vs auto-fill auto-fit colapsa colunas vazias (itens esticam); auto-fill mantém as colunas fantasmas (itens não esticam). Teste os dois com poucos itens para ver a diferença.

3.3 Áreas nomeadas: layout que se lê

.app {
  display: grid;
  grid-template-areas:
    "header header"
    "nav    main"
    "footer footer";
  grid-template-columns: 220px 1fr;
}
.app > header { grid-area: header; }
.app > nav    { grid-area: nav; }
.app > main   { grid-area: main; }

/* Reorganizar no mobile é reescrever o desenho: */
@media (max-width: 700px) {
  .app { grid-template-areas: "header" "main" "nav" "footer";
         grid-template-columns: 1fr; }
}

3.4 Subgrid avançado

Problema clássico: cards lado a lado com títulos de tamanhos diferentes — os botões desalinhados. subgrid deixa os filhos herdarem as trilhas do grid do avô, alinhando tudo entre cards:

.cards { display: grid;
         grid-template-columns: repeat(3, 1fr); gap: 1rem; }

.card  { display: grid;
         grid-row: span 3;              /* ocupa 3 linhas do pai   */
         grid-template-rows: subgrid; } /* herda essas 3 linhas!   */
/* Agora título, texto e botão de TODOS os cards
   compartilham as mesmas linhas → alinhamento perfeito. */
No mercado Saber decidir quando usar Grid vs Flexbox, e resolver alinhamento entre cards com subgrid, é exatamente o tipo de detalhe que diferencia um portfólio júnior de um pleno.

Módulo 4

Responsividade moderna intermediário

A responsividade de 2015 era "media queries por largura de tela". A de hoje é design intrínseco: componentes que se adaptam ao espaço que recebem, tipografia fluida e novas unidades de viewport.

4.1 Mobile-first

/* Base = celular (sem media query) */
.card { padding: 1rem; }

/* Melhorias progressivas para telas maiores */
@media (min-width: 48rem)  { .card { padding: 2rem; } }
@media (min-width: 64rem)  { .card { padding: 3rem; } }

/* Sintaxe moderna de intervalo (range syntax): */
@media (48rem <= width < 64rem) { … }

4.2 Tipografia fluida com clamp()

clamp(mínimo, preferido, máximo) elimina dezenas de media queries:

h1 { font-size: clamp(2rem, 1.2rem + 3vw, 3.5rem); }
/* nunca menor que 2rem, nunca maior que 3.5rem,
   escala fluida no meio (o termo com vw dá a inclinação) */
Acessibilidade Sempre inclua um termo em rem na parte preferida (1.2rem + 3vw, não só 3vw). Sem ele, o zoom por tamanho de fonte do usuário para de funcionar — reprovação certa em auditoria de acessibilidade.

4.3 Container Queries avançado

A maior mudança em responsividade da década: componentes que respondem ao tamanho do contêiner, não da tela. O mesmo card fica horizontal na área larga e empilhado na sidebar estreita — sem saber onde está.

.onde-o-card-mora { container-type: inline-size;
                    container-name: cartao; }

.card { display: grid; gap: .8rem; }

@container cartao (min-width: 420px) {
  .card { grid-template-columns: 130px 1fr; align-items: center; }
}
demo ao vivo — arraste o canto inferior direito da moldura tracejada

Card camaleão

Eu mudo de layout quando meu contêiner passa de 420px — a janela não importa.

Container queries trazem também unidades próprias: cqw, cqh, cqi, cqb (porcentagem do contêiner). Ex.: font-size: clamp(1rem, 4cqi, 1.6rem) faz o texto escalar com o card.

4.4 Novas unidades de viewport: dvh, svh, lvh

No celular, a barra do navegador aparece e some — e o velho 100vh estoura a tela. As unidades dinâmicas resolvem:

  • svh — viewport pequeno (barra visível)
  • lvh — viewport grande (barra recolhida)
  • dvhdinâmico, acompanha a barra em tempo real. Use min-height: 100dvh para seções de tela cheia.

4.5 Media queries de preferência do usuário

@media (prefers-color-scheme: dark)     { … }  /* tema escuro   */
@media (prefers-reduced-motion: reduce) { … }  /* menos animação */
@media (prefers-contrast: more)         { … }  /* alto contraste */
@media (hover: none)                    { … }  /* telas de toque */

Respeitar essas preferências não é detalhe: é requisito de acessibilidade e aparece em checklist de code review de empresas sérias.

Módulo 5

Seletores modernos e arquitetura avançado

5.1 :is() e :where(): menos repetição

/* Antes */
header a:hover, nav a:hover, footer a:hover { color: red; }

/* Agora */
:is(header, nav, footer) a:hover { color: red; }

/* :where() é igual, mas com ESPECIFICIDADE ZERO —
   perfeito para estilos-base fáceis de sobrescrever: */
:where(h1, h2, h3) { margin-block: 0; }

5.2 :has(): o "seletor de pai" fronteira

Por décadas foi impossível estilizar um elemento com base no que existe dentro dele. :has() mudou o jogo — e eliminou muito JavaScript de interface:

/* Card que CONTÉM imagem ganha outro layout */
.card:has(img) { grid-template-rows: 160px auto; }

/* Label acende quando o checkbox interno é marcado */
label:has(input:checked) { border-color: var(--brand); }

/* Formulário inteiro reage a um campo inválido */
form:has(input:invalid) .btn-enviar { opacity: .4; pointer-events: none; }

/* Irmão anterior (!): título que antecede uma lista */
h2:has(+ ul) { margin-bottom: .3rem; }
demo ao vivo — label:has(input:checked), sem JavaScript

5.3 Nesting nativo: adeus, pré-processadores?

O aninhamento que popularizou o Sass agora é CSS puro:

.card {
  padding: 1rem;
  border: 1px solid var(--line);

  & .titulo { font-weight: 600; }     /* .card .titulo  */
  &:hover   { box-shadow: var(--shadow); }
  &.destaque { border-color: gold; }  /* .card.destaque */

  @media (min-width: 48rem) { padding: 2rem; }  /* MQ aninhada! */
}
Cuidado profissional Nesting profundo (4+ níveis) gera seletores frágeis e específicos demais — o mesmo pecado da era Sass. Regra de time: no máximo 2–3 níveis.

5.4 @layer: o fim da guerra de especificidade

Camadas de cascata deixam você declarar a ordem de prioridade da arquitetura inteira em uma linha. Regras de uma camada posterior vencem as anteriores independentemente de especificidade:

/* 1ª linha do projeto: a hierarquia oficial */
@layer reset, terceiros, base, componentes, utilitarios;

@layer reset        { /* normalizações            */ }
@layer terceiros    { /* CSS de bibliotecas       */ }
@layer base         { /* tipografia, cores globais */ }
@layer componentes  { /* .card, .btn, .modal      */ }
@layer utilitarios  { /* .mt-4, .hidden — vencem tudo */ }

Um #id.super.especifico na camada base perde para um simples .hidden em utilitarios. Isso resolve o problema que gerou décadas de !important. Esta apostila usa exatamente essa estrutura — confira no código-fonte.

5.5 @scope: estilos com fronteira fronteira

@scope (.comentarios) to (.editor) {
  /* aplica dentro de .comentarios,
     mas PARA ao encontrar .editor (buraco no escopo) */
  p { margin-block: .5rem; }
}

5.6 Convenções de nomenclatura que o mercado usa

BEM (Block, Element, Modifier) continua sendo a convenção mais pedida em vagas que usam CSS "artesanal":

.card {}              /* Bloco                    */
.card__titulo {}      /* Elemento do bloco (__)   */
.card--destaque {}    /* Modificador do bloco (--) */

Em paralelo, o utility-first (Tailwind CSS) domina startups: classes utilitárias minúsculas compostas no HTML. Você não precisa escolher um lado — precisa entender os dois e o CSS que existe por baixo. Entrevistadores percebem rapidamente quem só sabe Tailwind sem saber CSS.

Módulo 6

Variáveis CSS e @property avançado

6.1 Custom properties: o sistema nervoso do design

:root {
  --brand: oklch(48% .19 275);
  --radius: 10px;
  --espaco: 1rem;
}
.btn {
  background: var(--brand);
  border-radius: var(--radius);
  padding: var(--espaco) calc(var(--espaco) * 2);
}
/* Fallback se a variável não existir: */
color: var(--texto, #333);

Diferente de variáveis de Sass, elas vivem no navegador: mudam em tempo real, respeitam a cascata (pode redefinir --brand só dentro de .tema-escuro) e são lidas/alteradas via JavaScript. São a base de design tokens, tema claro/escuro e white-label — vocabulário que impressiona em entrevista.

6.2 Escopo local = componentes configuráveis

.avatar { --tamanho: 40px;
          width: var(--tamanho); height: var(--tamanho); }

.avatar--grande { --tamanho: 72px; }  /* só muda o token! */

6.3 @property: variáveis com superpoderes fronteira

Por padrão o navegador trata variáveis como texto opaco — por isso não sabe animá-las. @property registra o tipo, e aí sim a variável vira animável. É assim que se anima um gradiente (que nativamente não é animável!):

@property --angulo {
  syntax: "<angle>";     /* o tipo destrava a interpolação */
  inherits: false;
  initial-value: 20deg;
}
.btn-gradiente {
  background: linear-gradient(var(--angulo), #4338ca, #0891b2);
  transition: --angulo .6s ease;   /* animando a VARIÁVEL */
}
.btn-gradiente:hover { --angulo: 200deg; }
demo ao vivo — gradiente animado via @property (passe o mouse)

Módulo 7

Cores de nova geração fronteira

7.1 Por que abandonar o HEX/HSL: oklch()

oklch(luminosidade croma matiz) é perceptualmente uniforme: dois azuis e dois amarelos com o mesmo valor de L parecem igualmente claros ao olho humano (em HSL, não parecem — um amarelo 50% "brilha" muito mais que um azul 50%). Consequências práticas:

  • Paletas inteiras variando só um número, com contraste previsível;
  • Acesso a cores mais vivas em telas P3 (fora do alcance do sRGB);
  • Gradientes sem a "zona morta" acinzentada do RGB.
--brand:       oklch(48% 0.19 275);  /* L  C  H          */
--brand-claro: oklch(85% 0.08 275);  /* mesma matiz, + luz */
--brand-texto: oklch(30% 0.10 275);  /* mesma matiz, − luz */

7.2 color-mix(): misture no navegador

/* 25% da marca sobre transparente = tinta de destaque */
background: color-mix(in oklch, var(--brand) 25%, transparent);

/* hover 15% mais escuro, sem inventar outro hex: */
background: color-mix(in oklch, var(--brand), black 15%);

7.3 Relative Color Syntax: cores derivadas

/* "pegue --brand, desconte 0.25 de luminosidade" */
--brand-escuro: oklch(from var(--brand) calc(l - 0.25) c h);

/* mesma cor, 50% de opacidade */
--brand-vidro:  oklch(from var(--brand) l c h / 50%);

Um único token gera a família inteira de tons — o sonho dos design systems.

demo ao vivo — família de tons derivada de UM token oklch
+35 L
+20 L
token
−12 L
−55 H

7.4 light-dark(): tema escuro em uma linha

:root { color-scheme: light dark; }  /* obrigatório */

body {
  color:      light-dark(#1a2233, #e8ecf4);
  background: light-dark(#fafbfd, #14181f);
}

O navegador escolhe o valor conforme o tema do sistema (ou o color-scheme forçado por você). O botão "Alternar tema" desta apostila funciona exatamente assim: o JavaScript só troca um atributo; quem faz todo o trabalho é light-dark(). Complete com accent-color: var(--brand) para tingir checkboxes, radios e ranges nativos.

Módulo 8

Transitions e Transforms intermediário

8.1 Transition: interpolando estados

.btn {
  background: var(--brand);
  transition: background .25s ease, transform .15s ease;
  /*          o quê       tempo  curva                  */
}
.btn:hover  { background: var(--brand-2); }
.btn:active { transform: translateY(1px) scale(.98); }
Evite transition: all Ele anima propriedades que você não previu (inclusive quando o tema muda!) e força o navegador a observar tudo. Liste as propriedades explicitamente — isso aparece em code review.

8.2 Curvas de tempo: onde mora a "sensação" da interface

CurvaSensaçãoUso típico
ease-outrápido → suaveelementos entrando (padrão de UI)
ease-insuave → rápidoelementos saindo
cubic-bezier(.2,.8,.2,1)"expressiva", desacelera longamodais, painéis (padrão Material)
linear(…) modernaqualquer curva, até molasbounce/spring sem JavaScript
steps(n)saltos discretossprites, relógios, "máquina de escrever"

8.3 Transform: mover sem custo

transform: translate(-50%, -50%);   /* mover        */
transform: scale(1.05);             /* escalar      */
transform: rotate(45deg);           /* girar        */
transform: skewX(12deg);            /* inclinar     */

/* Sintaxe moderna: propriedades individuais, combináveis! */
translate: 0 -4px;
scale: 1.05;
rotate: 45deg;

Com as propriedades individuais (translate, scale, rotate), você anima cada uma em transições separadas sem sobrescrever as outras — antes era preciso repetir a lista inteira de transforms.

8.4 Performance: a regra de ouro da animação avançado

O navegador renderiza em etapas: Layout → Paint → Composite. Animar width, height, top, margin refaz o layout da página a cada frame (caro, trava em celulares). Animar transform e opacity acontece direto no compositor, geralmente na GPU — 60fps de graça.

/* ❌ dispara layout a cada frame */
.menu { left: -300px; transition: left .3s; }

/* ✅ só compositor, suave em qualquer aparelho */
.menu { translate: -300px 0; transition: translate .3s; }

will-change: transform avisa o navegador para preparar a otimização — use com moderação e só em elementos que realmente animam com frequência.

8.5 3D: perspective e o card flip

.palco  { perspective: 900px; }          /* no PAI          */
.carta  { transform-style: preserve-3d;
          transition: transform .7s cubic-bezier(.2,.8,.2,1); }
.palco:hover .carta { transform: rotateY(180deg); }
.face   { position: absolute; inset: 0;
          backface-visibility: hidden; } /* esconde o verso */
.verso  { transform: rotateY(180deg); }
demo ao vivo — card flip 3D (passe o mouse ou foque com Tab)
Frente
🂡
Verso
rotateY(180deg)

Módulo 9

@keyframes e animação avançada avançado

9.1 Anatomia completa

@keyframes flutuar {
  0%   { translate: 0 0; }
  50%  { translate: 0 -12px; rotate: 2deg; }
  100% { translate: 0 0; }
}
.balao {
  animation: flutuar 3s ease-in-out infinite;
  /* nome | duração | curva | delay | iterações |
     direção (alternate/reverse) | fill-mode | play-state */
}

As duas propriedades que mais confundem iniciantes (e caem em entrevista):

  • animation-fill-mode: forwards — o elemento fica no estado final em vez de "pular de volta";
  • animation-direction: alternate — vai e volta, ótimo com infinite.
demo ao vivo — loader com animation-delay escalonado

9.2 steps(): animação de sprite (jogos!)

.personagem {
  width: 64px; height: 64px;
  background: url(sprite-corrida.png) 0 0 / auto 64px;
  animation: correr .8s steps(8) infinite;  /* 8 quadros */
}
@keyframes correr { to { background-position: -512px 0; } }

9.3 O problema histórico: animar display: none fronteira

Durante 25 anos foi impossível fazer fade em elementos que entram/saem do DOM com display — todo mundo recorria a JavaScript e setTimeout. O CSS moderno resolveu com duas peças:

.toast {
  transition: opacity .4s, translate .4s,
              display .4s allow-discrete;  /* 1) display anima "no fim" */
  opacity: 1; translate: 0 0;
}
.toast[hidden] { display: none; opacity: 0; translate: 0 12px; }

@starting-style {          /* 2) estado do PRIMEIRO frame ao entrar */
  .toast { opacity: 0; translate: 0 12px; }
}
demo ao vivo — entrada/saída animada sem JavaScript de animação
✅ Salvo com sucesso — animado por @starting-style + allow-discrete

9.4 animation-composition: animações que se somam

.item {
  animation: flutuar 3s infinite, balancar 2s infinite;
  animation-composition: add;  /* soma os transforms
                                  em vez de a última vencer */
}

9.5 Acessibilidade de movimento — inegociável

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

Pessoas com distúrbios vestibulares passam mal com paralaxe e movimentos amplos. Todo projeto profissional embarca esse bloco (esta apostila embarca — teste ativando "reduzir movimento" no seu sistema).

Módulo 10

Scroll-driven animations e View Transitions fronteira

As duas APIs mais impactantes chegadas ao CSS recentemente. O que exigia bibliotecas JavaScript (GSAP ScrollTrigger, AOS) agora é declarativo — rodando fora da thread principal, sem travar.

10.1 animation-timeline: scroll() — progresso da rolagem

A linha do tempo da animação deixa de ser o relógio e passa a ser a barra de rolagem. A barra de progresso no topo desta página é isto:

.progresso {
  position: fixed; inset: 0 0 auto 0; height: 4px;
  background: linear-gradient(90deg, var(--brand), var(--brand-2));
  transform-origin: 0 50%; transform: scaleX(0);
  animation: crescer linear both;
  animation-timeline: scroll(root);   /* rolagem da página! */
}
@keyframes crescer { to { transform: scaleX(1); } }

10.2 animation-timeline: view() — revelar ao entrar na tela

A animação progride conforme o próprio elemento cruza a viewport. O clássico "fade-in ao rolar", 100% CSS:

.card {
  animation: surgir both;
  animation-timeline: view();
  animation-range: entry 0% entry 80%; /* do início da entrada
                                          até 80% dela           */
}
@keyframes surgir {
  from { opacity: 0; transform: translateY(28px) scale(.98); }
}
demo ao vivo — os itens abaixo surgem com view() (role para cima e para baixo)
🪂 Eu entro em cena guiado pela rolagem…
🎯 …sem nenhum IntersectionObserver…
⚡ …e a animação roda fora da thread principal.
Progressive enhancement Envolva em @supports (animation-timeline: view()) { … }: navegadores sem suporte simplesmente mostram o conteúdo estático. Site funciona para todos; a experiência melhora onde dá.

10.3 View Transitions API: transições entre estados e páginas

O efeito "app nativo" — um card que voa e vira a página de detalhes — chegou à web. Na mesma página:

/* JS: embrulhe a mudança de DOM */
document.startViewTransition(() => atualizarConteudo());

/* CSS: o navegador cria capturas ::view-transition-old/new
   e você anima a troca: */
::view-transition-old(root) { animation: fade-out .25s ease both; }
::view-transition-new(root) { animation: fade-in  .25s ease both; }

/* Elemento que "viaja" entre os estados: */
.card-destaque { view-transition-name: card-hero; }

E entre páginas diferentes (MPA), sem framework e sem JavaScript:

@view-transition { navigation: auto; }
/* pronto: navegação entre páginas do mesmo site com crossfade;
   nomeie elementos com view-transition-name para animações "hero" */
No mercado Essas duas APIs estão substituindo uma classe inteira de dependências JavaScript. Demonstrar um projeto com view transitions + scroll-driven animations no portfólio sinaliza "esta pessoa acompanha a plataforma" — exatamente o que times seniores procuram.

Módulo 11

SVG do zero básico

SVG (Scalable Vector Graphics) é imagem descrita por código XML: vetorial (nítida em qualquer zoom), leve, acessível, estilizável com CSS e animável. Ícones, logos, ilustrações, gráficos de dashboards — tudo isso no mercado é SVG.

11.1 O sistema de coordenadas: viewBox

<svg viewBox="0 0 100 100" width="200">
  <!-- "meu desenho vive num plano de 100×100 unidades,
       começando em (0,0)" — o width só ESCALA esse plano -->
</svg>

viewBox="min-x min-y largura altura" é o conceito nº 1 de SVG: separa o sistema de desenho (interno) do tamanho exibido (externo). É por isso que SVG escala sem perder qualidade.

11.2 Formas básicas

<svg viewBox="0 0 220 120">
  <rect x="10" y="10" width="60" height="60" rx="8" fill="#4338ca"/>
  <circle cx="120" cy="40" r="30" fill="#0891b2"/>
  <line x1="170" y1="10" x2="210" y2="70"
        stroke="#d97706" stroke-width="4" stroke-linecap="round"/>
  <polygon points="30,110 60,80 90,110" fill="#059669"/>
  <text x="120" y="105" font-size="14">Olá, SVG!</text>
</svg>
demo ao vivo — o código acima, renderizado
Olá, SVG!

11.3 <path>: a forma que desenha qualquer coisa

O atributo d é uma sequência de comandos de caneta. Os essenciais:

ComandoSignificadoExemplo
M x yMover a caneta (sem desenhar)M 10 80
L x yLinha reta até o pontoL 90 20
H x / V ylinha Horizontal / VerticalH 120
C x1 y1, x2 y2, x ycurva de Bézier Cúbica (2 controles)curvas suaves
Q x1 y1, x yBézier Quadrática (1 controle)arcos simples
A rx ry …Arco elípticofatias de pizza, medidores
Zfecha o caminho

Minúsculas (m, l, c…) usam coordenadas relativas ao ponto atual. Na prática você desenha no Figma/Illustrator e exporta — mas ler um d é o que permite editar, otimizar e animar.

11.4 fill, stroke e o truque do currentColor

/* SVG inline é estilizável por CSS normal: */
.icone { fill: currentColor; }   /* herda a cor do TEXTO ao redor */
.icone path { stroke: var(--brand); stroke-width: 2;
              stroke-linecap: round; stroke-linejoin: round; }

fill: currentColor é o padrão universal de bibliotecas de ícones: o ícone acompanha automaticamente a cor do texto do botão/link onde está — inclusive no hover e no tema escuro.

11.5 As três formas de usar SVG

FormaComoQuando
Arquivo externo<img src="logo.svg"> ou background-imageimagens estáticas; cacheável, mas não estilizável por CSS da página
Inline<svg>…</svg> direto no HTMLícones e ilustrações que você quer estilizar e animar — o caso principal desta apostila
Sprite<symbol id="x"> + <use href="#x">sistemas de ícones: define uma vez, usa em todo lugar (Módulo 12)

11.6 Acessibilidade de SVG — desde o primeiro dia

<!-- SVG informativo: -->
<svg role="img" aria-label="Crescimento de 32% nas vendas">…</svg>

<!-- SVG decorativo: esconda dos leitores de tela -->
<svg aria-hidden="true" focusable="false">…</svg>

Módulo 12

SVG avançado e animado avançado

12.1 O efeito de "desenho à mão": stroke-dasharray

A técnica de animação de SVG mais pedida do mercado. A ideia: um tracejado (stroke-dasharray) cujo traço tem o comprimento total do caminho, deslocado para fora da vista (stroke-dashoffset) e animado de volta a zero — parecendo que a linha se desenha:

<!-- pathLength="1" normaliza o comprimento: chega de medir com JS -->
<path d="M10 50 C 40 10, 80 90, 120 50 …"
      pathLength="1" fill="none" stroke="#4338ca" stroke-width="3"/>
path {
  stroke-dasharray: 1;      /* 1 traço do tamanho do caminho */
  stroke-dashoffset: 1;     /* começa 100% "escondido"       */
  animation: desenhar 3s ease forwards;
}
@keyframes desenhar { to { stroke-dashoffset: 0; } }
demo ao vivo — assinatura que se desenha em loop

12.2 CSS anima SVG como anima HTML — com dois cuidados

.estrela {
  transition: fill .3s, transform .3s;
  transform-origin: center;   /* 1) origem no centro da forma… */
  transform-box: fill-box;    /* 2) …RELATIVA à própria forma
                                    (sem isso, gira em torno do
                                    canto 0,0 do SVG inteiro!)  */
}
.estrela:hover { fill: gold; transform: scale(1.25) rotate(15deg); }
demo ao vivo — transform-box: fill-box (passe o mouse nas estrelas)

12.3 Movimento ao longo de um caminho: offset-path

Qualquer elemento HTML ou SVG pode percorrer um trajeto — órbitas, foguetes seguindo curvas, timelines:

.planeta {
  offset-path: ellipse(80px 50px at 50% 50%);
  /* aceita também: path("M0 0 C…"), ray(45deg), url(#trilha) */
  animation: orbitar 5s linear infinite;
}
@keyframes orbitar { to { offset-distance: 100%; } }
demo ao vivo — offset-path elíptico

12.4 Gradientes e filtros dentro do SVG

<defs>
  <linearGradient id="grad" x1="0" y1="0" x2="1" y2="1">
    <stop offset="0%"  stop-color="#4338ca"/>
    <stop offset="100%" stop-color="#0891b2"/>
  </linearGradient>

  <filter id="brilho">
    <feGaussianBlur stdDeviation="4" result="blur"/>
    <feMerge>
      <feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/>
    </feMerge>
  </filter>
</defs>

<circle r="40" fill="url(#grad)" filter="url(#brilho)"/>

Filtros SVG (feGaussianBlur, feDropShadow, feTurbulence para texturas e "gosma", feColorMatrix) são um mundo próprio — e podem ser aplicados a HTML comum via filter: url(#id) no CSS. Efeitos "impossíveis" de hover em sites premiados costumam ser isso.

12.5 Sistema de ícones profissional: <symbol> + <use>

<!-- Uma vez, no topo do HTML (ou arquivo sprite.svg): -->
<svg style="display:none">
  <symbol id="i-check" viewBox="0 0 24 24">
    <path d="M20 6 9 17l-5-5" fill="none"
          stroke="currentColor" stroke-width="2.5"/>
  </symbol>
</svg>

<!-- Em qualquer lugar, quantas vezes quiser: -->
<svg class="icone" width="20" height="20" aria-hidden="true">
  <use href="#i-check"/>
</svg>

12.6 Playground: edite um SVG ao vivo

Mude coordenadas, cores, o d do path, o viewBox… e veja na hora. Sugestões: troque r="28", mude o stroke-width, arraste os pontos de controle da curva C.

Otimização SVGs exportados de ferramentas de design vêm inchados (metadados, casas decimais infinitas). Antes de subir para produção, passe no SVGO (ou no site SVGOMG) — reduções de 60–90% são normais.

Módulo 13

CSS de produção: o que os times esperam avançado

Saber propriedades não basta; o mercado paga por CSS manutenível, acessível e rápido. Este módulo é o seu checklist de profissional.

13.1 Arquitetura em camadas (o padrão emergente)

@layer reset, tokens, base, layout, componentes, utilitarios;
/* + design tokens como custom properties em :root
   + componentes com escopo próprio (BEM, CSS Modules ou @scope)
   + utilitários por último, vencendo sem !important */

13.2 Checklist de acessibilidade (WCAG) que cai no dia a dia

  • Contraste mínimo 4.5:1 para texto (ferramenta: qualquer contrast checker; em breve nativo com a função contrast-color());
  • :focus-visible sempre estilizado — nunca outline: none sem substituto;
  • prefers-reduced-motion respeitado (Módulo 9.5);
  • Zoom de texto até 200% sem quebrar (use rem, evite alturas fixas);
  • Alvos de toque com no mínimo ~44×44px em mobile;
  • Nunca comunicar estado por cor (some ícone/texto).

13.3 Performance de CSS

  • Anime transform/opacity, não layout (Módulo 8.4);
  • content-visibility: auto em seções longas fora da tela — o navegador pula o render delas (ganhos enormes em páginas extensas);
  • contain: layout paint isola componentes e reduz recálculos;
  • Carregue fontes com font-display: swap e pré-conecte ao host;
  • Evite seletores dependentes de estrutura profunda (div > div > ul li span): frágeis e difíceis de manter.

13.4 Truques modernos que economizam JavaScript

Antes (JS)Agora (CSS/HTML)
Acordeão com cliques<details>/<summary> (+ interpolate-size: allow-keywords para animar até height: auto)
Carrossel com bibliotecascroll-snap-type + scroll-snap-align
Modal com foco preso na mão<dialog> + ::backdrop
Tooltip/menu posicionado por JSPopover API + Anchor Positioning (anchor-name/position-anchor) — a fronteira mais recente
Máscara de aspecto por cálculoaspect-ratio: 16 / 9
Truncar texto em N linhasline-clamp: 3

13.5 Ferramentas que aparecem em vagas

Tailwind CSS (utility-first), CSS Modules e styled-components (em React), Sass (legado ainda enorme), PostCSS (transformações de build), Stylelint (lint), Lighthouse/DevTools (auditoria). Aprenda os fundamentos primeiro: quem domina CSS aprende qualquer uma dessas em dias.

Módulo 14

IA e o futuro do trabalho com CSS fronteira

Uma resposta honesta, sem hype nem pânico, sobre como a inteligência artificial está mudando este ofício — escrita, aliás, com a ajuda de uma IA, o que torna o exemplo concreto.

14.1 O que a IA já mudou

  • Escrever CSS "commodity" ficou quase instantâneo. Assistentes (GitHub Copilot, Claude, ChatGPT, Cursor e afins) geram layouts, componentes e animações a partir de descrições em texto ou de screenshots. O trabalho de digitar um card responsivo do zero deixou de ser diferencial.
  • Design-to-code encurtou. Ferramentas convertem telas do Figma em HTML/CSS razoável; a IA faz a primeira passada e o dev refina.
  • Debug acelerou. Colar um trecho quebrado e perguntar "por que o z-index não funciona aqui?" resolve em segundos o que levava horas de tentativa e erro.
  • A barreira de entrada caiu — o que também significa que saber o básico vale menos do que valia.

14.2 O que a IA (ainda) não faz bem — e onde você vale ouro

  • Julgamento visual e de produto. A IA gera um resultado plausível; decidir se ele serve à marca, ao usuário e ao contexto continua humano. Código gerado tende ao genérico — olho treinado percebe.
  • Arquitetura e consistência de longo prazo. Manter um design system coerente por anos, decidir tokens, camadas e convenções de um produto real: a IA ajuda peça por peça, mas não carrega a visão do todo.
  • Auditoria do que foi gerado. IA produz com confiança código sutilmente errado: acessibilidade ignorada, animação de width em vez de transform, especificidade bagunçada, APIs inventadas. Quem não sabe CSS não consegue revisar CSS. Este é o ponto central: os fundamentos desta apostila são o que transforma a IA de risco em alavanca.
  • Contexto de código legado — entender por que aquele hack de 2017 existe antes de removê-lo.
  • Responsabilidade. Quando o site quebra em produção, quem responde é você, não o modelo.

14.3 Como o papel do dev front-end está se redesenhando

Menos tempo em…Mais tempo em…
Digitar CSS boilerplateEspecificar bem o problema (o "prompt" é uma spec)
Procurar sintaxe na documentaçãoRevisar, testar e endurecer código gerado
Reproduzir mockups pixel a pixelDecisões de sistema: tokens, acessibilidade, performance
Tarefas isoladasOrquestrar ferramentas (IA, build, CI, design) num fluxo

14.4 Usando IA a seu favor no estudo e no trabalho

  1. Peça explicações, não só código. "Explique por que essa solução usa grid e não flex" ensina; "faça pra mim" só entrega.
  2. Dê contexto no prompt: navegadores-alvo, convenção do time (BEM? Tailwind?), requisitos de acessibilidade. Saída genérica vem de pedido genérico.
  3. Trate toda saída como código de estagiário talentoso: revise acessibilidade, performance e casos extremos antes de commitar.
  4. Use a IA para praticar entrevista: peça perguntas do Módulo 15 e defenda suas respostas.
  5. Continue lendo a plataforma (MDN, release notes dos navegadores): modelos têm data de corte e frequentemente desconhecem — ou alucinam — as APIs mais novas, justamente as que dão vantagem competitiva.
Resumo para a carreira A IA está automatizando a digitação do CSS, não o entendimento dele. O profissional que sobe de valor é o que combina: fundamentos sólidos (para auditar), conhecimento de fronteira (que os modelos ainda erram), olho de design e acessibilidade (que exigem julgamento) e fluência em usar IA como ferramenta. É exatamente a trilha desta apostila.

Módulo 15

Desafios de mercado, entrevistas e portfólio

15.1 Cinco desafios progressivos (faça na ordem)

Desafio 1 · Card de produto responsivo básico

Tarefa: um card com imagem, título, descrição, preço e botão. Empilhado em telas estreitas; imagem ao lado do texto quando o contêiner passa de 420px (container query, Módulo 4). Botão com estados :hover, :active e :focus-visible.

Critérios de aceite: zero media queries de tela; funciona com zoom de 200%; transições apenas em transform/cores.

Desafio 2 · Dashboard em Grid intermediário

Tarefa: layout de app com header, sidebar, área principal e footer usando grid-template-areas (Módulo 3). No mobile, a sidebar vai para baixo. Galeria interna de cards com auto-fit/minmax. Bônus: alinhe os botões dos cards com subgrid.

Desafio 3 · Tema claro/escuro com design tokens avançado

Tarefa: defina a paleta inteira em oklch() como custom properties; derive hovers e superfícies com color-mix()/relative colors (Módulo 7); implemente o tema com light-dark() + um botão que alterna color-scheme. Contraste mínimo 4.5:1 nos dois temas.

Desafio 4 · Loader e ilustração SVG animada avançado

Tarefa: desenhe um logo simples em <path> (pode exportar do Figma e otimizar no SVGO). Anime o traçado com stroke-dasharray + pathLength="1" (Módulo 12); adicione um elemento orbitando com offset-path; tudo pausado sob prefers-reduced-motion.

Desafio 5 · Landing page de fronteira fronteira

Tarefa: uma landing com: barra de progresso de leitura (scroll()), seções que surgem com view(), navegação entre duas páginas com @view-transition, toast animado com @starting-style (Módulos 9–10). Envolva tudo em @supports para degradar com elegância. Este projeto, bem documentado no README, é ouro no portfólio.

15.2 Perguntas reais de entrevista (com o caminho da resposta)

"Explique especificidade. O que vence: #a .b ou .a .b .c .d?"

#a .b (1-1-0) vence (0-4-0): nenhuma quantidade de classes supera um ID. Cite o placar de três colunas, mencione :where() zerando especificidade e @layer como solução arquitetural moderna (Módulos 1 e 5).

"Flexbox ou Grid — quando usar cada um?"

Flexbox: um eixo, tamanho ditado pelo conteúdo (navbars, grupos de controles). Grid: duas dimensões, o layout dita o conteúdo (páginas, dashboards, galerias). Mostre que conhece subgrid e o padrão auto-fit/minmax — sinaliza atualização (Módulos 2–3).

"Como você faria uma animação suave em um celular fraco?"

Animar só transform/opacity (compositor/GPU, sem layout nem paint), will-change pontual, respeitar prefers-reduced-motion, e citar scroll-driven animations rodando fora da main thread (Módulos 8–10).

"O que é reflow (layout) e repaint? Como evitar?"

Reflow: recálculo de geometria (mudou width, font-size…); repaint: redesenho de pixels (mudou color, box-shadow). Evita-se animando propriedades de compositor, agrupando leituras/escritas de DOM e isolando com contain/content-visibility (Módulos 8 e 13).

"Como você estilizaria um componente sem vazar estilos para o resto do app?"

Convenção de nomes (BEM), CSS Modules/escopo do framework, @scope nativo, ou Shadow DOM em web components; e @layer para controlar quem vence quem (Módulo 5).

"Você usa IA para escrever CSS? Como garante a qualidade?"

Pergunta cada vez mais comum. Resposta forte: "uso para acelerar boilerplate e explorar alternativas, mas reviso como revisaria código de terceiros — acessibilidade, performance de animação, especificidade e suporte de navegador — porque sei o que procurar" (Módulo 14). Demonstra maturidade, não dependência.

15.3 Portfólio que contrata

  • 3 projetos profundos > 15 rasos. Os desafios 3, 4 e 5 acima são um portfólio completo.
  • README explica decisões: "usei container queries porque o card aparece em três contextos" vale mais que o código em si.
  • Publique (GitHub Pages, Netlify, Vercel) e teste no celular de verdade;
  • Rode o Lighthouse e exiba as notas de Acessibilidade e Performance;
  • Grave um GIF/vídeo curto das animações para o README — recrutador não roda projeto;
  • Um clone caprichado de UI conhecida (player de música, feed) mostra olho para detalhe — deixe claro que é estudo.

Apêndice

Referências para continuar

  • MDN Web Docs (developer.mozilla.org) — a documentação de referência; consulte para toda propriedade citada aqui.
  • web.dev/learn/css — curso gratuito do time do Chrome; e o blog do Chrome para novidades da plataforma.
  • CSS-Tricks — guias visuais clássicos de Flexbox e Grid.
  • caniuse.com — suporte de navegadores; procure também pelo selo Baseline nas documentações.
  • Kevin Powell (YouTube) — o professor de CSS mais didático da internet.
  • Josh W. Comeau — artigos interativos profundos (especialmente sobre animação e Flexbox).
  • State of CSS (stateofcss.com) — pesquisa anual: o que o mercado usa e o que vem aí.
  • SVGOMG — otimizador de SVG online; svg-path-editor (yqnn.github.io) para entender o atributo d visualmente.
Último conselho Navegadores evoluem todo mês e modelos de IA têm data de corte — inclusive o que escreveu esta apostila (início de 2026). Verifique o suporte atual das APIs marcadas como fronteira antes de usar em produção. A habilidade de checar a fonte primária é, em si, uma habilidade de mercado.