Módulo 2 · Ciclo Comum · IN02 · Aula 10 de 11

Front-End III — CSS e JavaScript avançado

Levando o front a nível profissional sem framework — variables, layouts, módulos e storage
🎨 CSS Variables
📐 Grid & Flex
📱 Responsivo
🎬 Transitions
🧬 ESM
🧱 BEM
💾 Storage

⏱️ Daily — 15 Minutos

Recap da Aula 9 · testes por camada, Husky e CI
15:00
✅ O que fiz desde a aula 9 🎯 O que vou estilizar hoje 🚧 Algum impedimento de UI? 📦 Estado do projeto

📋 Agenda da Aula 10

Estrutura e objetivos da aula de hoje

🕐 Bloco 1 — Autoestudo (revisão e dúvidas)

Recap do material — variáveis CSS, Flexbox/Grid, mobile-first, ESM, classes e closures.

🕑 Bloco 2 — Instrução (Professor)

Aplicar design system com tokens CSS, padrões responsivos e organização modular do JS no front.

🕒 Bloco 3 — Almoço

Pausa para refeição.

🎯 Bloco 4 — Desenvolvimento (Projeto)

Polir o front com tema consistente, layout responsivo e código JS modular.

🗺️ Roadmap do Módulo 2

Onde estamos agora — Aula 10 de 11
1
Introdução aos Sistemas Web
Visão geral da stack web
2
Banco de Dados I
Modelagem ER e SQL básico
3
Banco de Dados II
CRUD: INSERT, SELECT, UPDATE, DELETE
4
Banco de Dados III
JOINs e consultas avançadas
5
Back-End I — Express + TypeScript
Servidor HTTP, rotas, MVC
6
Back-End II — Camada de dados
Repositories, services, pg
7
Front-End I — EJS e DOM
SSR, templates, manipulação
8
Front-End II — fetch e redes
Async, promises, JSON, CORS
9
Testes e Automação
Jest, supertest, Husky, CI
10
Front-End III — CSS e JS avançado (você está aqui)
Variables, grid, ESM, classes, storage
11
Mergulhando nas Redes
TCP/IP, DNS, CDN e resiliência

🎯 Foco da Aula 10

Sair do "CSS funciona" para o "CSS profissional". Sair do "JS no onclick" para o "JS modular, com classes e storage".

CSS Variables — Tematização viva

Custom properties: o design system em uma única fonte de verdade
public/css/base.css
:root {
--primary: #4b5563;
--surface: #ffffff;
--text: #0f172a;
--radius: 12px;
--space: 1rem;
}
/* Override pelo data-attribute */
[data-theme="dark"] {
--surface: #0f172a;
--text: #e2e8f0;
}
.card {
background: var(--surface);
color: var(--text);
border-radius: var(--radius);
}
data-theme="light"
Surface clara, texto escuro
data-theme="dark"
Surface escura, texto claro

🎯 Por que CSS Variables?

  • Cascata real: herdam pela árvore do DOM e podem ser sobrescritas em qualquer escopo (.card, :root, [data-theme]).
  • Acessíveis pelo JS: el.style.setProperty('--primary', '#22c55e').
  • Tema sem rebuild: alterna em document.documentElement.dataset.theme.
  • Substitui SASS variables para a maioria dos projetos modernos.

Flexbox — Layout em 1 dimensão

Para barras, cards em linha, alinhamento e distribuição de espaço
flex.css
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
}
.card-row { display: flex; gap: 12px; }
.card-row .card { flex: 1; }
/* flex-direction: row | column */
/* flex-wrap: wrap (quebra linha) */
.navbar (preview)
Logo
Home
Sair
.card-row (3 cards iguais com flex:1)
A
B
C

📌 Quando usar Flex

Quando o layout é linear: navbar, lista horizontal, formulários, alinhamento de ícones e textos.

Grid — Layout em 2 dimensões

Linhas e colunas explícitas, áreas nomeadas, responsivo com auto-fit
grid.css
.grid-12 {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 16px;
}
/* Cards responsivos */
.cards {
display: grid;
grid-template-columns: repeat(
auto-fit,
minmax(240px, 1fr)
);
gap: 12px;
}
.cards (auto-fit + minmax — responsivo automático)
card 1
card 2
card 3
card 4
card 5
card 6

📌 Flex × Grid — quando usar

  • Flex: 1 dimensão (linha OU coluna), conteúdo dita o tamanho.
  • Grid: 2 dimensões, layout dita o tamanho. Ideal para dashboards e listagens.
  • auto-fit + minmax(240px, 1fr) = grid que se reorganiza sozinho conforme a largura.

Mobile-first + clamp() + rem

Tipografia e espaçamentos fluidos, sem JavaScript
responsive.css
/* Mobile-first: estilos base = mobile */
.container {
padding: 1rem;
max-width: 100%;
}
/* Tablets pra cima */
@media (min-width: 768px) {
.container { max-width: 720px; }
}
@media (min-width: 1024px) {
.container { max-width: 1100px; }
}
/* Tipografia fluida */
h1 {
font-size: clamp(1.5rem, 4vw, 2.5rem);
}

