Do Zero ao Código: Construindo Modo Escuro e Pokédex com API e JavaScript Puro
Aprender JavaScript é mais do que decorar sintaxe, é entender como o código ganha vida no navegador e transforma ideias em experiências reais. Nesta aula, vamos explorar isso na prática com dois mini-projetos que unem criatividade e fundamentos do front-end.
O primeiro é voltado para interatividade e estilo, com a criação de um seletor de tema (modo claro e escuro). O segundo foca em consumir e exibir dados de uma API real, construindo uma Pokédex divertida e funcional.
Ambos os projetos têm o mesmo propósito: mostrar como conceitos básicos de HTML, CSS e JavaScript puro podem ser combinados para criar aplicações modernas, dinâmicas e com uma ótima experiência de usuário.
Projeto 1: Crie um Seletor de Tema (Dark Mode) com JavaScript e localStorage📚
No mundo do desenvolvimento front-end, criar uma experiência de usuário agradável é fundamental. E uma das funcionalidades mais pedidas e apreciadas hoje em dia é o seletor de tema (Modo Claro e Escuro). Além de dar conforto visual, é um excelente projeto para praticar conceitos essenciais de JavaScript.
Neste tutorial, vamos construir juntos, do zero, um projeto divertido chamado “FiloDex”: uma Pokedex de Filósofos. Mas o foco principal não será a filosofia, e sim o código por trás da mágica!
Você vai aprender a:
- Estruturar o projeto com HTML semântico.
- Estilizar e criar temas usando variáveis CSS.
- Manipular a página dinamicamente com JavaScript (DOM).
- Salvar a preferência do usuário para que o tema persista, mesmo depois de fechar o navegador, usando
localStorage
.
BORA CODAR!!
Pré-requisitos
Para acompanhar este tutorial, é bom que você tenha um conhecimento básico de:
- HTML: Estrutura de tags, como
<div>
,<h1>
,<img>
. - CSS: Seletores de classe, propriedades como
background-color
ecolor
. - Um editor de código (como o VS Code) e um navegador.
Vamos dividir nosso projeto em três partes: a estrutura, o estilo e a interatividade.
Parte 1: A Estrutura com HTML
Primeiro, precisamos do esqueleto do nosso site. Criaremos um arquivo index.html
com uma estrutura simples: um cabeçalho para o título e o botão de toggle, e uma área principal para os nossos “cards” de filósofos.
Crie o arquivo index.html
e cole o código abaixo:
HTML
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FiloDex - Pokedex de Filósofos</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>📚 FiloDex</h1>
<input type="checkbox" id="theme-toggle" class="theme-toggle-checkbox">
<label for="theme-toggle" class="theme-toggle-label">
<span class="sun-icon">☀️</span>
<span class="moon-icon">🌙</span>
</label>
</header>
<main class="philosopher-grid">
<div class="card">
<img src="https://via.placeholder.com/150" alt="Imagem de Platão">
<h2>Platão #001</h2>
<div class="tags">
<span class="tag idealismo">Idealismo</span>
</div>
<p>Discípulo de Sócrates, sua filosofia é marcada pela Teoria das Ideias, que postula um mundo de formas perfeitas e eternas.</p>
</div>
</main>
<script src="script.js"></script>
</body>
</html>
Ponto importante: Note que nosso botão de toggle é, na verdade, um input
do tipo checkbox
. Essa é uma técnica comum e acessível para criar botões de ligar/desligar. Nós vamos escondê-lo com CSS e usar o label
(com os ícones de sol e lua) como a parte clicável.
Parte 2: A Estilização com CSS
Agora, vamos dar vida ao nosso HTML. O segredo para um seletor de tema eficiente está no uso de variáveis CSS. Definimos nossas cores principais em um lugar só e, para ativar o modo escuro, apenas trocamos os valores dessas variáveis.
Crie o arquivo style.css
e adicione o seguinte:
CSS
/* 1. Definindo nossas variáveis de cor para o tema padrão (Claro) */
:root {
--bg-color: #ffffff;
--card-bg-color: #f0f0f0;
--text-color: #333333;
--shadow-color: rgba(0, 0, 0, 0.1);
}
/* 2. Definindo as mesmas variáveis, mas com valores para o tema Escuro */
body.dark {
--bg-color: #121212;
--card-bg-color: #2a2a2a;
--text-color: #e0e0e0;
--shadow-color: rgba(0, 0, 0, 0.4);
}
/* 3. Usando as variáveis para estilizar os elementos */
body {
background-color: var(--bg-color); /* Usa a variável de cor de fundo */
color: var(--text-color); /* Usa a variável de cor do texto */
font-family: sans-serif;
transition: background-color 0.3s ease, color 0.3s ease; /* Animação suave */
}
.card {
background-color: var(--card-bg-color);
border-radius: 15px;
padding: 1.5rem;
box-shadow: 0 4px 15px var(--shadow-color);
/* ... outros estilos ... */
}
/* ... cole o restante do seu CSS para o header, grid, etc. aqui ... */
Como funciona? Por padrão, o <body>
usa as cores definidas no :root
. Quando adicionarmos a classe .dark
ao <body>
via JavaScript, as regras dentro de body.dark
terão prioridade, e os valores das variáveis serão trocados, mudando o tema do site inteiro instantaneamente!
Parte 3: A Interatividade com JavaScript
Aqui é onde a mágica acontece! Vamos capturar o clique no botão, trocar a classe do body
e usar o localStorage
para salvar a escolha.
Crie o arquivo script.js
:
JavaScript
// 1. Selecionamos os elementos que vamos manipular
const toggle = document.getElementById('theme-toggle');
const body = document.body;
// --- LÓGICA PARA RESTAURAR O TEMA ---
// 3. Verificamos se há um tema salvo no localStorage
const savedTheme = localStorage.getItem('theme');
// Se existir um tema salvo...
if (savedTheme) {
// ...adicionamos a classe do tema salvo ('dark') ao body
body.classList.add(savedTheme);
// ...e marcamos o checkbox para refletir o estado ativo
toggle.checked = true;
}
// --- LÓGICA PARA TROCAR O TEMA ---
// 2. Adicionamos um "ouvinte" que espera por uma mudança no checkbox
toggle.addEventListener('change', () => {
// Se o checkbox estiver MARCADO (ativado)...
if (toggle.checked) {
// ...adicionamos a classe 'dark' ao body
body.classList.add('dark');
// ...e salvamos a preferência 'dark' no localStorage
localStorage.setItem('theme', 'dark');
} else {
// ...caso contrário (desmarcado), removemos a classe 'dark'
body.classList.remove('dark');
// ...e removemos a preferência do localStorage
localStorage.removeItem('theme');
}
});
O que é o localStorage
? Pense nele como um pequeno “bloco de notas” que o seu navegador guarda para cada site. Com localStorage.setItem('chave', 'valor')
, nós escrevemos uma nota. Com localStorage.getItem('chave')
, nós lemos essa nota. Ela fica salva mesmo que você feche a aba!
É por isso que a primeira coisa que nosso script faz é verificar se existe uma nota chamada ‘theme’. Se existir, ele já aplica o tema escuro antes mesmo de você fazer qualquer coisa.
Conclusão e Próximos Passos
Parabéns! Você acabou de criar uma das funcionalidades mais modernas e úteis do desenvolvimento front-end. Você não só aprendeu a criar um seletor de tema, mas também entendeu a lógica por trás da persistência de dados com localStorage
, uma habilidade que você usará em inúmeros projetos.
Desafios para você ir além:
- Adicione mais filósofos: Popule seu FiloDex com mais cards.
- Animações CSS: Adicione transições mais elaboradas quando os cards aparecem na tela.
- Salvar mais coisas: Crie um botão de “Favoritar” em cada card e use o
localStorage
para salvar quais filósofos o usuário favoritou.
🔗Projeto no github para pegar as iamgens: https://github.com/guilherme-silvam/FiloDex?tab=readme-ov-file
Projeto 2: Crie sua própria Pokédex com HTML, CSS e JavaScript do Zero 🐉
Já pensou em criar sua própria Pokédex funcional usando apenas as tecnologias web mais fundamentais? Neste tutorial, vamos embarcar em uma jornada divertida para construir um “Poké-Busca”: um pequeno aplicativo web onde você pode pesquisar por um Pokémon e ver suas informações básicas.
O melhor de tudo? Faremos isso usando apenas HTML, CSS e JavaScript puros, sem frameworks ou bibliotecas complicadas. É o projeto perfeito para você que está começando e quer entender na prática como consumir dados de uma API real.
Ao final deste guia, você terá um projeto assim:
BORA CODAR!
O que vamos aprender?
- HTML: Estruturar a página da nossa aplicação.
- CSS: Estilizar tudo para ficar com uma cara incrível, incluindo a fonte e as cores da logo do Pokémon.
- JavaScript: A mágica por trás de tudo! Vamos aprender a:
- Capturar a entrada do usuário.
- Fazer uma requisição a uma API pública (a PokéAPI).
- Manipular os dados recebidos (em formato JSON).
- Exibir dinamicamente as informações na tela.
Ferramentas Necessárias
- Um editor de código (como o Visual Studio Code).
- Um navegador web (Google Chrome, Firefox, etc.).
- Um pouco de curiosidade e vontade de aprender!
Passo 1: A Estrutura (HTML)
Todo projeto web começa com o esqueleto: o HTML. Ele define quais elementos estarão na nossa página, como o título, os campos de texto e os botões.
Crie um arquivo chamado index.html
e cole o código abaixo:
HTML
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Poké-Busca</title>
<link rel="icon" type="image/png" href="pokeball-icon.png">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="container">
<h1>Poké-Busca</h1>
<div class="search-box">
<input type="text" id="pokemonInput" placeholder="Digite o nome ou ID">
<button id="searchButton">Buscar</button>
<button id="resetButton">Limpar</button>
</div>
<div id="pokemonDisplay" class="pokemon-display-area"></div>
</main>
<script src="script.js"></script>
</body>
</html>
O que fizemos aqui?
- Criamos a estrutura básica com um título
<h1>
. - Adicionamos um
input
para o usuário digitar, e doisbutton
, um para buscar e outro para limpar. - Definimos uma
div
com o idpokemonDisplay
. É aqui que as informações do Pokémon aparecerão. - Linkamos nossos futuros arquivos
style.css
escript.js
.
Não se esqueça: Você precisará de uma imagem de pokébola chamada pokeball-icon.png
na mesma pasta para o ícone da aba funcionar!
Passo 2: Dando Estilo e Personalidade (CSS)
Um esqueleto não é nada sem músculos e pele, certo? O CSS vai dar vida e cor ao nosso projeto.
Crie um arquivo chamado style.css
e adicione o código a seguir. Os comentários explicam o que cada parte faz!
CSS
/* Importa a fonte personalizada que imita a da logo do Pokémon */
@import url('https://fonts.cdnfonts.com/css/pokemon-solid');
body {
font-family: Arial, sans-serif;
/* Imagem de fundo temática */
background-image: url('pokemon_wallpaper.jpg');
background-size: cover;
background-position: center;
background-attachment: fixed; /* A imagem fica fixa durante o scroll */
/* Centraliza todo o conteúdo na página */
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
}
.container {
background-color: rgba(255, 255, 255, 0.9); /* Fundo branco semi-transparente */
padding: 20px 40px;
border-radius: 10px;
box-shadow: 0 8px 16px rgba(0,0,0,0.3); /* Sombra para destacar */
text-align: center;
width: 400px;
}
/* O título com o estilo da logo do Pokémon! */
h1 {
font-family: 'Pokemon Solid', sans-serif;
color: #FFCB05; /* Amarelo Pokémon */
font-size: 3.5rem;
letter-spacing: 4px;
/* O truque do contorno azul com text-shadow */
-webkit-text-stroke: 2px #3D7DCA; /* Azul Pokémon */
text-shadow: 3px 3px 0 #3D7DCA;
}
.search-box {
display: flex;
justify-content: center;
gap: 10px; /* Espaçamento entre os botões e o input */
margin-bottom: 20px;
}
#pokemonInput {
padding: 12px;
border: 1px solid #ccc;
border-radius: 5px;
width: 200px;
font-size: 1rem;
}
/* Botão de Busca (Vermelho) */
#searchButton {
padding: 12px 20px;
border: none;
background-color: #e74c3c;
color: white;
border-radius: 5px;
cursor: pointer;
font-size: 1rem;
transition: background-color 0.3s ease;
}
#searchButton:hover {
background-color: #c0392b;
}
/* Botão de Limpar (Cinza) */
#resetButton {
padding: 12px 20px;
border: none;
background-color: #7f8c8d;
color: white;
border-radius: 5px;
cursor: pointer;
font-size: 1rem;
transition: background-color 0.3s ease;
}
#resetButton:hover {
background-color: #95a5a6;
}
/* Área onde o Pokémon será exibido */
.pokemon-display-area {
margin-top: 20px;
padding: 15px;
min-height: 250px; /* Altura mínima para o layout não "quebrar" */
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.pokemon-display-area img {
width: 120px;
height: 120px;
}
.error {
color: #c0392b;
font-weight: bold;
}
Atenção: Para o fundo funcionar, você precisará de uma imagem chamada pokemon_wallpaper.jpg
na pasta do projeto.
Passo 3: A Mágica da Interatividade (JavaScript)
Agora vem a parte mais emocionante! O JavaScript vai conectar nosso site à internet para buscar os dados dos Pokémon.
Crie um arquivo chamado script.js
e cole este código:
JavaScript
// Primeiro, pegamos as referências dos elementos HTML com os quais vamos interagir
const pokemonInput = document.getElementById('pokemonInput');
const searchButton = document.getElementById('searchButton');
const resetButton = document.getElementById('resetButton');
const pokemonDisplay = document.getElementById('pokemonDisplay');
// --- Função de Busca ---
const fetchPokemon = () => {
// Pegamos o valor que o usuário digitou (e convertemos para minúsculas)
const pokemonNameOrId = pokemonInput.value.toLowerCase();
// Se o campo estiver vazio, não fazemos nada
if (!pokemonNameOrId) {
alert('Por favor, digite o nome ou ID de um Pokémon.');
return;
}
// Exibe uma mensagem de "Buscando..."
pokemonDisplay.innerHTML = '<p>Buscando...</p>';
// A MÁGICA DO FETCH: fazendo a chamada para a PokéAPI
fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonNameOrId}`)
.then(response => {
// Se a resposta não for bem-sucedida (ex: erro 404), nós lançamos um erro
if (!response.ok) {
throw new Error('Pokémon não encontrado!');
}
// Se deu tudo certo, convertemos a resposta para o formato JSON
return response.json();
})
.then(data => {
// Com os dados em mãos, criamos o HTML para exibir o Pokémon
pokemonDisplay.innerHTML = `
<h2>${data.name.charAt(0).toUpperCase() + data.name.slice(1)}</h2>
<img src="${data.sprites.front_default}" alt="Imagem do ${data.name}">
<p><strong>ID:</strong> ${data.id}</p>
<p><strong>Tipo:</strong> ${data.types[0].type.name}</p>
<p><strong>Altura:</strong> ${data.height / 10} m</p>
<p><strong>Peso:</strong> ${data.weight / 10} kg</p>
`;
})
.catch(error => {
// Se qualquer etapa acima der erro, exibimos a mensagem de erro
pokemonDisplay.innerHTML = `<p class="error">${error.message}</p>`;
});
};
// --- Função de Limpar ---
const resetSearch = () => {
pokemonDisplay.innerHTML = ''; // Limpa a área de exibição
pokemonInput.value = ''; // Limpa o campo de texto
pokemonInput.focus(); // Coloca o cursor de volta no campo de texto
};
// Adicionamos os "ouvintes de evento" para os botões
searchButton.addEventListener('click', fetchPokemon);
resetButton.addEventListener('click', resetSearch);
Como a mágica funciona?
getElementById
: Usamos isso para “capturar” os elementos do HTML e poder manipulá-los com o JS.addEventListener
: Dizemos aos botões para “escutarem” por um clique. Quando o clique acontece, eles executam uma função (fetchPokemon
ouresetSearch
).fetch()
: Essa é a função mais importante aqui. Ela faz uma “requisição” para o endereço da PokéAPI. É como se o nosso código pedisse ao servidor da API: “Ei, me dê os dados do Pokémon ‘pikachu’!”..then()
e.catch()
: Como a internet pode demorar, ofetch
trabalha com “Promessas” (Promises). O.then()
executa somente quando a resposta chega com sucesso. O.catch()
é o nosso plano B, executado se algo der errado (como um Pokémon que não existe).innerHTML
: Depois de obter e organizar os dados, usamos oinnerHTML
para injetar o novo conteúdo HTML diretamente na nossa página.
Passo Final: Juntando Tudo!
Certifique-se de que os três arquivos (index.html
, style.css
, script.js
) e as duas imagens (pokeball-icon.png
e pokemon_wallpaper.jpg
) estejam todos na mesma pasta.
Agora, basta abrir o arquivo index.html
no seu navegador.
Digite “pikachu”, “ditto” ou o seu número da sorte (de 1 a 1025) e veja a mágica acontecer!
Desafios para você ir além
Gostou do resultado? Que tal tentar alguns desafios para aprimorar o projeto e seus conhecimentos?
- Exiba mais informações: A API fornece muito mais dados! Tente mostrar os status base do Pokémon (HP, ataque, defesa).
- Mostre todos os tipos: Alguns Pokémon têm dois tipos. Modifique o código para exibir ambos.
- Botões de Navegação: Adicione botões de “Anterior” e “Próximo” para navegar pela Pokédex usando os IDs.
🔗Projeto no github para pegar as iamgens: https://github.com/guilherme-silvam/Pok-dex–API
Publicar comentário