🚀 Trilha Web
0/0

🚀 Trilha Web

Roadmap de 2 semanas para aprender HTML, CSS e JavaScript — do zero, com exemplos comentados e exercícios práticos.

14 dias de estudo
0 exercícios concluídos
2 projetos práticos

💡 Dica: marque os exercícios conforme concluir — o progresso fica salvo neste navegador. Use F12 (Console) para testar o JavaScript.

Guia completo e explicado para iniciantes absolutos (ADS — 3ª semana)

Como usar este guia: leia a teoria do dia, digite os exemplos (não copie/cole — digitar fixa o aprendizado), faça os exercícios e só então avance. Ritmo sugerido: 1h30–2h por dia. Se um dia ficar pesado, divida em dois — o importante é entender, não correr.

PARTE PARTE 0 — ANTES DE COMEÇAR

0.1 O que são HTML, CSS e JavaScript? (A analogia da casa)

Imagine que você vai construir uma casa:

TecnologiaPapelAnalogia
HTMLEstruturaOs tijolos, paredes, cômodos e a planta da casa. Define O QUE existe na página (títulos, textos, imagens, botões, formulários).
CSSVisualA pintura, o piso, a decoração. Define COMO a página se parece (cores, tamanhos, espaçamentos, posições).
JavaScriptComportamentoA elétrica, o encanamento, as portas automáticas. Define O QUE ACONTECE quando o usuário interage (clique, digitação, envio de formulário).

Resumo: HTML = conteúdo. CSS = aparência. JS = comportamento. Os três juntos formam qualquer site moderno.

0.2 Ferramentas que você vai usar

  1. Editor de código — VS Code (gratuito): https://code.visualstudio.com
  2. Instale a extensão Live Server (ícone de extensões na barra lateral → pesquise "Live Server" → Install). Ela recarrega a página automaticamente quando você salva o arquivo.
  3. Navegador — Chrome ou Edge (você já tem). Use o DevTools (tecla F12): é o "raio-X" da página. Nele você vê o HTML, testa CSS na hora e vê erros de JS no Console.
  4. Uma pasta de estudos: crie C:\estudos-web\ (ou onde preferir). Um arquivo HTML por dia, com nome claro: dia1.html, dia2.html...

0.3 Como funciona um site?


PARTE PARTE 1 — SEMANA 1: HTML & CSS


📅 DIA 1 — Primeiro HTML: estrutura, textos, listas, links e imagens

1.1 A estrutura obrigatória de todo documento HTML

Todo arquivo HTML tem este "esqueleto". Vou explicar linha por linha:

HTML
<!DOCTYPE html>              <!-- Diz ao navegador: "isto é um documento HTML5" (a versão atual) -->
<html lang="pt-BR">          <!-- A tag raiz. Envolve TUDO. lang="pt-BR" diz que o idioma é português -->
<head>                       <!-- Cabeça: informações invisíveis sobre a página (metadados) -->
    <meta charset="UTF-8">   <!-- Define a codificação de caracteres. Sem isso, acentos (ã, ç) aparecem quebrados! -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
                             <!-- Faz o site funcionar bem no celular (obrigatório em sites modernos) -->
    <title>Minha Primeira Página</title>
                             <!-- O texto que aparece na aba do navegador -->
</head>
<body>                       <!-- Corpo: TUDO que aparece visível na página fica aqui -->
    <h1>Olá, mundo!</h1>     <!-- Título principal da página -->
    <p>Meu primeiro parágrafo.</p>
</body>
</html>

Anatomia de uma tag: a maioria das tags vem em par: <tag> (abertura) ... </tag> (fechamento, com a barra). Algumas são "auto-fecháveis", como <img> e <br>.

Atributos: informações extras dentro da tag de abertura: <tag atributo="valor">. Ex.: <a href="https://google.com">.

Comentários: <!-- texto --> — o navegador ignora. Use para se organizar!

1.2 Tags de texto

HTML
<h1>Título principal</h1>   <!-- IMPORTANTE: só UM h1 por página (usado pelo Google para entender o assunto) -->
<h2>Subtítulo</h2>          <!-- h1 > h2 > h3 > h4 > h5 > h6: hierarquia de importância -->
<h3>Seção menor ainda</h3>

<p>Parágrafo normal. Texto corrido vai aqui.</p>
<p>Outro parágrafo. O navegador já coloca espaçamento entre parágrafos sozinho.</p>

<strong>Texto em negrito (ênfase forte)</strong>
<em>Texto em itálico (ênfase)</em>
<mark>Texto marcado (grifado)</mark>
<small>Texto pequeno (notas, avisos legais)</small>
<del>Texto riscado</del>  <!-- mostra: <del>Texto riscado</del> -->
<ins>Texto sublinhado</ins>

<br>          <!-- Quebra de linha ("break") — use com moderação, prefira <p> -->
<hr>          <!-- Linha horizontal divisória -->

<blockquote>Citação longa — aparece recuada.</blockquote>
<code>console.log("código")</code>  <!-- Trecho de código em fonte monoespaçada -->

Dica de ouro: o navegador ignora espaços e quebras de linha extras no seu código. Se você digitar 10 espaços seguidos, ele mostra 1. Para espaçar, use CSS (aprenderemos amanhã).

1.3 Listas

HTML
<!-- Lista não ordenada (com marcadores "bolinha") -->
<ul>
    <li>HTML</li>
    <li>CSS</li>
    <li>JavaScript</li>
</ul>

<!-- Lista ordenada (numerada) -->
<ol>
    <li>Estudar estrutura</li>
    <li>Fazer exercícios</li>
    <li>Revisar</li>
</ol>

<!-- Lista de definição (termo + descrição) -->
<dl>
    <dt>HTML</dt>          <!-- termo -->
    <dd>Linguagem de marcação para estruturar páginas.</dd>  <!-- descrição -->
</dl>
HTML
<a href="https://www.google.com">Ir para o Google</a>

<!-- Abrir em nova aba: atributo target="_blank" (SEMPRE use com rel="noopener" por segurança) -->
<a href="https://www.google.com" target="_blank" rel="noopener">Google em nova aba</a>

<!-- Link para uma página sua (arquivo na mesma pasta) -->
<a href="contato.html">Página de contato</a>

<!-- Link para uma parte da MESMA página (âncora): o destino precisa ter um id -->
<a href="#secao-projetos">Ir para meus projetos</a>
...
<h2 id="secao-projetos">Projetos</h2>

<!-- Link que abre o app de email -->
<a href="mailto:seuemail@gmail.com">Me mande um email</a>

1.5 Imagens

HTML
<!-- src = fonte (caminho do arquivo ou URL). alt = texto alternativo (acessibilidade + SEO). OBRIGATÓRIO -->
<img src="foto.jpg" alt="Foto do meu gato dormindo">

<!-- Do tamanho certo: width e height em pixels -->
<img src="foto.jpg" alt="Foto do meu gato" width="300" height="200">

<!-- Imagem vinda da internet (URL completa) -->
<img src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" alt="Logo do Google">

<!-- width="300" apenas distorce a exibição; o arquivo continua o mesmo tamanho no disco -->

Pegadinha comum: se a imagem não aparecer, o caminho em src está errado (nome com erro de digitação, maiúsculas/minúsculas, ou pasta errada). Verifique!

✅ Exercícios do Dia 1


↑ InícioDia 2 →

📅 DIA 2 — Semântica, tabelas e formulários

2.1 Tags semânticas: dar significado às partes da página