📐 Unidades — quando usar cada uma

  • rem: tipografia (escala com a preferência do usuário)
  • em: paddings de componentes (escala com a fonte local)
  • %: largura responsiva
  • vw / vh: hero, telas cheias
  • clamp(min, ideal, max): valor fluido com limites

📱 Mobile-first ≠ "fazer mobile depois"

Os estilos base são para mobile. @media (min-width: ...) vai adicionando melhorias em telas maiores. Resultado: CSS mais simples, performance melhor no celular.

Transitions e animação com performance

Anime transform e opacity — não width nem height
animation.css
.btn {
transition: transform .2s ease, box-shadow .2s ease;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 18px rgba(0,0,0,.18);
}
@keyframes fadeUp {
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
* { animation-duration: .01ms !important; }
}

🚫 Lento — repaints/layouts

Animar width, height, top, left, margin dispara layout a cada frame. Em listas grandes, mata a performance.

✅ Rápido — GPU compositing

transform e opacity rodam direto na GPU, sem reflow. Sempre prefira essas duas para qualquer animação.

♿ Acessibilidade

Respeite prefers-reduced-motion — usuários com vestibular sensível precisam disso.

BEM — Block, Element, Modifier

Convenção de classes que escala — sem framework, sem conflitos
card.css
/* Block */
.card {
background: var(--surface);
border-radius: 12px;
padding: 1rem;
}
/* Element */
.card__title {
font-size: 1.1rem;
font-weight: 700;
}
.card__desc { color: var(--muted); }
/* Modifier */
.card--featured {
border-left: 4px solid var(--primary);
background: linear-gradient(135deg, #dbeafe, #ede9fe);
}
BLOCK .card
Componente independente, autossuficiente.
ELEMENT .card__title
Parte do bloco — duplo underline (__).
MODIFIER .card--featured
Variante — duplo hífen (--).

ES Modules no browser

Import/export nativos — fim do JS único de 2000 linhas
public/js/products/list.js
// === views/products/index.ejs ===
<script type="module" src="/js/products/list.js"></script>
// === public/js/products/list.js ===
import { debounce } from '../utils/debounce.js';
import ProductCard from './ProductCard.js';
const cards = document.querySelectorAll('.card');
// === public/js/utils/debounce.js ===
export function debounce(fn, ms = 200) {
let id;
return (...args) => {
clearTimeout(id);
id = setTimeout(() => fn(...args), ms);
};
}
// import dinâmico (lazy load):
const { chart } = await import('./chart.js');

🧬 Vantagens dos ESM

  • Escopo modular: nada vaza para window.
  • Dependências explícitas: dá pra ler o grafo sem rodar.
  • Defer automático: type="module" não bloqueia o parse.
  • Strict mode ligado por padrão.

📁 Organização sugerida

public/js/
├── products/
│ ├── list.js
│ └── ProductCard.js
├── users/
│ └── login.js
└── utils/
└── debounce.js

Destructuring · Spread · Optional Chaining

Sintaxe moderna que elimina 90% do código verboso
modern-syntax.js — desestruturação e spread
// 1) Destructuring de objeto
const user = { id: 1, nome: 'Ana', email: 'ana@inteli.edu' };
const { nome, email } = user; // sem user.nome, user.email
// 2) Destructuring de array + rest
const [primeiro, segundo, ...resto] = [10, 20, 30, 40];
// 3) Spread — clonar e mesclar sem mutar
const copia = { ...user, nome: 'Ana Lima' };
const listaNova = [...lista, novoItem];
// 4) Default parameters
function saudacao(nome = 'visitante') {
return `Olá, ${nome}`;
}
optional-chaining.js
// 5) Optional chaining — sem TypeError
const cidade = user?.endereco?.cidade; // undefined
const total = pedidos?.[0]?.total; // safe
// 6) Nullish ?? vs OR ||
const qtd = pedido.qtd ?? 1; // 0 é válido ✓
const apelido = user.apelido || 'anon'; // '' vira 'anon' ⚠

🎯 Quando usar cada um

  • Destructuring: ao receber resposta de API ou parâmetros de função
  • Spread: ao clonar estado (imutabilidade) ou mesclar configurações
  • Optional chaining ?.: ao acessar dados externos que podem ser null
  • Nullish ??: substitua || quando 0 ou "" são valores legítimos

Classes e Closures

Encapsulamento moderno em JavaScript
ProductCard.js
export default class ProductCard {
// campo privado (#)
#el;
constructor(produto) {
this.produto = produto;
this.#el = this.render();
}
render() {
const div = document.createElement('article');
div.className = 'card';
div.innerHTML = `
<h3 class="card__title">${this.produto.nome}</h3>
<p class="card__price">R$ ${this.produto.preco}</p>`;
return div;
}
mount(parent) { parent.appendChild(this.#el); }
}
closure.js — contador
export function criarContador(inicio = 0) {
let valor = inicio; // preso na closure
return {
inc: () => ++valor,
dec: () => --valor,
get: () => valor,
};
}
const c = criarContador();
c.inc(); c.inc(); // 2 — valor está protegido

🔒 Por que importam?

Classes dão estrutura, closures dão estado privado sem expor variáveis. As duas técnicas substituem o padrão "variável global" que vaza no window.

Storage e FormData — estado no cliente

Quando guardar onde, e como enviar formulários sem stress
RecursoTamanhoTempo de vidaQuando usar
localStorage~5MBPersiste Tema, preferências, rascunhos
sessionStorage~5MBAba aberta Filtros temporários, wizard
cookies~4KBConfigurável Sessão de auth (HttpOnly!)

⚠️ Storage é síncrono

Bloqueia a thread. Para muitos dados, prefira IndexedDB (assíncrono).

form.js — FormData + Storage
// localStorage — persistir tema
localStorage.setItem('tema', 'dark');
const tema = localStorage.getItem('tema') ?? 'light';
// salvar objeto = JSON.stringify
localStorage.setItem('filtros', JSON.stringify({ ordem: 'preco' }));
const filtros = JSON.parse(localStorage.getItem('filtros'));
// FormData — submeter form sem parsing manual
const form = document.querySelector('#novo-produto');
form.addEventListener('submit', async (e) => {
e.preventDefault();
const data = new FormData(form);
const obj = Object.fromEntries(data); // p/ JSON
await fetch('/produtos', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(obj),
});
});

Design System nas 5 Visões RM-ODP

ISO/IEC 10746 · RF, Artefatos e RNF (ISO/IEC 25010) desta aula
🏢 Enterprise
Identidade visual da marca
📋 Information
Tokens, escalas, breakpoints
⚙️ Computational
Componentes JS modulares
🔧 Engineering
Build, ESM, storage
💻 Technology
CSS Grid/Flex, JS ES6+

📌 Requisito Funcional

Aplicar identidade visual e layout responsivo consistentes em todas as páginas do produto — visão Information/Computational materializada como código no front.

📦 Artefato

  • 🎨 Tokens CSS (variáveis de tema)
  • 📐 Layout responsivo com Flex/Grid
  • 🧩 Componentes JS modulares (ESM)

⚖️ RNF — Eixos ISO/IEC 25010

USAB Usabilidade✅ Mobile-first + responsivo
ACES Acessibilidade✅ Contraste, foco, semântica
MANT Manutenibilidade✅ Tokens + BEM
DES Desempenho→ Transitions otimizadas
PORT Portabilidade→ ESM + temas trocáveis

🎯 Atividade — Design System no Projeto

Grupos de até 3 pessoas · Aplique ≥ 4 pontos abaixo no front do projeto
📋 Instrução: Refatore o front-end do projeto usando as técnicas da aula. Documente antes/depois com capturas de tela. Tempo: resto da tarde.
CSS VARIABLES
🎨 Tokens de tema
Crie base.css com ≥ 6 variáveis (--primary, --surface, --text, --radius…). Aplique em todos os componentes via var().
BEM
🧱 Nomenclatura
Renomeie classes do card principal: .card, .card__title, .card__price, .card--featured. Sem classes aninhadas arbitrárias.
GRID LAYOUT
📐 Responsivo
Converta a listagem para repeat(auto-fit, minmax(240px, 1fr)). Teste redimensionando a janela — sem media queries extras.
TRANSITIONS
🎬 Interação
Hover no card: transform: translateY(-3px) + box-shadow. Use apenas transform e opacity — não anime width ou height.
JS CLASSE
🧩 Módulo ESM
Crie uma classe (ProductCard, TaskItem…) com constructor, render() e mount(parent). Exporte via export default.
LOCALSTORAGE
💾 Persistência
Salve ordenação/filtro ativo. Use JSON.stringify para objetos. Restaure no DOMContentLoaded com JSON.parse + ?? para default.
🎨

Front-end profissional!

Você já tem CSS arquitetural com variables e BEM, layouts com Grid e Flex, animações performáticas, JS modular com classes, closures e storage. Na próxima aula, mergulhamos nas redes: TCP/IP, DNS, HTTPS, CDN e cache — a infraestrutura que sustenta tudo em produção.
✅ CSS Variables
✅ Flex & Grid
✅ Mobile-first
✅ Transitions
✅ BEM
✅ ESM
✅ Classes
✅ Storage
Entrega da tarde
Refatorar o front do projeto: BEM + variables + grid + 1 componente JS classe + persistência localStorage
Módulo 2 · Ciclo Comum · Aula 10 de 11 → Aula 11: Mergulhando nas Redes