Apostila completa · 6 módulos

CSS do básico ao mercado de trabalho

Um guia prático para quem já conhece HTML e quer dominar CSS de verdade — com exemplos renderizados ao vivo, exercícios com solução, mini-projetos para o portfólio e preparação para entrevistas. Fecha com um módulo de SCSS.

  • Pré-requisitoHTML básico
  • FormatoTeoria + prática + entrevista
  • BônusMódulo de SCSS

Como usar esta apostila

Cada seção segue o mesmo ritmo: conceito → código → resultado ao vivo → exercício. Os blocos tracejados roxos mostram o CSS realmente aplicado no seu navegador — esta própria página é estilizada com as técnicas que ela ensina (abra o código-fonte e confira!).

Você vai encontrar três tipos de destaque ao longo do caminho:

Caixas verdes conectam o conteúdo com o que empresas realmente cobram em vagas e entrevistas.
Caixas laranjas apontam erros clássicos de iniciante que derrubam candidatos em testes técnicos.
Caixas roxas trazem exercícios. Tente antes de abrir a solução — na entrevista não tem "ver resposta".

Recomendação de estudo: crie uma pasta estudos-css no seu computador, com um arquivo index.html e um style.css, e reproduza cada exemplo digitando (não copie e cole). Digitar cria memória muscular — e teste técnico é feito digitando.

Módulo 1.1 — O que é CSS e como aplicá-lo

CSS (Cascading Style Sheets) é a linguagem que controla a aparência do HTML: cores, tamanhos, espaçamentos, posicionamento, animações. O HTML é o esqueleto; o CSS é a pele, a roupa e o movimento.

Existem três formas de aplicar CSS a uma página:

<!-- 1. Inline: direto no elemento (evite — difícil de manter) -->
<p style="color: purple;">Texto roxo</p>

<!-- 2. Interno: dentro de <style> no <head> (ok para testes) -->
<style>
  p { color: purple; }
</style>

<!-- 3. Externo: arquivo .css separado (padrão profissional) -->
<link rel="stylesheet" href="style.css">
Em projetos reais, CSS fica sempre em arquivos externos. CSS inline em tudo é um sinal vermelho clássico em revisão de código. Exceção: e-mails HTML, onde inline ainda é necessário por limitação dos clientes de e-mail.

Módulo 1.2 — Sintaxe e seletores básicos

Toda regra CSS tem a mesma anatomia:

seletor {
  propriedade: valor;   /* isto é uma declaração */
  outra-propriedade: outro-valor;
}

Os 4 seletores que você usará todos os dias

SeletorSintaxeSelecionaExemplo
ElementopTodas as tags daquele tipop { color: gray; }
Classe.destaqueElementos com class="destaque".destaque { font-weight: bold; }
ID#topoO único elemento com id="topo"#topo { background: black; }
Universal*Todos os elementos* { box-sizing: border-box; }

Você também pode agrupar seletores com vírgula:

h1, h2, h3 {
  font-family: 'Sora', sans-serif;
}
Prefira classes para estilizar. IDs têm especificidade altíssima (você vai entender no Módulo 2.1) e geram brigas no código. Regra prática do mercado: ID para JavaScript e âncoras, classe para CSS.
Crie um HTML com três parágrafos. Faça: (a) todos os parágrafos ficarem cinza; (b) apenas um deles, com a classe .importante, ficar vermelho e em negrito.
Ver solução
p { color: gray; }

.importante {
  color: red;
  font-weight: bold;
}

Módulo 1.3 — Cores e unidades de medida

Formas de escrever cores

.exemplos-de-cor {
  color: purple;                  /* nome (140+ nomes existem) */
  color: #663399;                 /* hexadecimal — o mais comum */
  color: rgb(102, 51, 153);       /* vermelho, verde, azul (0–255) */
  color: rgba(102, 51, 153, .5);  /* com transparência (0 a 1) */
  color: hsl(270, 50%, 40%);      /* matiz, saturação, luminosidade */
}

hsl() é o favorito de quem cria sistemas de cores: para clarear ou escurecer um tom, basta mudar o último número.

Unidades: quando usar cada uma

UnidadeO que éUse para
pxPixel fixoBordas, sombras, detalhes pequenos
remMúltiplo da fonte raiz (16px por padrão)Fontes, margens, paddings — respeita a configuração de acessibilidade do usuário
emMúltiplo da fonte do elemento paiEspaçamentos relativos ao texto local
%Percentual do paiLarguras fluidas
vw / vh% da largura/altura da telaSeções de tela cheia, tipografia fluida
Pergunta comum de entrevista: "qual a diferença entre em e rem?" Resposta: rem é sempre relativo ao elemento raiz (html), previsível; em é relativo ao pai, então acumula em elementos aninhados. Por isso o mercado padronizou rem para quase tudo.

Módulo 1.4 — Box model: o conceito mais importante do CSS

Todo elemento HTML é uma caixa com quatro camadas, de dentro para fora:

  1. Content — o conteúdo (texto, imagem);
  2. Padding — respiro interno, entre o conteúdo e a borda;
  3. Border — a borda em si;
  4. Margin — respiro externo, entre a caixa e as vizinhas.