Antigamente usava-se <div> (divisão genérica) para tudo. Hoje usamos tags que dizem o que cada parte é — isso ajuda o Google, leitores de tela (acessibilidade) e você mesmo a se achar no código:

HTML
<body>
    <header>    <!-- Cabeçalho da página (logo, menu, título) -->
        <nav>   <!-- Navegação: o menu de links -->
            <a href="#inicio">Início</a>
            <a href="#sobre">Sobre</a>
            <a href="#contato">Contato</a>
        </nav>
    </header>

    <main>      <!-- Conteúdo PRINCIPAL. Deve haver só um por página -->
        <section id="sobre">   <!-- Seção: bloco temático da página -->
            <h2>Sobre mim</h2>
            <p>Texto sobre mim...</p>
        </section>

        <article>   <!-- Artigo: conteúdo independente (post de blog, notícia) -->
            <h2>Meu primeiro projeto</h2>
            <p>Como eu fiz...</p>
            <time datetime="2026-08-09">9 de agosto de 2026</time>  <!-- data legível para máquinas -->
        </article>
    </main>

    <aside>     <!-- Conteúdo lateral/complementar (barra lateral, propaganda, links relacionados) -->
        <p>Publicidade ou links úteis.</p>
    </aside>

    <footer>    <!-- Rodapé: copyright, contatos, links legais -->
        <p>© 2026 Meu Site. Todos os direitos reservados.</p>
    </footer>
</body>

<div> vs <span>: são os "contêineres genéricos" (sem significado). <div> é em bloco (ocupa a linha toda); <span> é inline (fica no meio do texto). Use-os quando nenhuma tag semântica servir:

HTML
<div class="card">Bloco genérico</div>
<p>Texto com um <span class="destaque">trecho destacado</span> no meio.</p>

2.2 Tabelas

HTML
<table>                          <!-- a tabela -->
    <caption>Notas dos alunos</caption>   <!-- legenda da tabela -->
    <thead>                      <!-- cabeçalho da tabela -->
        <tr>                     <!-- linha (table row) -->
            <th>Aluno</th>       <!-- célula de cabeçalho (fica em negrito automaticamente) -->
            <th>Nota</th>
        </tr>
    </thead>
    <tbody>                      <!-- corpo da tabela -->
        <tr>
            <td>Ana</td>         <!-- célula de dados -->
            <td>9,5</td>
        </tr>
        <tr>
            <td>Bruno</td>
            <td>7,0</td>
        </tr>
    </tbody>
    <tfoot>                      <!-- rodapé da tabela (opcional) -->
        <tr>
            <td>Média</td>
            <td>8,25</td>
        </tr>
    </tfoot>
</table>

<!-- Mesclar células: colspan (colunas) e rowspan (linhas) -->
<tr>
    <td colspan="2">Esta célula ocupa 2 colunas</td>
</tr>

Dica: tabelas são para dados (notas, horários, preços). NUNCA use tabela para fazer layout da página — isso é coisa dos anos 2000, use CSS (Flexbox/Grid, dias 4–5).

2.3 Formulários — como a página recebe dados do usuário

HTML
<!-- action = para onde os dados vão (no começo, pode ser "#"). method = como (GET/POST) -->
<form action="#" method="post">

    <!-- CADA campo precisa de um <label> com "for" apontando para o "id" do input.
         Clique no label = foca o campo. Acessibilidade + usabilidade. -->
    <label for="nome">Nome completo:</label>
    <input type="text" id="nome" name="nome" placeholder="Digite seu nome" required>

    <label for="email">Email:</label>
    <input type="email" id="email" name="email" placeholder="voce@email.com" required>
    <!-- type="email" valida automaticamente se tem @ e . -->

    <label for="senha">Senha:</label>
    <input type="password" id="senha" name="senha" required>
    <!-- type="password" esconde os caracteres digitados -->

    <label for="idade">Idade:</label>
    <input type="number" id="idade" name="idade" min="0" max="120">

    <label for="nascimento">Data de nascimento:</label>
    <input type="date" id="nascimento" name="nascimento">

    <label for="cor">Cor favorita:</label>
    <input type="color" id="cor" name="cor">

    <!-- Checkbox: marcações independentes. name igual = grupo -->
    <p>Interesses:</p>
    <input type="checkbox" id="front" name="interesse" value="frontend">
    <label for="front">Front-end</label>
    <input type="checkbox" id="back" name="interesse" value="backend">
    <label for="back">Back-end</label>

    <!-- Radio: escolhe APENAS UMA opção (name igual obrigatório para agrupar) -->
    <p>Nível:</p>
    <input type="radio" id="iniciante" name="nivel" value="iniciante" checked>
    <label for="iniciante">Iniciante</label>
    <input type="radio" id="medio" name="nivel" value="medio">
    <label for="medio">Intermediário</label>

    <!-- Select: lista suspensa -->
    <label for="cidade">Cidade:</label>
    <select id="cidade" name="cidade">
        <option value="">Selecione...</option>
        <option value="sp">São Paulo</option>
        <option value="rj">Rio de Janeiro</option>
        <option value="bh">Belo Horizonte</option>
    </select>

    <!-- Textarea: texto longo -->
    <label for="mensagem">Mensagem:</label>
    <textarea id="mensagem" name="mensagem" rows="4" cols="40">Texto inicial</textarea>

    <!-- Botões -->
    <button type="submit">Enviar</button>   <!-- envia o formulário -->
    <button type="reset">Limpar</button>    <!-- limpa os campos -->
    <button type="button">Sem ação</button> <!-- não faz nada (útil com JS) -->

</form>

Atributos importantes de inputs:

✅ Exercícios do Dia 2


← Dia 1↑ InícioDia 3 →

📅 DIA 3 — CSS: conectando, seletores, cores e o famoso Box Model

3.1 As 3 formas de usar CSS

HTML
<!-- 1) ARQUIVO EXTERNO (a forma certa — usaremos sempre esta) -->
<!-- No <head> do HTML: -->
<link rel="stylesheet" href="style.css">

<!-- 2) Tag <style> dentro do <head> (ok para testes rápidos) -->
<style>
    p { color: red; }
</style>

<!-- 3) Atributo style inline (EVITE — mistura conteúdo e estilo, difícil de manter) -->
<p style="color: red;">Texto vermelho</p>

Regra de prioridade (a mais específica vence): inline > id > class > tag. E !important (evite) vence tudo.

3.2 Seletores: como "apontar" para os elementos

CSS
/* Seleciona TODAS as tags <p> */
p { color: blue; }

/* Seleciona o elemento com id="titulo" (IDs são ÚNICOS na página) */
#titulo { font-size: 32px; }

/* Seleciona todos os elementos com class="card" (classes podem repetir) */
.card { background-color: lightgray; }

/* Seleciona TODOS os elementos da página */
* { margin: 0; }

/* Seleciona <a> que está DENTRO de <nav> (seletor descendente) */
nav a { text-decoration: none; }

/* Seleciona só o FILHO direto */
main > p { color: green; }

/* Seleciona <input> do tipo email (seletor de atributo) */
input[type="email"] { border: 2px solid blue; }

/* Vários seletores com a mesma regra */
h1, h2, h3 { color: navy; }

Nomenclatura de classes: use inglês, minúsculas, com hífen (kebab-case): botao-primario, card-produto, menu-item.

3.3 Cores e texto

CSS
p {
    color: #ff5733;              /* HEX: #RRGGBB (vermelho, verde, azul) — o padrão da web */
    color: rgb(255, 87, 51);     /* RGB: números de 0 a 255 */
    color: rgba(255, 87, 51, 0.5); /* RGBA: o 4º valor (0 a 1) é a TRANSPARÊNCIA (alpha) */
    color: tomato;               /* Nomes de cores também funcionam (147 nomes) */
    background-color: lightyellow; /* fundo do elemento */
    opacity: 0.7;                /* transparência do elemento INTEIRO (texto também) */
}

Pegadinha: color muda a cor do TEXTO. background-color muda o FUNDO. Os dois juntos = texto colorido sobre fundo colorido.

Propriedades de texto:

CSS
p {
    font-family: Arial, Helvetica, sans-serif;  /* lista de fontes: se a 1ª não existir, tenta a próxima */
    font-size: 18px;               /* tamanho da fonte */
    font-weight: bold;             /* espessura: normal | bold | 100–900 */
    font-style: italic;            /* normal | italic */
    line-height: 1.6;              /* altura da linha (1.5–1.7 = leitura confortável) */
    text-align: center;            /* left | center | right | justify */
    text-decoration: underline;    /* none | underline | line-through */
    text-transform: uppercase;     /* uppercase | lowercase | capitalize */
    letter-spacing: 2px;           /* espaçamento entre letras */
    text-shadow: 2px 2px 4px gray; /* sombra: x y blur cor */
}

3.4 ⭐ O BOX MODEL — o conceito mais importante do CSS

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

Código
┌─────────────────────────────────────────────┐
│  MARGIN  (espaço EXTERNO — afasta das outras caixas) │
│  ┌───────────────────────────────────────┐  │
│  │  BORDER  (a borda visível)            │  │
│  │  ┌─────────────────────────────────┐  │  │
│  │  │  PADDING (espaço INTERNO —      │  │  │
│  │  │  entre o conteúdo e a borda)    │  │  │
│  │  │  ┌───────────────────────────┐  │  │  │
│  │  │  │  CONTENT (o conteúdo:     │  │  │  │
│  │  │  │  texto, imagem...)        │  │  │  │
│  │  │  └───────────────────────────┘  │  │  │
│  │  └─────────────────────────────────┘  │  │
│  └───────────────────────────────────────┘  │
└─────────────────────────────────────────────┘
CSS
.card {
    width: 300px;          /* largura do CONTEÚDO (por padrão) */
    height: 150px;
    padding: 20px;         /* 20px nos 4 lados. Formas: padding: 10px 20px; (vertical horizontal) / padding-top, padding-right... */
    border: 2px solid black;  /* espessura estilo cor (solid | dashed | dotted) */
    border-radius: 10px;   /* cantos arredondados! (50% = círculo) */
    margin: 15px;          /* espaço externo. margin: 0 auto; centraliza HORIZONTALMENTE a caixa */
}

A pegadinha número 1 do CSS (decore isso!): por padrão, width: 300px conta SÓ o conteúdo. Se você adicionar padding: 20px e border: 2px, a caixa visual fica com 344px (300 + 40 + 4). Isso quebra layouts o tempo todo.

A solução universal — box-sizing:

CSS
/* Coloque isto no topo do seu CSS (reset básico) e a vida fica mais fácil: */
* {
    box-sizing: border-box;  /* agora width/height INCLUEM padding e border */
    margin: 0;               /* remove margens padrão do navegador */
    padding: 0;
}

3.5 Unidades de medida

UnidadeO que éQuando usar
pxPixel (fixo)Bordas, ícones, coisas pequenas
%Porcentagem do elemento PAILarguras de layout (ex.: 50% = metade do pai)
remRelativo à fonte raiz (<html>, padrão 16px → 1rem = 16px)Tamanhos de fonte (acessibilidade: respeita o zoom do usuário)
emRelativo à fonte do elemento atualEspaçamentos proporcionais
vh / vw% da altura/largura da JANELASeções de tela cheia (height: 100vh)
CSS
body { font-size: 16px; }
h1 { font-size: 2rem; }        /* = 32px */
.container { width: 80%; }     /* 80% da largura do pai */
.hero { height: 100vh; }       /* altura total da tela */

✅ Exercícios do Dia 3


← Dia 2↑ InícioDia 4 →

📅 DIA 4 — Flexbox: alinhamento sem sofrimento

4.1 O problema

Antigamente, centralizar um elemento verticalmente era um pesadelo. O Flexbox (2015+) resolveu isso: é um sistema de layout em uma dimensão (linha OU coluna) com regras simples.

4.2 Como funciona

Você transforma um elemento em container flex com display: flex;. Os filhos diretos dele viram "itens flex" e passam a obedecer alinhamento automático:

HTML
<div class="container">   <!-- VIRA O CONTAINER -->
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
</div>
CSS
.container {
    display: flex;            /* liga o flexbox */
    flex-direction: row;      /* direção: row (linha, padrão) | column (coluna) | row-reverse | column-reverse */
    justify-content: center;  /* alinha no EIXO PRINCIPAL (horizontal se row) */
    align-items: center;      /* alinha no EIXO TRANSVERSAL (vertical se row) */
    gap: 20px;                /* espaçamento ENTRE os itens (use isso, não margin!) */
}

Os valores mais usados de justify-content (eixo principal):

Código
flex-start    [1][2][3]                 (padrão: esquerda)
center        ....[1][2][3]....         (centro)
flex-end      ............[1][2][3]     (direita)
space-between [1]......[2]......[3]     (primeiro e último nas pontas)
space-around  ..[1].....[2].....[3]..   (espaço igual ao redor)
space-evenly  ...[1]...[2]...[3]...     (espaços iguais)

align-items (eixo transversal): flex-start (topo) | center (meio) | flex-end (baixo) | stretch (estica, padrão).

Propriedades nos ITENS:

CSS
.item {
    flex-grow: 1;   /* quanto o item "cresce" para ocupar espaço extra (0 = não cresce). 1 em todos = larguras iguais */
    flex-shrink: 1; /* quanto encolhe quando falta espaço */
    flex-basis: 200px; /* tamanho inicial antes de crescer/encolher */
    align-self: center;  /* alinhamento individual (sobrescreve align-items) */
    order: 2;        /* ordem visual (sem mudar o HTML) */
}

flex-wrap: por padrão os itens tentam caber numa linha (e espremem). Com flex-wrap: wrap, quando não couberem, quebram para a linha de baixo:

CSS
.container {
    display: flex;
    flex-wrap: wrap;   /* agora itens viram grade quando necessário */
}

Como centralizar qualquer coisa na tela (o clássico):

CSS
.pai {
    display: flex;
    justify-content: center;
    align-items: center;
}

4.3 Exemplo completo: navbar (barra de navegação)

HTML
<nav class="navbar">
    <a href="#" class="logo">MeuSite</a>
    <div class="links">
        <a href="#">Início</a>
        <a href="#">Sobre</a>
        <a href="#">Contato</a>
    </div>
</nav>
CSS
.navbar {
    display: flex;
    justify-content: space-between;  /* logo na esquerda, links na direita */
    align-items: center;
    padding: 15px 30px;
    background-color: #222;
}
.navbar a { color: white; text-decoration: none; }
.links { display: flex; gap: 20px; }

Regra mental: Flexbox = alinhar itens numa linha/coluna (navbar, cards lado a lado, centralizar). Grid (amanhã) = layout completo da página em 2 dimensões.

✅ Exercícios do Dia 4