.cartao {
  width: 300px;
  padding: 20px;              /* respiro interno */
  border: 2px solid #663399;  /* borda */
  margin: 16px;               /* respiro externo */
}

/* Atalhos (sentido horário: cima, direita, baixo, esquerda) */
.atalhos {
  margin: 10px 20px 10px 20px;  /* os 4 lados */
  margin: 10px 20px;            /* vertical | horizontal */
  margin: 0 auto;               /* truque clássico: centraliza horizontalmente */
}

box-sizing: border-box — a primeira linha de todo projeto

Por padrão, width: 300px se refere só ao conteúdo — padding e borda são somados por fora, e a caixa fica maior do que você pediu. A correção universal:

* {
  box-sizing: border-box; /* width agora inclui padding e borda */
}
Erro nº 1 de iniciante em teste técnico: layout "estourando" porque esqueceu o border-box. Praticamente todo projeto profissional começa com um reset que inclui essa linha.
Sem olhar a solução: se uma div tem width: 200px, padding: 20px e border: 5px solid, qual a largura total renderizada (a) no modelo padrão e (b) com border-box?
Ver solução

(a) 200 + 20 + 20 + 5 + 5 = 250px. (b) 200px — padding e borda passam a caber dentro dos 200px. Essa é literalmente uma pergunta de entrevista de estágio/júnior.

Módulo 1.5 — Tipografia

body {
  font-family: 'Inter', Arial, sans-serif; /* lista de fallbacks */
  font-size: 1rem;        /* 16px */
  font-weight: 400;       /* 400 normal · 700 bold */
  line-height: 1.6;       /* sem unidade = múltiplo da fonte (melhor prática) */
  letter-spacing: 0.01em;
}

h1 { text-transform: uppercase; }
a  { text-decoration: none; }
p  { text-align: left; }  /* evite justify na web: cria "rios" de espaço */

Georgia, 22px, line-height 1.3 — título com serifa

Corpo de texto menor, line-height 1.8, cor suavizada — repare como só tipografia já cria hierarquia visual sem nenhuma imagem.

Boa tipografia é o jeito mais barato de um portfólio parecer profissional: line-height entre 1.5 e 1.7 no corpo, no máximo 2 famílias de fonte por projeto, e tamanhos definidos em rem. Recrutadores técnicos reparam nisso em 5 segundos.

Módulo 2.1 — Cascata, especificidade e herança

O "C" de CSS é Cascading: quando duas regras disputam o mesmo elemento, o navegador decide a vencedora por três critérios, nesta ordem:

  1. Especificidade — quão "preciso" é o seletor;
  2. Ordem — em empate, a última regra escrita vence;
  3. Origem — estilos do autor vencem os padrões do navegador.

Calculando especificidade

Pense em três placares (A, B, C):