← Dia 3↑ InícioDia 5 →

📅 DIA 5 — Grid e responsividade (sites que funcionam no celular)

5.1 Grid: layout em 2 dimensões (linhas E colunas ao mesmo tempo)

O Grid cria uma "tabela invisível" onde você posiciona os elementos:

CSS
.container {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;   /* 3 colunas de largura igual (1fr = 1 fração do espaço) */
    grid-template-columns: repeat(3, 1fr); /* mesmo resultado, mais legível */
    grid-template-columns: 200px 1fr;      /* coluna fixa de 200px + o resto */
    gap: 20px;                             /* espaço entre colunas E linhas */
}
HTML
<div class="galeria">
    <div class="foto">1</div>
    <div class="foto">2</div>
    <div class="foto">3</div>
    <div class="foto">4</div>
    <div class="foto">5</div>
    <div class="foto">6</div>
</div>

Com 3 colunas e 6 itens: 2 linhas de 3 — automático, sem cálculo nenhum.

Fazer um item ocupar mais espaço:

CSS
.foto-grande { grid-column: span 2; }  /* ocupa 2 colunas */
.foto-alta   { grid-row: span 2; }     /* ocupa 2 linhas */

Áreas nomeadas (layout clássico de página):

CSS
.layout {
    display: grid;
    grid-template-areas:
        "header header"
        "sidebar main"
        "footer footer";
    grid-template-columns: 250px 1fr;
    gap: 15px;
}
header { grid-area: header; }
aside  { grid-area: sidebar; }
main   { grid-area: main; }
footer { grid-area: footer; }

Flexbox ou Grid? Flexbox = alinhar uma sequência (navbar, cards). Grid = estrutura geral da página (colunas + linhas juntas). Ambos se combinam: Grid no layout, Flexbox dentro de cada bloco.

5.2 Responsividade: Media Queries

A mesma página precisa ficar boa no monitor de 24" e no celular. A ferramenta: media queries — regras CSS que só valem em certas condições (ex.: telas menores que X px).

CSS
/* Estilos padrão (desktop) vêm primeiro — ou mobile-first, como preferir */

@media (max-width: 768px) {   /* telas de até 768px de largura (tablet/celular) */
    .galeria {
        grid-template-columns: repeat(2, 1fr);  /* 2 colunas em vez de 3 */
    }
    .navbar {
        flex-direction: column;   /* menu empilhado */
        gap: 10px;
    }
}

@media (max-width: 480px) {   /* celulares pequenos */
    .galeria {
        grid-template-columns: 1fr;  /* 1 coluna só */
    }
}

Teste no DevTools: F12 → ícone de celular/tablet no topo (ou Ctrl+Shift+M) → escolha um tamanho de tela e veja o site se adaptar.

Pegadinhas comuns de responsividade:

✅ Exercícios do Dia 5


← Dia 4↑ InícioDia 6 →

📅 DIA 6 — Posicionamento, pseudo-classes e animações suaves

6.1 position: controlar onde a caixa fica

CSS
/* static (padrão): flui normalmente com a página. Nada acontece. */

.relative {
    position: relative;  /* âncora para filhos absolutos + permite top/left/right/bottom para DESLOCAR da posição original */
    top: 10px;           /* move 10px para baixo do lugar original */
    left: 20px;
}

.absolute {
    position: absolute;  /* sai do fluxo! Posiciona em relação ao ancestral mais próximo com position (senão, à página) */
    top: 0; right: 0;    /* gruda no canto superior direito do ancestral */
}

.fixed {
    position: fixed;     /* gruda na JANELA. Não rola com a página — navbar fixa, botão "voltar ao topo" */
    top: 0; left: 0;
    width: 100%;
}

.sticky {
    position: sticky;    /* comporta-se como static, mas "gruda" no topo quando você rola até ele */
    top: 0;
}

Padrão clássico: pai com position: relative + filho com position: absolute → o filho se posiciona em relação ao pai. Ex.: selo "PROMOÇÃO" no canto do card.

z-index: controla quem fica por cima quando elementos se sobrepõem. z-index: 10 fica acima de z-index: 1. Só funciona em elementos posicionados (relative/absolute/fixed/sticky).

6.2 Pseudo-classes: estados dos elementos (:)

CSS
a:hover { color: orange; }        /* quando o mouse está POR CIMA */
a:active { color: red; }          /* no instante do clique */
input:focus { border-color: blue; } /* quando o campo está selecionado/focado */
button:disabled { opacity: 0.5; }   /* botão desativado */
li:first-child { font-weight: bold; }   /* o primeiro filho */
li:last-child { border-bottom: none; }
li:nth-child(2n) { background: #f5f5f5; } /* linhas pares (efeito zebra) — 2n = pares, 3n = a cada 3 */
p:not(.destaque) { color: gray; }  /* tudo que NÃO tem a classe */

6.3 Pseudo-elementos (::): criar conteúdo decorativo

CSS
.card::before {
    content: "★ ";      /* insere conteúdo ANTES do elemento (só funciona com content) */
    color: gold;
}
.card::after {
    content: "";        /* vazio + display block + dimensões = desenho (ex.: linha decorativa) */
    display: block;
    width: 50px;
    height: 3px;
    background: orange;
    margin-top: 10px;
}

6.4 Transitions: animação suave de hover

CSS
.botao {
    background-color: blue;
    color: white;
    padding: 12px 24px;
    border: none;
    border-radius: 6px;
    cursor: pointer;              /* mãozinha ao passar o mouse (sempre em botões!) */

    transition: background-color 0.3s ease, transform 0.3s ease;
    /*            propriedade        duração  ritmo               */
}

.botao:hover {
    background-color: darkblue;
    transform: scale(1.05);       /* cresce 5% (transform: translate/rotate/scale) */
}

Regra: a transition fica no estado NORMAL (não no :hover), para a animação funcionar nos dois sentidos (entrar E sair do hover).

✅ Exercícios do Dia 6


← Dia 5↑ InícioDia 7 →

📅 DIA 7 — 🎯 PROJETO DA SEMANA 1: Página de Portfólio Pessoal

Objetivo: uma página única de portfólio — algo que você pode mostrar para colegas, professores e futuros empregadores.

Requisitos (use TUDO da semana):

  1. <!DOCTYPE html> + metas (charset, viewport) + <title> correto
  2. Estrutura semântica: headernav (menu fixo com position: sticky), main, sections, footer
  3. Seção Sobre com foto sua, <h1> com seu nome e um parágrafo
  4. Seção Projetos: 3 cards em Grid (3 colunas → 1 no celular), cada card com imagem, título, descrição e link
  5. Seção Contato: formulário (nome, email, mensagem) + links de redes sociais
  6. CSS externo com: reset (box-sizing: border-box), paleta de 2–3 cores, :hover nos links/botões, transition suave
  7. Responsivo: @media (max-width: 768px) e @media (max-width: 480px)
  8. Valide no https://validator.w3.org (cole o código, veja se não há erros)

Inspiração de estrutura:

HTML
<header>
  <nav>...</nav>
</header>
<main>
  <section id="sobre">...</section>
  <section id="projetos">
    <div class="grid-projetos">
      <article class="card">...</article>
      <article class="card">...</article>
      <article class="card">...</article>
    </div>
  </section>
  <section id="contato">
    <form>...</form>
  </section>
</main>
<footer>...</footer>

Desafio extra: publique no GitHub (crie uma conta em github.com, crie repositório, suba os arquivos) — é o seu cartão de visitas profissional.


← Dia 6↑ InícioDia 8 →

PARTE PARTE 2 — SEMANA 2: JAVASCRIPT

Mudança de mentalidade: JS é uma linguagem de programação de verdade (a mesma usada no servidor, no Node.js). Você não está mais "marcando texto" — está dando instruções ao computador. O computador faz exatamente o que você manda, na ordem que você manda. Nem mais, nem menos.

📅 DIA 8 — Primeiros passos: variáveis, tipos e operadores

8.1 Como colocar JS na página

HTML
<!-- No final do <body> (antes de </body>): o HTML já carregou, e o JS roda em cima dele -->
<script src="script.js"></script>

<!-- Ou direto no HTML (só para testes): -->
<script>
    console.log("Olá, mundo!");
</script>

O Console do DevTools (F12 → Console) é seu melhor amigo: mostra erros em vermelho e resultados de console.log. Você também pode digitar JS ali e testar na hora.

8.2 Variáveis: caixinhas com nome

JavaScript
let idade = 20;          // let: variável que PODE mudar de valor depois
const nome = "Ana";      // const: constante — NÃO pode mudar (use por padrão!)
// var: forma antiga, evite

idade = 21;              // ✅ ok, let permite
// nome = "Bruno";       // ❌ erro! const não pode ser reatribuída

// Regras de nome: sem espaços, sem começar com número, sem caracteres especiais (só _ e $)
// Convenção: camelCase — primeira palavra minúscula, próximas com maiúscula: minhaIdade, nomeCompleto

Regra prática: use const por padrão. Só use let se você PRECISA reatribuir. Se der erro "Assignment to constant variable", você sabe o motivo.

8.3 Tipos de dados

JavaScript
const texto = "Olá, mundo";       // string (texto) — aspas simples ' ', duplas " " ou crases ` `
const numero = 42;                // number — inteiros e decimais (42.5)
const verdadeiro = true;          // boolean — true ou false
const nada = null;                // null: "vazio de propósito" (você define)
let indefinido;                   // undefined: existe mas não tem valor (a linguagem define)
// Também: objetos, arrays, funções (próximos dias)

console.log(typeof texto);        // "string" — typeof diz o tipo
console.log(typeof numero);       // "number"

null vs undefined: undefined = "nunca recebeu valor". null = "recebi um valor que significa nada". Detalhe fino, mas cai em entrevista. 😄

8.4 Operadores

JavaScript
// Aritméticos
5 + 3    // 8  (soma)
5 - 3    // 2  (subtração)
5 * 3    // 15 (multiplicação)
5 / 2    // 2.5 (divisão)
5 % 2    // 1  (RESTO da divisão — ótimo para par/ímpar)
2 ** 3   // 8  (potência)
let x = 5; x++;   // x vira 6 (incremento). x-- decrementa.

// Atalhos
x += 3;   // x = x + 3
x -= 3;   // x = x - 3
x *= 2;   // x = x * 2

// Comparação — SEMPRE use === e !== (triplo!)
5 == "5"    // true  (== compara ignorando tipo — EVITE, causa bugs!)
5 === "5"   // false (=== compara valor E tipo — USE SEMPRE)
5 !== "5"   // true
10 > 5      // true | < menor | >= maior ou igual | <= menor ou igual

// Lógicos
true && false   // false (E: os dois precisam ser true)
true || false   // true  (OU: pelo menos um true)
!true           // false (NEGAÇÃO: inverte)

8.5 Template literals (crases) — o jeito moderno de montar texto

JavaScript
const nome = "Ana";
const idade = 20;

// Jeito antigo (concatenação com +):
console.log("Meu nome é " + nome + " e tenho " + idade + " anos.");

// Jeito moderno (template literal com crases ` e ${}):
console.log(`Meu nome é ${nome} e tenho ${idade} anos.`);

// Dá para fazer contas dentro:
console.log(`Ano que vem farei ${idade + 1} anos.`);

✅ Exercícios do Dia 8


← Dia 7↑ InícioDia 9 →

📅 DIA 9 — Condicionais, loops e funções (o coração da lógica)

9.1 Condicionais: o computador decide

JavaScript
const nota = 7.5;

if (nota >= 7) {
    console.log("Aprovado! 🎉");
} else if (nota >= 5) {
    console.log("Recuperação 😬");
} else {
    console.log("Reprovado 💔");
}

// Operador ternário: if/else em uma linha (para casos simples)
const resultado = nota >= 7 ? "Aprovado" : "Reprovado";
//                 condição      valor se true    valor se false

// switch: muitas comparações com o MESMO valor
const dia = "segunda";
switch (dia) {
    case "sabado":
    case "domingo":
        console.log("Fim de semana!");
        break;              // SEMPRE coloque break (senão "cai" no próximo case)
    default:                // se nenhum case bater
        console.log("Dia útil");
}

9.2 Loops: repetição sem copiar e colar

JavaScript
// for: quando você sabe QUANTAS vezes
for (let i = 0; i < 5; i++) {
    //   início    condição    incremento
    console.log(`Volta número ${i + 1}`);
}
// imprime: Volta número 1, 2, 3, 4, 5

// while: quando você não sabe quantas vezes (repete ENQUANTO a condição for true)
let tentativas = 0;
while (tentativas < 3) {
    console.log("Tentando...");
    tentativas++;   // SEMPRE incremente algo, senão = loop infinito (trava o navegador!)
}

// for...of: percorrer itens de um array (veremos arrays amanhã)
const frutas = ["maçã", "banana", "uva"];
for (const fruta of frutas) {
    console.log(fruta);
}

// break: para o loop na hora. continue: pula para a próxima volta
for (let i = 1; i <= 10; i++) {
    if (i === 5) break;      // para no 4
    if (i % 2 === 0) continue;  // pula pares
    console.log(i);          // imprime 1, 3
}

9.3 Funções: blocos de código reutilizáveis

JavaScript
// Declaração tradicional
function somar(a, b) {
    return a + b;       // return devolve o resultado para quem chamou
}
console.log(somar(2, 3));   // 5 — passamos 2 e 3 como ARGUMENTOS

// Arrow function (jeito moderno, você verá MUITO por aí)
const multiplicar = (a, b) => a * b;   // sem {} = return implícito
console.log(multiplicar(4, 2));        // 8

// Arrow com corpo maior
const saudacao = (nome) => {
    const mensagem = `Olá, ${nome}!`;
    return mensagem;
};

// Função SEM return devolve undefined
function semRetorno() {
    console.log("faz algo");
}
console.log(semRetorno());  // undefined

// Parâmetro padrão
function dividir(a, b = 2) {   // se b não for passado, vale 2
    return a / b;
}
console.log(dividir(10));   // 5

Escopo (resumo): variável criada dentro de {} de função existe só lá dentro. Variável no topo do arquivo (global) existe em todo lugar. Não declare variáveis globais à toa.

✅ Exercícios do Dia 9


← Dia 8↑ InícioDia 10 →

📅 DIA 10 — Arrays e objetos: organizando dados

10.1 Arrays: listas

JavaScript
const frutas = ["maçã", "banana", "uva"];
//                índice:   0        1      2   ← SEMPRE começa em 0!

console.log(frutas[0]);        // "maçã" (acessar pelo índice entre colchetes)
console.log(frutas.length);    // 3 (quantidade de itens)
console.log(frutas[frutas.length - 1]);  // "uva" (sempre o último item)

frutas.push("laranja");        // adiciona no FIM  → ["maçã","banana","uva","laranja"]
frutas.pop();                  // remove o ÚLTIMO  → ["maçã","banana","uva"]
frutas.unshift("manga");       // adiciona no INÍCIO
frutas.shift();                // remove o PRIMEIRO

frutas.indexOf("banana");      // 1 (posição) | -1 se não existir
frutas.includes("uva");        // true (existe?)
frutas.join(", ");             // "maçã, banana, uva" (vira texto)

// Percurso moderno: forEach (para cada item, faça...)
frutas.forEach((fruta) => console.log(fruta));

map e filter — os dois mais importantes (decore!):

JavaScript
// map: transforma CADA item e devolve um NOVO array do mesmo tamanho
const numeros = [1, 2, 3, 4];
const dobrados = numeros.map((n) => n * 2);
console.log(dobrados);   // [2, 4, 6, 8]  — o original NÃO muda

const precoEmCentavos = [100, 250, 990];
const precoEmReais = precoEmCentavos.map((c) => `R$ ${(c / 100).toFixed(2)}`);
// ["R$ 1.00", "R$ 2.50", "R$ 9.90"]

// filter: devolve um NOVO array só com os itens que passam no teste (true)
const numeros2 = [1, 2, 3, 4, 5, 6];
const pares = numeros2.filter((n) => n % 2 === 0);
console.log(pares);      // [2, 4, 6]

// reduce: reduz tudo a UM valor (soma, média...)
const total = numeros2.reduce((acumulador, n) => acumulador + n, 0);
console.log(total);      // 21

10.2 Objetos: agrupando informações relacionadas

JavaScript
const aluno = {
    nome: "Ana",
    idade: 20,
    curso: "ADS",
    aprovada: true,
    materias: ["Matemática", "Programação"],   // objetos podem ter arrays
    endereco: {                                 // e objetos dentro de objetos!
        cidade: "São Paulo",
        uf: "SP"
    },
    apresentar() {                              // métodos = funções dentro do objeto
        return `Sou ${this.nome}, do curso de ${this.curso}.`;
        //       ^^^^ this = o próprio objeto (aqui: aluno)
    }
};

console.log(aluno.nome);            // "Ana" (acesso com ponto)
console.log(aluno["nome"]);         // "Ana" (acesso com colchetes — útil p/ nomes dinâmicos)
console.log(aluno.endereco.cidade); // "São Paulo" (caminho)
console.log(aluno.apresentar());    // "Sou Ana, do curso de ADS."

aluno.idade = 21;       // alterar
aluno.email = "ana@email.com";  // adicionar propriedade nova

// O padrão mais comum do mundo real: ARRAY DE OBJETOS
const produtos = [
    { nome: "Teclado", preco: 150 },
    { nome: "Mouse",   preco: 80 },
    { nome: "Monitor", preco: 900 }
];

const caros = produtos.filter((p) => p.preco > 100);
// [{ nome: "Teclado", preco: 150 }, { nome: "Monitor", preco: 900 }]

const nomes = produtos.map((p) => p.nome);
// ["Teclado", "Mouse", "Monitor"]

✅ Exercícios do Dia 10


← Dia 9↑ InícioDia 11 →

📅 DIA 11 — DOM: o JavaScript "enxergando" a página

11.1 O que é o DOM?

Quando o navegador lê seu HTML, ele monta uma árvore de objetos na memória chamada DOM (Document Object Model). Cada tag vira um "nó" da árvore. O JavaScript pode achar, ler, criar e modificar esses nós. É assim que a página "ganha vida".

Código
document (a página inteira)
└── body
    ├── h1  "Minha Lista"
    ├── ul
    │   ├── li  "Estudar HTML"   ← o JS pode achar este li...
    │   └── li  "Estudar CSS"
    └── button  "Adicionar"      ← ...e reagir quando clicam aqui

11.2 Selecionando elementos (o "radar" do JS)

JavaScript
// Pelo ID (retorna UM elemento ou null)
const titulo = document.getElementById("titulo");

// Pelo seletor CSS (retorna UM — o primeiro que encontrar)
const primeiroCard = document.querySelector(".card");
const botao = document.querySelector("#btn-enviar");
const link = document.querySelector("nav a");

// Por seletor CSS (retorna TODOS — uma NodeList, parecida com array)
const cards = document.querySelectorAll(".card");
console.log(cards.length);           // quantidade
cards.forEach((card) => console.log(card));  // percorrer

11.3 Lendo e alterando conteúdo

JavaScript
const titulo = document.querySelector("h1");

titulo.textContent = "Novo título!";   // muda o texto (USE SEMPRE para texto)
console.log(titulo.textContent);       // "Novo título!"

// innerHTML: muda o HTML interno (cuidado: aceita HTML, mas é risco de segurança
// se o conteúdo vier do usuário — prefira textContent)
titulo.innerHTML = "<em>Título</em> com itálico";

// Atributos
const link = document.querySelector("a");
link.href = "https://google.com";
link.setAttribute("target", "_blank");
console.log(link.getAttribute("href"));

// Estilos (inline — ok para mudanças pontuais)
titulo.style.color = "red";
titulo.style.fontSize = "32px";   // camelCase! (font-size vira fontSize)
titulo.style.display = "none";    // esconde o elemento

11.4 Classes: o jeito certo de estilizar via JS

JavaScript
const card = document.querySelector(".card");

card.classList.add("destaque");      // adiciona classe
card.classList.remove("destaque");   // remove
card.classList.toggle("destaque");   // liga/desliga (interruptor — PERFEITO p/ dark mode)
card.classList.contains("destaque"); // true/false (tem a classe?)
CSS
/* No CSS: */
.card.destaque {
    border: 2px solid orange;
    background-color: #fff8e1;
}

11.5 Criando e removendo elementos

JavaScript
// 1. Cria o elemento (ainda não está na página!)
const novoItem = document.createElement("li");
novoItem.textContent = "Estudar JavaScript";

// 2. Coloca dentro de um pai existente
const lista = document.querySelector("ul");
lista.appendChild(novoItem);        // adiciona no fim
// lista.prepend(novoItem);         // adiciona no início

// 3. Remove
novoItem.remove();                  // some da página
// lista.removeChild(novoItem);     // forma antiga

// Padrão completo: array → elementos na tela
const tarefas = ["Estudar HTML", "Estudar CSS", "Estudar JS"];
const listaTarefas = document.querySelector("#lista");

tarefas.forEach((tarefa) => {
    const li = document.createElement("li");
    li.textContent = tarefa;
    listaTarefas.appendChild(li);
});

✅ Exercícios do Dia 11


← Dia 10↑ InícioDia 12 →

📅 DIA 12 — Eventos: a página reage ao usuário + localStorage

12.1 addEventListener: "fique de ouvido" para o clique

JavaScript
const botao = document.querySelector("#btn-clique");

botao.addEventListener("click", () => {
    console.log("Você clicou no botão!");
});
//            ↑ evento   ↑ o que fazer quando acontecer (callback)

Eventos mais comuns:

JavaScript
elemento.addEventListener("click", handler);     // clique
elemento.addEventListener("dblclick", handler);  // duplo clique
elemento.addEventListener("mouseover", handler); // mouse por cima
elemento.addEventListener("mouseout", handler);  // mouse saiu
elemento.addEventListener("input", handler);     // digitou em um campo (dispara a cada tecla)
elemento.addEventListener("change", handler);    // campo mudou e perdeu foco (select, checkbox)
elemento.addEventListener("keydown", handler);   // apertou tecla (event.key = qual tecla)
elemento.addEventListener("submit", handler);    // enviou formulário (no <form>)

O objeto event: o navegador passa informações sobre o evento:

JavaScript
document.querySelector("input").addEventListener("input", (event) => {
    console.log(event.target);       // o elemento que disparou
    console.log(event.target.value); // o valor digitado ← MUITO usado
});

document.addEventListener("keydown", (event) => {
    if (event.key === "Enter") console.log("Apertou Enter!");
});

12.2 Formulários: capturando o que o usuário digitou

JavaScript
const formulario = document.querySelector("#meu-form");

formulario.addEventListener("submit", (event) => {
    event.preventDefault();   // ⚠️ IMPEDE o recarregamento da página (comportamento padrão do form)!

    // Lê os valores pelos "name" dos campos:
    const nome = document.querySelector("#nome").value;
    const email = document.querySelector("#email").value;

    console.log(`Cadastro: ${nome} (${email})`);

    // Limpa o formulário:
    formulario.reset();
});

12.3 Adicionando itens a uma lista (o exercício que vira seu projeto final)

JavaScript
const formulario = document.querySelector("#form-tarefa");
const input = document.querySelector("#nova-tarefa");
const lista = document.querySelector("#lista");

formulario.addEventListener("submit", (event) => {
    event.preventDefault();

    const texto = input.value.trim();   // .trim() remove espaços em branco das pontas
    if (texto === "") return;           // não aceita tarefa vazia

    const li = document.createElement("li");
    li.textContent = texto;

    // Botão de remover em cada item:
    const botaoRemover = document.createElement("button");
    botaoRemover.textContent = "❌";
    botaoRemover.addEventListener("click", () => li.remove());
    li.appendChild(botaoRemover);

    lista.appendChild(li);
    input.value = "";       // limpa o campo
    input.focus();          // devolve o foco para continuar digitando
});

12.4 localStorage: dados que sobrevivem ao refresh 🧠

O localStorage guarda dados no navegador do usuário (até ~5MB, texto puro). É a memória do seu site:

JavaScript
// Salvar (só aceita TEXTO):
localStorage.setItem("nome", "Ana");
localStorage.setItem("idade", "20");

// Ler:
const nome = localStorage.getItem("nome");   // "Ana" (ou null se não existir)
const idade = Number(localStorage.getItem("idade"));  // Number() converte texto → número

// Remover:
localStorage.removeItem("nome");
// localStorage.clear();  // limpa TUDO

// Para salvar ARRAYS/OBJETOS: JSON.stringify (vira texto) e JSON.parse (volta a ser objeto)
const tarefas = ["Estudar HTML", "Estudar CSS"];
localStorage.setItem("tarefas", JSON.stringify(tarefas));  // salva como "[...]"

const tarefasSalvas = JSON.parse(localStorage.getItem("tarefas"));  // volta a ser array
console.log(tarefasSalvas[0]);  // "Estudar HTML"

Padrão completo para o seu app (salvar → carregar na abertura):

JavaScript
const lista = document.querySelector("#lista");
const input = document.querySelector("#nova-tarefa");
const formulario = document.querySelector("#form-tarefa");

// 1. Função que DESENHA a lista na tela (a partir de um array):
function renderizar(tarefas) {
    lista.innerHTML = "";          // limpa a lista
    tarefas.forEach((tarefa) => {
        const li = document.createElement("li");
        li.textContent = tarefa;
        lista.appendChild(li);
    });
}

// 2. Carregar do localStorage quando a página abre:
let tarefas = JSON.parse(localStorage.getItem("tarefas")) || [];
//   ↑ se não existir nada, vira [] (array vazio) — o || é "fallback"

renderizar(tarefas);

// 3. Adicionar tarefa:
formulario.addEventListener("submit", (event) => {
    event.preventDefault();
    const texto = input.value.trim();
    if (texto === "") return;

    tarefas.push(texto);
    localStorage.setItem("tarefas", JSON.stringify(tarefas));  // salvar
    renderizar(tarefas);                                        // redesenhar
    input.value = "";
});

Pegadinhas: o localStorage é por origem (domínio) — cada site tem o seu. E guardar senha/dado sensível lá = nunca. Só dados simples.

✅ Exercícios do Dia 12


← Dia 11↑ InícioDia 13 →

📅 DIA 13 — JSON, fetch e APIs: buscando dados da internet

13.1 O que é uma API?

Uma API é um "garçom" de um sistema: você faz um pedido (requisição) e ela traz o que você pediu (resposta). Muitos serviços públicos oferecem APIs gratuitas que devolvem dados em JSON — exatamente a estrutura de array de objetos que você já aprendeu!

13.2 JSON — o formato de dados da web

Código
[
  { "nome": "Ana", "idade": 20 },
  { "nome": "Bruno", "idade": 22 }
]

É literalmente texto que parece um array de objetos. No JS:

JavaScript
// JSON → objeto JS: JSON.parse
const texto = '{"nome": "Ana"}';
const objeto = JSON.parse(texto);
console.log(objeto.nome);   // "Ana"

// objeto JS → JSON: JSON.stringify
const deVolta = JSON.stringify(objeto);
console.log(deVolta);       // '{"nome":"Ana"}'

13.3 fetch + async/await: buscar dados

JavaScript
// async = função que pode esperar coisas. await = "espere terminar antes de continuar".
async function carregarUsuarios() {
    try {
        // 1. Busca (fetch) — isso leva tempo (rede), por isso o await
        const resposta = await fetch("https://jsonplaceholder.typicode.com/users");
        // 2. Converte a resposta em JSON (array de objetos)
        const usuarios = await resposta.json();

        console.log(usuarios);  // veja no console!
        return usuarios;
    } catch (erro) {
        // 3. Se QUALQUER coisa der errado (sem internet, servidor fora...):
        console.error("Erro ao carregar:", erro);
    }
}

Ligando tudo — buscar e desenhar na tela:

HTML
<body>
    <button id="btn-carregar">Carregar usuários</button>
    <ul id="lista"></ul>
    <script src="script.js"></script>
</body>
JavaScript
const botao = document.querySelector("#btn-carregar");
const lista = document.querySelector("#lista");

botao.addEventListener("click", async () => {
    botao.textContent = "Carregando...";   // feedback pro usuário
    botao.disabled = true;

    try {
        const resposta = await fetch("https://jsonplaceholder.typicode.com/users");
        if (!resposta.ok) throw new Error(`Erro HTTP: ${resposta.status}`);  // status 200 = ok
        const usuarios = await resposta.json();

        lista.innerHTML = "";   // limpa
        usuarios.forEach((usuario) => {
            const li = document.createElement("li");
            li.textContent = `${usuario.name} — ${usuario.email}`;
            lista.appendChild(li);
        });
    } catch (erro) {
        lista.innerHTML = `<li>❌ Falha ao carregar: ${erro.message}</li>`;
    } finally {
        botao.textContent = "Carregar usuários";   // restaura (roda sempre, certo ou errado)
        botao.disabled = false;
    }
});

APIs gratuitas para praticar:

✅ Exercícios do Dia 13


← Dia 12↑ InícioDia 14 →

📅 DIA 14 — 🎯 PROJETO FINAL: To-Do List completa

Você já tem todas as peças. Agora é juntar: HTML + CSS + JS + localStorage.

Requisitos (mínimo):

  1. ✅ Adicionar tarefa (formulário + Enter)
  2. ✅ Marcar como concluída (clique no texto → riscado)
  3. ✅ Remover tarefa (botão ❌)
  4. ✅ Persistência com localStorage (recarregou, continua lá)
  5. ✅ Contador de tarefas pendentes
  6. ✅ Layout responsivo decente

Bônus (se sobrar tempo): filtros (Todas / Ativas / Concluídas), campo de busca, editar tarefa, data de criação.

Estrutura sugerida (3 arquivos):

index.html:

HTML
<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Minha To-Do List</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="app">
        <h1>✅ Minhas Tarefas</h1>
        <p id="contador"></p>
        <form id="form-tarefa">
            <input type="text" id="nova-tarefa" placeholder="O que precisa ser feito?" required>
            <button type="submit">Adicionar</button>
        </form>
        <ul id="lista"></ul>
    </div>
    <script src="script.js"></script>
</body>
</html>

style.css: (você já sabe! Flexbox centralizando, cards, hover, media query p/ celular — capriche)

script.js: (o padrão do dia 12, com uma evolução — cada tarefa vira um objeto com texto e feita)

JavaScript
const form = document.querySelector("#form-tarefa");
const input = document.querySelector("#nova-tarefa");
const lista = document.querySelector("#lista");
const contador = document.querySelector("#contador");

// Cada tarefa: { texto: "Estudar JS", feita: false }
let tarefas = JSON.parse(localStorage.getItem("tarefas")) || [];

function salvar() {
    localStorage.setItem("tarefas", JSON.stringify(tarefas));
}

function atualizarContador() {
    const pendentes = tarefas.filter((t) => !t.feita).length;
    contador.textContent = `${pendentes} pendente(s)`;
}

function renderizar() {
    lista.innerHTML = "";
    tarefas.forEach((tarefa, indice) => {
        const li = document.createElement("li");
        li.textContent = tarefa.texto;
        if (tarefa.feita) li.classList.add("feita");   // CSS: .feita { text-decoration: line-through; ... }

        // Clique no item = marcar/desmarcar
        li.addEventListener("click", () => {
            tarefa.feita = !tarefa.feita;
            salvar();
            renderizar();
        });

        // Botão remover
        const btnRemover = document.createElement("button");
        btnRemover.textContent = "❌";
        btnRemover.addEventListener("click", (event) => {
            event.stopPropagation();   // impede que o clique chegue no <li> (senão marca como feita!)
            tarefas.splice(indice, 1); // remove do array pela posição
            salvar();
            renderizar();
        });

        li.appendChild(btnRemover);
        lista.appendChild(li);
    });
    atualizarContador();
}

form.addEventListener("submit", (event) => {
    event.preventDefault();
    const texto = input.value.trim();
    if (texto === "") return;
    tarefas.push({ texto: texto, feita: false });
    salvar();
    renderizar();
    input.value = "";
    input.focus();
});

renderizar();   // carrega tudo ao abrir a página

Após terminar — PUBLIQUE!

  1. Crie o repositório no GitHub e suba os 3 arquivos
  2. Publique no Cloudflare Pages → você terá https://seu-projeto.pages.dev para mostrar para todo mundo (peça para mim — tenho o script pronto, é rápido!)
  3. Mandou bem? Faça uma segunda versão com filtros e busca — é assim que se vira desenvolvedor: iterando.

← Dia 13↑ Início

PARTE PARTE 3 — REFERÊNCIAS RÁPIDAS

Glossário de tags HTML (consulte sempre que esquecer)

TagO que faz
<html>Raiz do documento
<head>Metadados invisíveis
<body>Conteúdo visível
<h1><h6>Títulos (1 = mais importante)
<p>Parágrafo
<a>Link (atributo href)
<img>Imagem (atributos src, alt)
<ul> / <ol> / <li>Listas: não ordenada / ordenada / item
<div>Bloco genérico
<span>Trecho inline genérico
<header> / <footer>Cabeçalho / rodapé da página ou de uma seção
<nav>Menu de navegação
<main>Conteúdo principal (único)
<section>Seção temática
<article>Conteúdo independente (post, notícia)
<aside>Conteúdo lateral
<table> <tr> <td> <th>Tabela / linha / célula / célula de cabeçalho
<form>Formulário
<input>Campo de entrada (type: text, email, password, number, date, checkbox, radio, color...)
<label>Rótulo do campo (atributo forid)
<select> <option>Lista suspensa / opção
<textarea>Campo de texto longo
<button>Botão (type: submit, reset, button)
<br> / <hr>Quebra de linha / linha horizontal
<strong> / <em>Negrito / itálico (com significado)
<code>Trecho de código
<blockquote>Citação longa
<time>Data/hora legível
<figure> <figcaption>Imagem com legenda
<!-- -->Comentário

Glossário de propriedades CSS

PropriedadeO que faz
color / background-colorCor do texto / do fundo
font-size / font-familyTamanho / fonte
font-weight / font-styleEspessura / itálico
text-align / text-decorationAlinhamento / decoração do texto
line-heightAltura da linha
width / heightLargura / altura
max-widthLargura máxima (responsividade)
margin / paddingEspaço externo / interno
border / border-radiusBorda / cantos arredondados
box-sizingborder-box = width inclui padding+borda
displayblock / inline / flex / grid / none
flex-directionrow / column
justify-contentAlinhamento no eixo principal
align-itemsAlinhamento no eixo transversal
gapEspaço entre itens flex/grid
grid-template-columnsColunas do grid
positionstatic / relative / absolute / fixed / sticky
top / right / bottom / leftDeslocamento do elemento posicionado
z-indexCamada (quem fica por cima)
transitionAnimação suave entre estados
transformscale() / translate() / rotate()
cursorFormato do mouse (pointer = mãozinha)
opacityTransparência (0–1)
overflowComportamento do conteúdo que transborda

Comandos JS que você mais vai usar

JavaScript
console.log(x)                    // imprimir/debugar
const / let                       // declarar variáveis
if / else / switch                // decisões
for / while / for...of            // repetição
function / () =>                  // funções
array.map(f) / array.filter(f)    // transformar / filtrar
array.forEach(f)                  // percorrer
objeto.propriedade                // acessar objeto
document.querySelector(css)       // achar elemento
elemento.textContent              // ler/mudar texto
elemento.classList.add/remove/toggle  // classes
elemento.addEventListener(ev, f)  // eventos
elemento.style.propriedade        // estilos inline
localStorage.setItem/getItem      // persistência
JSON.stringify / JSON.parse       // objeto ↔ texto
async / await / fetch(url)        // chamadas de rede
event.preventDefault()            // parar comportamento padrão

PARTE PARTE 4 — PLANO DE ESTUDOS E RECURSOS

Rotina diária recomendada (1h30–2h)

  1. 10 min: revisão rápida do dia anterior (releia o código que fez)
  2. 30–40 min: teoria deste guia (leia, digite os exemplos)
  3. 50–70 min: exercícios do dia + um desafio a mais
  4. 5 min: anote o que aprendeu e o que ficou confuso (no fim da semana, revise as dúvidas)

Recursos gratuitos

O que NÃO estudar agora (armadilhas do iniciante)

Checklist final (depois das 2 semanas, você deve saber)


Bons estudos! Se travar, aplique a regra dos 15 minutos: tente sozinho, depois pesquise ("MDN "), e se ainda assim não sair, pergunte para alguém (ou para mim!) mostrando exatamente o que tentou. 🔥