PlacarVale paraPeso
AIDs (#menu)1-0-0
BClasses, atributos, pseudo-classes (.btn, :hover)0-1-0
CElementos e pseudo-elementos (p, ::before)0-0-1
p               /* 0-0-1 */
.aviso          /* 0-1-0 — vence p */
p.aviso         /* 0-1-1 — vence .aviso */
#rodape .aviso  /* 1-1-0 — vence todos acima */
!important atropela toda a cascata — e por isso é considerado último recurso. Se você precisa dele para "fazer funcionar", o problema quase sempre é especificidade mal organizada. Em entrevistas, dizer "resolvo com !important" é resposta errada; a certa é "reviso a especificidade dos seletores".

Herança

Propriedades de texto (cor, fonte, line-height) são herdadas pelos filhos automaticamente. Propriedades de caixa (margin, padding, border, width) não são. Por isso definir font-family no body estiliza a página inteira.

Módulo 2.2 — Seletores avançados

Combinadores

nav a        /* descendente: qualquer <a> dentro de nav, em qualquer nível */
nav > a      /* filho direto: só <a> imediatamente dentro de nav */
h2 + p       /* irmão adjacente: o <p> logo depois de um h2 */
h2 ~ p       /* irmãos gerais: todos os <p> depois de um h2 */

Pseudo-classes essenciais

a:hover            { color: purple; }   /* mouse em cima */
input:focus        { outline: 2px solid purple; } /* selecionado via clique/teclado */
li:first-child     { font-weight: bold; }
li:last-child      { border-bottom: none; }
li:nth-child(odd)  { background: #f4f2ea; } /* zebra em tabelas/listas */
input:disabled     { opacity: .5; }
li:not(.ativo)     { color: gray; }

Pseudo-elementos

p::first-line   { font-weight: bold; }
.btn::before    { content: "→ "; }  /* insere conteúdo decorativo via CSS */
::selection     { background: #FFE066; } /* cor ao selecionar texto */

Teste agora: selecione qualquer texto desta apostila com o mouse — o fundo amarelo do destaque é um ::selection em ação... brincadeira, aqui usamos o padrão. Mas os balões "▶ Resultado ao vivo" e "💼 Dica de mercado" desta página são todos ::before!

Módulo 2.3 — Display e posicionamento

display: os três comportamentos clássicos

ValorComportamentoExemplos nativos
blockOcupa a linha inteira; aceita width/heightdiv, p, h1, section
inlineFlui no texto; ignora width/height e margens verticaisspan, a, strong
inline-blockFlui no texto, mas aceita dimensões

E o mais usado de todos: display: none remove o elemento da página (diferente de visibility: hidden, que esconde mas mantém o espaço ocupado — clássica pergunta de entrevista).

position

.estatico   { position: static; }    /* padrão: fluxo normal */
.relativo   { position: relative; top: 10px; }  /* desloca a partir de onde estava */
.absoluto   { position: absolute; top: 0; right: 0; } /* ancora no ancestral posicionado mais próximo */
.fixo       { position: fixed; bottom: 20px; }  /* fixa na TELA (não rola) */
.grudento   { position: sticky; top: 0; }       /* rola até "grudar" no topo */
O padrão de mercado é o duo relative + absolute: o pai recebe position: relative e o filho position: absolute para se ancorar nele (badge no canto do card, ícone dentro do input, botão de fechar no modal). O menu lateral desta apostila usa position: sticky.

z-index controla quem fica por cima quando elementos se sobrepõem — mas só funciona em elementos posicionados (qualquer position exceto static).

Módulo 2.4 — Flexbox: layout em uma dimensão

Flexbox distribui itens em um eixo (linha OU coluna). É a ferramenta nº 1 para alinhar coisas: menus, botões lado a lado, centralização.

.container {
  display: flex;
  flex-direction: row;        /* row (padrão) | column */
  justify-content: space-between; /* eixo PRINCIPAL: flex-start | center | space-between | space-around */
  align-items: center;        /* eixo TRANSVERSAL: stretch | center | flex-start */
  gap: 12px;                  /* espaço entre itens (adeus, margens manuais) */
  flex-wrap: wrap;            /* permite quebrar linha */
}

.item { flex: 1; }            /* itens crescem igualmente para preencher */
1
2
3

display:flex; gap:12px; com flex:1 em cada caixa.

A centralização perfeita (decore isto)

.centralizar {
  display: flex;
  justify-content: center;  /* horizontal */
  align-items: center;      /* vertical */
  min-height: 100vh;
}
"Como você centraliza uma div?" é a pergunta-meme das entrevistas de front-end — e ainda cai. Saiba responder de 3 formas: flexbox (acima), grid (display:grid; place-items:center) e o antigo margin: 0 auto (só horizontal). Explicar as três mostra senioridade.
Crie uma barra de navegação: logo à esquerda, três links à direita, tudo alinhado verticalmente ao centro.
Ver solução
<nav class="navbar">
  <span class="logo">MeuSite</span>
  <div class="links">
    <a href="#">Home</a> <a href="#">Sobre</a> <a href="#">Contato</a>
  </div>
</nav>
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 32px;
}
.links { display: flex; gap: 24px; }

Módulo 2.5 — Grid: layout em duas dimensões

Grid organiza linhas E colunas ao mesmo tempo. É a escolha para estruturas de página: galeria de cards, dashboard, layout com sidebar.

.galeria {
  display: grid;
  grid-template-columns: repeat(3, 1fr); /* 3 colunas de tamanho igual */
  gap: 12px;
}

.destaque {
  grid-column: span 3;  /* este item ocupa as 3 colunas */
}
Destaque (span 3)
A
B
C

O padrão de galeria responsiva sem media query

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 20px;
}

Tradução: "crie quantas colunas couberem, cada uma com no mínimo 250px". Ao estreitar a tela, as colunas quebram sozinhas. Este snippet resolve 80% das galerias do mundo real — memorize-o.

Flexbox ou Grid?

Use Flexbox quando…Use Grid quando…
Alinhar itens em uma direção (menu, botões, ícone + texto)Estruturar a página em áreas (header, sidebar, main)
O conteúdo define o tamanhoO layout define o tamanho
Componentes pequenosGalerias e dashboards
Resposta pronta para entrevista: "Flexbox para uma dimensão, Grid para duas. Na prática eu uso os dois juntos: Grid para o esqueleto da página, Flexbox dentro dos componentes."

Módulo 2.6 — Sombras, bordas e gradientes

.card {
  border-radius: 12px;                      /* cantos arredondados */
  box-shadow: 0 4px 24px rgba(0,0,0,.12);   /* x | y | blur | cor */
  background: linear-gradient(135deg, #663399, #9B59D0);
}

.avatar   { border-radius: 50%; }           /* círculo perfeito */
.texto-sombra { text-shadow: 1px 1px 3px rgba(0,0,0,.3); }
.foco-suave   { background: radial-gradient(circle, #fff, #F1EAF8); }
sombra
Sombras discretas = profissional; sombras pretas e duras = amador. Padrão seguro: rgba(0,0,0,.1) a .15, com blur generoso (16–32px). Compare portfólios aprovados: quase todos usam sombras suaves.

Módulo 3.1 — Responsividade e mobile-first

Mais da metade dos acessos à web vem de celulares. Site que quebra no celular = candidato eliminado. A ferramenta central é a media query:

/* Abordagem MOBILE-FIRST (padrão do mercado):
   escreva o CSS base para telas pequenas... */
.cards {
  display: grid;
  grid-template-columns: 1fr;   /* 1 coluna no celular */
  gap: 16px;
}

/* ...e adicione complexidade conforme a tela CRESCE */
@media (min-width: 768px) {
  .cards { grid-template-columns: repeat(2, 1fr); }  /* tablet */
}

@media (min-width: 1100px) {
  .cards { grid-template-columns: repeat(3, 1fr); }  /* desktop */
}

Breakpoints comuns (referência, não lei)

FaixaDispositivo típico
até 640pxCelulares
641–1023pxTablets
1024px+Notebooks e desktops

O kit responsivo básico

<!-- Sem esta meta tag no HTML, NADA responsivo funciona no celular -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
img { max-width: 100%; height: auto; }  /* imagens nunca estouram o container */
Em teste técnico, abra o DevTools (F12) e ative o modo dispositivo (Ctrl+Shift+M) antes de entregar. Avaliadores SEMPRE redimensionam a janela. Redimensione esta apostila e veja o menu lateral virar topo — é a media query do nosso próprio código.
Faça um layout com sidebar de 250px + conteúdo ao lado no desktop, que vira coluna única no celular (sidebar em cima).
Ver solução
.layout { display: grid; grid-template-columns: 1fr; }

@media (min-width: 900px) {
  .layout { grid-template-columns: 250px 1fr; }
}

Mobile-first: base = 1 coluna; desktop = 2 colunas. Exatamente o que esta apostila faz.

Módulo 3.2 — Variáveis CSS (custom properties) e dark mode

Variáveis nativas do CSS permitem definir valores uma vez e reutilizar em todo o projeto:

:root {                        /* :root = escopo global */
  --cor-primaria: #663399;
  --cor-texto: #20242F;
  --espaco: 16px;
}

.botao {
  background: var(--cor-primaria);
  padding: var(--espaco);
  color: var(--cor-texto);
}

Dark mode em 10 linhas

Como as variáveis podem ser sobrescritas por contexto, trocar o tema inteiro vira trocar meia dúzia de valores:

:root {
  --fundo: #ffffff;
  --texto: #20242F;
}

/* respeita a preferência do sistema operacional do usuário */
@media (prefers-color-scheme: dark) {
  :root {
    --fundo: #14161F;
    --texto: #E8EAF2;
  }
}

body { background: var(--fundo); color: var(--texto); }

Para um botão de alternância manual, basta uma classe no body (body.dark { --fundo: #14161F; }) trocada com 1 linha de JavaScript.

Implementar dark mode num projeto de portfólio é um diferencial barato e visível. E "como você estruturaria temas claro/escuro?" é pergunta real de entrevista — a resposta esperada é exatamente esta: design tokens em variáveis CSS sobrescritas por tema.

Módulo 3.3 — calc(), clamp(), min() e max()

.sidebar-layout {
  width: calc(100% - 280px);   /* mistura unidades diferentes */
}

h1 {
  /* clamp(MÍNIMO, IDEAL, MÁXIMO): tipografia fluida sem media query */
  font-size: clamp(1.8rem, 5vw, 3.5rem);
}

.container {
  width: min(90%, 1200px);     /* o que for MENOR: container responsivo em 1 linha */
}

Redimensione a janela: eu me adapto!

font-size: clamp(16px, 4vw, 34px) — cresce e encolhe com a tela, dentro dos limites.

Módulo 3.4 — Transições, transforms e animações

transition: animando mudanças de estado

.botao {
  background: #663399;
  transition: transform .2s ease, box-shadow .2s ease;
}

.botao:hover {
  transform: translateY(-3px);            /* sobe 3px */
  box-shadow: 0 8px 20px rgba(102,51,153,.35);
}

↑ Exatamente o código acima, ao vivo.

transform: mover, girar, escalar

.el { transform: translateX(20px); }  /* mover */
.el { transform: rotate(45deg); }     /* girar */
.el { transform: scale(1.1); }        /* aumentar 10% */
.el { transform: rotate(45deg) scale(1.1); } /* combinar */

@keyframes: animações contínuas

@keyframes girar {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

.loading {
  animation: girar 3s linear infinite;
  /* nome | duração | curva | repetições */
}

↑ O @keyframes girar acima, rodando agora.

Performance: anime preferencialmente transform e opacity — o navegador as processa na GPU sem recalcular o layout. Animar width, height, top ou margin causa travamentos em telas fracas. E respeite @media (prefers-reduced-motion: reduce) para usuários sensíveis a movimento — isso é acessibilidade cobrada em empresas sérias.

Módulo 3.5 — CSS moderno que impressiona em entrevista

:has() — o "seletor de pai"

/* estiliza o card QUE CONTÉM uma imagem */
.card:has(img) { padding: 0; }

/* formulário com campo inválido ganha borda vermelha */
form:has(input:invalid) { border-color: red; }

Container queries — responsividade por componente

.sidebar { container-type: inline-size; }

/* o card responde ao tamanho do CONTAINER, não da tela */
@container (min-width: 400px) {
  .card { display: flex; }
}

Media queries perguntam "qual o tamanho da tela?"; container queries perguntam "qual o tamanho do espaço onde estou?" — perfeito para componentes reutilizáveis em design systems.

Nesting nativo

.card {
  padding: 20px;

  .titulo { font-weight: 700; }   /* aninhado, sem pré-processador! */

  &:hover { box-shadow: 0 4px 24px rgba(0,0,0,.12); }
}

Sim: o CSS incorporou o recurso mais famoso do SCSS (veremos no Módulo 4). Suportado em todos os navegadores modernos desde 2023.

Outros que valem citar

.video   { aspect-ratio: 16 / 9; }      /* proporção fixa sem hacks */
.thumb   { object-fit: cover; }         /* imagem preenche sem distorcer */
.grid    { place-items: center; }       /* atalho p/ centralizar em grid */
.lista   { scroll-snap-type: x mandatory; } /* carrossel sem JS */

Módulo 3.6 — Arquitetura CSS: escrevendo código que escala

Saber propriedades te faz passar no teste; saber organizar CSS te faz ser contratado. O problema clássico: projetos crescem, seletores conflitam, ninguém tem coragem de apagar nada.

BEM — Block, Element, Modifier

A convenção de nomenclatura mais pedida em vagas brasileiras:

/* Bloco: o componente independente */
.card { }

/* Elemento: parte do bloco → bloco__elemento */
.card__titulo { }
.card__imagem { }

/* Modificador: variação → bloco--modificador */
.card--destaque { }
.card__botao--desabilitado { }
<article class="card card--destaque">
  <img class="card__imagem" src="foto.jpg" alt="Produto">
  <h2 class="card__titulo">Título</h2>
</article>

Vantagens: especificidade sempre baixa (só classes), nomes autoexplicativos, zero conflito entre componentes. O código-fonte desta apostila usa BEM (.sidebar__logo, .hero__tag...).

Organização de arquivos

css/
├── base/        /* reset, tipografia, variáveis */
├── components/  /* botao.css, card.css, navbar.css */
├── layout/      /* header.css, footer.css, grid.css */
└── pages/       /* home.css, contato.css */
Vagas de front-end citam com frequência: BEM, design tokens (as variáveis do 3.2), Tailwind CSS (classes utilitárias prontas) e CSS Modules / styled-components (no ecossistema React). Você não precisa dominar todos — mas precisa saber explicar o que são e por que existem: todos atacam o mesmo problema, CSS global que vira bagunça.

Módulo 3.7 — Acessibilidade e performance

Acessibilidade (a11y) no CSS

.botao:focus-visible {
  outline: 3px solid #663399;
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

Performance

Acessibilidade saiu de "diferencial" para requisito legal e de vaga (no Brasil, LBI — Lei 13.146). Dizer numa entrevista que você testa contraste, navegação por teclado e reduced-motion coloca você na frente da maioria dos juniores.

Módulo 4.1 — O que é Sass/SCSS

Sass é um pré-processador: uma linguagem que compila para CSS. Você escreve num arquivo .scss com superpoderes (variáveis com lógica, funções, loops, módulos) e uma ferramenta converte para o CSS que o navegador entende.

SCSS é a sintaxe moderna do Sass — todo CSS válido já é SCSS válido, então a curva de aprendizado é suave.

Instalando e compilando

# requer Node.js instalado
npm install -g sass

# compila uma vez
sass style.scss style.css

# modo watch: recompila a cada salvamento (use este no dia a dia)
sass --watch scss/:css/

Em projetos reais com React/Vue/Vite, a compilação é automática: basta instalar sass como dependência e importar o arquivo .scss.

Módulo 4.2 — Variáveis, nesting e partials

Variáveis com $

$roxo: #663399;
$espaco: 16px;

.botao {
  background: $roxo;
  padding: $espaco ($espaco * 2);  // SCSS faz MATEMÁTICA com variáveis
  border: 1px solid darken($roxo, 15%); // e tem funções de cor embutidas
}

Diferença para variáveis CSS: as do SCSS são resolvidas na compilação (viram valores fixos); as do CSS vivem no navegador e podem mudar em tempo real (por isso dark mode usa variáveis CSS). Times maduros usam as duas juntas.

Nesting (aninhamento)

.navbar {
  display: flex;
  gap: 24px;

  a {
    color: white;
    text-decoration: none;

    &:hover { color: $roxo; }       // & = o seletor pai (.navbar a:hover)
    &.ativo { font-weight: bold; }  // .navbar a.ativo
  }
}

// & também encurta BEM:
.card {
  &__titulo { font-size: 1.2rem; }  // vira .card__titulo
  &--destaque { border: 2px solid $roxo; } // vira .card--destaque
}
Regra de ouro do nesting: no máximo 3 níveis. Aninhamento profundo gera seletores gigantes e específicos demais — o exato problema que arquitetura CSS tenta evitar. Isso É verificado em code review.

Partials e @use: dividindo em arquivos

// _variaveis.scss  (o underscore indica: "não compile sozinho")
$roxo: #663399;

// _botoes.scss
@use 'variaveis' as v;
.botao { background: v.$roxo; }

// main.scss — o único que vira CSS final
@use 'variaveis';
@use 'botoes';
@use 'navbar';

@use substituiu o antigo @import (deprecado). Se encontrar @import num projeto legado, saiba ler os dois.

Módulo 4.3 — Mixins, funções, @extend e loops

Mixins: blocos reutilizáveis (com parâmetros!)

@mixin flex-center($direcao: row) {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: $direcao;
}

@mixin mobile {
  @media (max-width: 640px) { @content; }
}

.hero {
  @include flex-center(column);

  @include mobile {
    padding: 16px;   // injetado dentro da media query
  }
}

O mixin de breakpoint é o padrão de mercado: centraliza os breakpoints num lugar só e deixa as media queries legíveis.

Funções

@function rem($px) {
  @return calc($px / 16) * 1rem;
}

h1 { font-size: rem(32); }  // → 2rem

@extend e placeholders

%botao-base {
  padding: 12px 28px;
  border-radius: 8px;
  font-weight: 700;
}

.botao-primario   { @extend %botao-base; background: $roxo; }
.botao-secundario { @extend %botao-base; background: transparent; border: 2px solid $roxo; }

Loops: gerando classes utilitárias

@for $i from 1 through 5 {
  .mt-#{$i} { margin-top: $i * 8px; }
}
// gera .mt-1 {margin-top: 8px} até .mt-5 {margin-top: 40px}

$cores: (primaria: #663399, sucesso: #2B8A3E, erro: #E8590C);
@each $nome, $valor in $cores {
  .texto-#{$nome} { color: $valor; }
}

Módulo 4.4 — SCSS no mercado hoje: o cenário honesto

Vale calibrar expectativas para não estudar no escuro:

Estratégia recomendada: domine CSS puro profundamente (é a base de tudo), saiba SCSS o suficiente para trabalhar em qualquer projeto que o use (este módulo cobre 90% do uso real), e aprenda Tailwind quando for entrar no ecossistema React.

Pergunta de entrevista real: "Por que usar um pré-processador se o CSS já tem variáveis e nesting?" Boa resposta: mixins com parâmetros, funções próprias, loops para gerar utilitários e o sistema de módulos @use ainda não têm equivalente nativo — além de bases de código existentes que precisam de manutenção. Mostra que você entende trade-offs, não só sintaxe.
Converta este CSS para SCSS usando variáveis, nesting e um mixin de hover:
.menu { background: #663399; }
.menu a { color: white; padding: 8px 16px; }
.menu a:hover { background: #4B2570; }
.menu a.ativo { font-weight: bold; }
Ver solução
$roxo: #663399;

@mixin hover-escuro {
  &:hover { background: darken($roxo, 15%); }
}

.menu {
  background: $roxo;

  a {
    color: white;
    padding: 8px 16px;
    @include hover-escuro;

    &.ativo { font-weight: bold; }
  }
}

Módulo 5.1 — Projeto: Card de perfil

Primeiro projeto de portfólio: um card de perfil como os do LinkedIn. Treina box model, border-radius, sombras, flexbox e o duo relative/absolute.

👩‍💻

Ana Ferreira

Desenvolvedora Front-end

Estrutura HTML

<article class="card">
  <div class="card__topo"></div>
  <div class="card__corpo">
    <div class="card__avatar">👩‍💻</div>
    <p class="card__nome">Ana Ferreira</p>
    <p class="card__cargo">Desenvolvedora Front-end</p>
    <button class="card__botao">Conectar</button>
  </div>
</article>

CSS comentado

.card {
  max-width: 320px;
  background: #fff;
  border-radius: 14px;
  overflow: hidden;             /* o topo colorido respeita os cantos arredondados */
  box-shadow: 0 4px 24px rgba(32,36,47,.12);
}

.card__topo {
  height: 80px;
  background: linear-gradient(135deg, #663399, #9B59D0);
}

.card__corpo {
  padding: 0 20px 20px;
  text-align: center;
}

.card__avatar {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: #FFE066;
  border: 4px solid #fff;
  margin: -36px auto 8px;       /* margem NEGATIVA: metade do avatar invade o topo */
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 30px;
}

.card__nome  { font-weight: 700; font-size: 18px; margin: 0; }
.card__cargo { color: #5A6072; font-size: 14px; margin: 2px 0 14px; }
Evolua o projeto: (a) adicione um badge "PRO" no canto superior direito usando position: absolute; (b) faça o card subir 4px no hover com transição suave; (c) adicione uma linha de estatísticas (posts · seguidores · conexões) usando flexbox com justify-content: space-around.

Módulo 5.2 — Projeto: Navbar responsiva

Toda entrevista prática tem uma navbar. Esta versão usa zero JavaScript: o menu mobile abre com o truque do checkbox invisível — demonstra domínio de seletores.

<nav class="nav">
  <span class="nav__logo">MeuSite</span>

  <input type="checkbox" id="menu-toggle" class="nav__check">
  <label for="menu-toggle" class="nav__hamburguer">☰</label>

  <ul class="nav__links">
    <li><a href="#">Home</a></li>
    <li><a href="#">Projetos</a></li>
    <li><a href="#">Contato</a></li>
  </ul>
</nav>
/* Mobile-first: menu escondido, hambúrguer visível */
.nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  padding: 16px 24px;
  background: #20242F;
}

.nav__logo { color: #fff; font-weight: 700; }
.nav__check { display: none; }              /* o checkbox em si fica invisível */
.nav__hamburguer { color: #fff; font-size: 24px; cursor: pointer; }

.nav__links {
  display: none;                            /* fechado por padrão */
  width: 100%;
  list-style: none;
  margin: 0; padding: 0;
}

/* A MÁGICA: checkbox marcado + irmão seguinte = menu aberto */
.nav__check:checked ~ .nav__links { display: block; }

.nav__links a {
  display: block;
  color: #C4C8D6;
  text-decoration: none;
  padding: 12px 0;
}
.nav__links a:hover { color: #FFE066; }

/* Desktop: esconde o hambúrguer, mostra os links em linha */
@media (min-width: 768px) {
  .nav__hamburguer { display: none; }
  .nav__links {
    display: flex !important;   /* sempre visível no desktop */
    width: auto;
    gap: 28px;
  }
  .nav__links a { padding: 0; }
}
Este projeto rende ótima conversa em entrevista: você explica o seletor de irmão (~), a pseudo-classe :checked, mobile-first e o trade-off "CSS puro vs JavaScript". Depois, refaça a versão com JS e um botão <button aria-expanded> — a versão com botão é mais acessível para leitores de tela, e saber comparar as duas é ponto extra.

Módulo 5.3 — Projeto final: Landing page completa

O projeto que vai para o topo do portfólio. Monte uma landing page de um produto fictício (app, cafeteria, academia — escolha algo de que você goste) com estas seções:

SeçãoTécnicas que ela demonstra
1. Navbar fixaposition: sticky, flexbox, projeto 5.2
2. Hero (título + botão CTA)min-height: 100vh, centralização, clamp() no título, gradiente
3. Grade de 3 benefíciosGrid com auto-fit/minmax, cards com sombra e hover
4. DepoimentosFlexbox, border-radius: 50% nos avatares, ::before com aspas decorativas
5. Formulário de contatoEstilização de inputs, :focus-visible, estados :invalid
6. FooterGrid de colunas, variáveis CSS para o tema escuro da seção

Esqueleto para começar

:root {
  --primaria: #663399;      /* troque pela paleta do SEU tema */
  --escuro: #20242F;
  --claro: #FBFAF6;
  --espaco-secao: clamp(48px, 8vw, 110px);
}

* { box-sizing: border-box; margin: 0; }

body { font-family: system-ui, sans-serif; line-height: 1.6; color: var(--escuro); }

section { padding: var(--espaco-secao) 24px; }

.container { width: min(90%, 1100px); margin: 0 auto; }

.hero {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  background: linear-gradient(135deg, var(--primaria), #9B59D0);
  color: #fff;
}

.hero h1 { font-size: clamp(2rem, 6vw, 4rem); }

Critérios de "pronto para o portfólio"

Desafio extra: refaça o CSS da landing em SCSS, com _variaveis.scss, _mixins.scss (incluindo o mixin de breakpoint do Módulo 4.3) e um partial por seção. Suba as duas versões no GitHub — isso vira assunto de entrevista.

Módulo 6.1 — O que as vagas realmente pedem

Analisando vagas de front-end júnior no Brasil, o padrão de requisitos envolvendo CSS é consistente:

Requisito da vagaOnde você aprendeu nesta apostila
"HTML5 e CSS3 sólidos"Módulos 1 e 2 inteiros
"Layouts responsivos / mobile-first"3.1
"Flexbox e Grid"2.4 e 2.5
"Sass/SCSS ou Less"Módulo 4
"Metodologias como BEM"3.6
"Acessibilidade (WCAG)"3.7
"Pixel perfect a partir do Figma"Prática dos projetos do Módulo 5

"Pixel perfect" merece explicação: significa reproduzir fielmente um layout desenhado no Figma. Treine pegando designs gratuitos da comunidade do Figma (ou desafios do Frontend Mentor) e reproduzindo em código — é o formato mais comum de teste técnico júnior.

Módulo 6.2 — Perguntas de entrevista (com respostas)

Nível júnior

1. Explique o box model.

Todo elemento é uma caixa com content, padding, border e margin. Com box-sizing: border-box, o width declarado passa a incluir padding e borda, tornando o layout previsível.

2. Qual a diferença entre margin e padding?

Padding é espaço interno (entre conteúdo e borda; herda a cor de fundo do elemento). Margin é espaço externo (entre o elemento e os vizinhos; sempre transparente).

3. Diferença entre display:none e visibility:hidden?

display:none remove o elemento do fluxo — o espaço some. visibility:hidden só o torna invisível — o espaço continua reservado.

4. Diferença entre em e rem?

rem é relativo à fonte do elemento raiz (previsível); em é relativo à fonte do pai (acumula em aninhamentos). O mercado padroniza rem.

5. Como centralizar uma div?

Três formas: flexbox (display:flex; justify-content:center; align-items:center), grid (display:grid; place-items:center) e, para centralização só horizontal de bloco com largura definida, margin: 0 auto.

Nível pleno

6. Explique especificidade e por que evitar !important.

Especificidade é o placar (IDs, classes, elementos) que decide qual regra vence. !important ignora esse sistema, criando regras impossíveis de sobrescrever sem outro !important — uma corrida armamentista. A solução correta é manter especificidade baixa e consistente (só classes, como no BEM).

7. Flexbox vs Grid: quando usar cada um?

Flexbox para uma dimensão (alinhamento de itens em linha ou coluna: menus, botões); Grid para duas (estrutura da página: galerias, dashboards). Na prática, Grid para o esqueleto e Flexbox dentro dos componentes.

8. O que são pseudo-classes e pseudo-elementos?

Pseudo-classes (:hover, :focus, :nth-child) selecionam estados ou posições de elementos existentes. Pseudo-elementos (::before, ::after, ::first-line) criam ou estilizam partes que não existem no HTML.

9. Como você faria dark mode?

Design tokens em variáveis CSS no :root, sobrescritos por @media (prefers-color-scheme: dark) para respeitar o sistema, mais uma classe no body para alternância manual persistida em localStorage.

10. Quais propriedades são mais baratas de animar e por quê?

transform e opacity: são compostas na GPU sem disparar recálculo de layout (reflow) nem repintura, mantendo 60fps. Animar width, height ou top força reflow a cada frame.

11. Por que usar SCSS se o CSS moderno tem variáveis e nesting?

Mixins parametrizados, funções próprias, loops e o sistema de módulos @use ainda não têm equivalente nativo — e há muitas bases de código SCSS em manutenção. Mas para projetos novos e simples, CSS puro moderno pode bastar; a escolha é um trade-off de equipe.

12. O que é a cascata do CSS?

O algoritmo que resolve conflitos entre regras, considerando origem (autor > navegador), especificidade do seletor e, em empate, ordem no código (a última vence). Herança complementa: propriedades de texto descem para os filhos.

Em entrevistas, respostas boas seguem o formato conceito → exemplo → trade-off. Não diga só "uso flexbox"; diga "uso flexbox porque é um eixo só; se fosse uma galeria em duas dimensões, usaria grid". Demonstrar critério vale mais do que decorar propriedades.

Módulo 6.3 — Checklist de portfólio que gera entrevista

  1. 3 projetos bem-feitos > 10 medianos. Sugestão: os três desta apostila, evoluídos — card de perfil, navbar/página institucional e a landing page completa.
  2. Tudo publicado online com link clicável (GitHub Pages, Netlify ou Vercel). Recrutador não clona repositório.
  3. README caprichado em cada repositório: screenshot, link ao vivo, técnicas usadas ("Grid com auto-fit, BEM, dark mode com variáveis CSS") e o que você aprendeu.
  4. Responsivo sem exceção. O recrutador vai abrir no celular. Se quebrar, acabou.
  5. Um projeto reproduzindo design real (Frontend Mentor tem designs gratuitos com nível de dificuldade) — prova que você faz "pixel perfect".
  6. Commits em português ou inglês consistentes e frequentes — mostra processo, não só resultado.
  7. Acessibilidade citada explicitamente no README: contraste testado, navegação por teclado, reduced-motion. Pouquíssimos juniores fazem isso.

Módulo 6.4 — Próximos passos na carreira

Com CSS e SCSS dominados, a trilha natural de front-end segue assim:

  1. JavaScript — a próxima linguagem obrigatória: interatividade, DOM, eventos, fetch;
  2. Git e GitHub a fundo — branches, pull requests, resolução de conflitos (usado todo dia em equipe);
  3. Um framework — React domina as vagas no Brasil; Vue e Angular também têm mercado;
  4. Tailwind CSS — quando entrar no ecossistema React, aprenda a abordagem utility-first;
  5. TypeScript — cada vez mais presente até em vagas júnior.

E continue praticando CSS: Frontend Mentor (desafios com design pronto), CSS Battle (golfe de CSS, ótimo para seletores) e os guias da MDN Web Docs — a documentação oficial de referência, em português inclusive.


Fim da apostila — e começo da prática. 🚀
Lembre-se: esta página inteira foi construída com as técnicas que ela ensina.
Abra o código-fonte (Ctrl+U), inspecione com o DevTools (F12) e use-a como material de estudo duplo.