Desenho e construção de interfaces web
Apresentação
UC02833 (50h · 4,5 pts) ensina a construir o frontend de aplicações web: HTML5 semântico, CSS moderno (Flexbox, Grid, variáveis), design responsivo mobile-first e acessibilidade. É a base para UC02834 (programação web) e UC02835 (apps móveis).
HTML5
Estrutura de documento
<!DOCTYPE html>
<html lang="pt">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Descrição da página">
<title>Título — Aulify</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- conteúdo -->
<script src="app.js"></script>
</body>
</html>
lang="pt"— importante para leitores de ecrã e SEO.<meta charset="UTF-8">— suporta acentos.<meta name="viewport">— essencial para responsivo.
Elementos semânticos
| Elemento | Uso |
|---|---|
<header> |
Cabeçalho da página ou secção |
<nav> |
Navegação principal |
<main> |
Conteúdo principal (1 por página) |
<article> |
Conteúdo independente (post, notícia) |
<section> |
Agrupamento temático |
<aside> |
Conteúdo lateral relacionado |
<footer> |
Rodapé |
<figure>/<figcaption> |
Imagem com legenda |
<time> |
Data/hora |
Usar tag semântica antes de <div>. <div> e <span> são contentores sem significado, último recurso.
<!-- MAU -->
<div class="header">
<div class="title">Aulify</div>
<div class="menu">...</div>
</div>
<!-- BOM -->
<header>
<h1>Aulify</h1>
<nav>...</nav>
</header>
Vantagens da semântica: - Acessibilidade — leitores de ecrã navegam por landmarks. - SEO — motores valorizam estrutura clara. - Manutenção — código auto-explicativo.
Texto e listas
<h1>Título principal</h1> <!-- 1 por página -->
<h2>Subtítulo</h2>
<h3>Sub-subtítulo</h3> <!-- não saltar níveis -->
<p>Parágrafo com <strong>importante</strong> e <em>ênfase</em>.</p>
<ul>
<li>Item não ordenado</li>
</ul>
<ol>
<li>Item ordenado</li>
</ol>
<blockquote cite="https://...">Citação</blockquote>
Hiperligações e imagens
<a href="https://aulify.pt">Link externo</a>
<a href="/recursos">Link interno</a>
<a href="#seccao">Âncora na página</a>
<a href="mailto:geral@aulify.pt">Email</a>
<img src="logo.png" alt="Logótipo Aulify" width="200" height="60">
<picture>
<source srcset="hero.webp" type="image/webp">
<img src="hero.jpg" alt="...">
</picture>
alt obrigatório. Vazio (alt="") para imagens puramente decorativas.
Formulários
<form action="/registar" method="post">
<label for="nome">Nome</label>
<input type="text" id="nome" name="nome" required minlength="2">
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
<label for="pass">Palavra-passe</label>
<input type="password" id="pass" name="pass" minlength="10">
<label for="idade">Idade</label>
<input type="number" id="idade" name="idade" min="13" max="120">
<fieldset>
<legend>Plano</legend>
<label><input type="radio" name="plano" value="free" checked> Grátis</label>
<label><input type="radio" name="plano" value="pro"> Pro</label>
</fieldset>
<label for="bio">Sobre ti</label>
<textarea id="bio" name="bio" rows="4"></textarea>
<label>
<input type="checkbox" name="termos" required> Aceito os termos
</label>
<button type="submit">Registar</button>
</form>
Tipos de input HTML5: email, tel, url, number, date, time, color, range, search. Cada um traz validação e teclado adequado em mobile.
Acessibilidade de formulários:
- Cada input tem <label for="id"> ligado.
- required, min, max, pattern validam no browser (mas validar sempre também no servidor).
- fieldset + legend agrupam radios/checkboxes relacionados.
CSS
Como aplicar
<!-- Externo (recomendado) -->
<link rel="stylesheet" href="style.css">
<!-- Interno -->
<style> p { color: red; } </style>
<!-- Inline (evitar) -->
<p style="color: red;">...</p>
Seletores
/* Tipo */
p { }
/* Classe */
.card { }
/* ID */
#cabecalho { }
/* Descendente */
nav a { }
/* Filho directo */
ul > li { }
/* Múltiplas classes */
.btn.btn-primario { }
/* Atributo */
input[type="email"] { }
/* Pseudo-classes */
a:hover { }
input:focus { }
li:first-child { }
li:nth-child(2n) { } /* pares */
/* Pseudo-elementos */
p::first-line { }
.card::before { content: ""; }
Especificidade
Quando há conflito, vence a regra mais específica:
- Inline style (1000)
- ID (100)
- Classe, atributo, pseudo-classe (10)
- Elemento, pseudo-elemento (1)
Evitar !important — torna debugging um pesadelo. Preferir aumentar especificidade legítima ou reorganizar CSS.
Box model
Todo elemento é uma caixa: content → padding → border → margin.
*, *::before, *::after {
box-sizing: border-box;
}
Com border-box, width inclui padding e border — muito mais previsível.
Cores e unidades
.x {
color: #333; /* hex */
color: rgb(51, 51, 51);
color: rgba(0, 0, 0, .5); /* com transparência */
color: hsl(240, 60%, 50%); /* matiz, saturação, luz */
}
| Unidade | Quando usar |
|---|---|
rem |
Tipografia, espaçamento (relativo à raiz) |
em |
Espaçamento relativo ao elemento |
px |
Bordas, detalhes precisos |
% |
Larguras relativas ao pai |
vw/vh |
Relativo à viewport |
fr |
Fracções no grid |
ch |
Largura de caracteres (texto legível) |
h1 { font-size: clamp(1.5rem, 4vw, 3rem); }
/* mínimo 1.5rem, escala com viewport, máximo 3rem */
Variáveis CSS (custom properties)
:root {
--cor-primaria: #6366f1;
--cor-texto: #1a1a2e;
--espaco-s: 8px;
--espaco-m: 16px;
--espaco-l: 32px;
--raio: 8px;
--fonte: "Inter", system-ui, sans-serif;
}
.botao {
background: var(--cor-primaria);
padding: var(--espaco-m);
border-radius: var(--raio);
font-family: var(--fonte);
}
/* Dark mode trivial */
@media (prefers-color-scheme: dark) {
:root {
--cor-texto: #eee;
--cor-fundo: #1a1a2e;
}
}
Centralizam o design system. Mudar 1 valor propaga a todo o site.
Layout
Flexbox (uma dimensão)
.container {
display: flex;
flex-direction: row; /* ou column */
justify-content: space-between; /* eixo principal */
align-items: center; /* eixo cruzado */
gap: 16px;
flex-wrap: wrap;
}
.item {
flex: 1; /* cresce igualmente */
}
.item-fixo {
flex: 0 0 200px; /* não cresce, 200px */
}
justify-content: flex-start, center, flex-end, space-between, space-around, space-evenly.
Ideal para: navbars, toolbars, alinhar itens numa linha/coluna, centrar conteúdo.
Grid (duas dimensões)
.galeria {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto;
gap: 20px;
}
/* Responsivo sem media queries */
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 16px;
}
/* Layout de página */
.app {
display: grid;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
grid-template-columns: 240px 1fr;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
}
.app > header { grid-area: header; }
.app > nav { grid-area: sidebar; }
.app > main { grid-area: main; }
.app > footer { grid-area: footer; }
Ideal para: galerias, dashboards, layouts de página inteira, qualquer grelha 2D.
Regra prática: Flexbox para componentes (uma direcção); Grid para layout de página (duas direcções).
Posicionamento
.x { position: static; } /* default */
.x { position: relative; } /* relativo a si mesmo; cria contexto */
.x { position: absolute; } /* relativo ao ancestral posicionado */
.x { position: fixed; } /* relativo à viewport */
.x { position: sticky; top: 0; } /* fixa ao rolar */
Design responsivo
Mobile-first
Escrever CSS base para mobile; adicionar regras para ecrãs maiores.
/* Base — mobile */
.container {
padding: 16px;
}
.menu {
display: none; /* hamburger em mobile */
}
/* Tablet */
@media (min-width: 768px) {
.container { padding: 32px; }
.menu { display: flex; }
}
/* Desktop */
@media (min-width: 1024px) {
.container {
max-width: 1100px;
margin: 0 auto;
}
}
Vantagens do mobile-first: força priorização de conteúdo essencial; CSS base mais simples; progressive enhancement.
Breakpoints comuns
| Dispositivo | Largura |
|---|---|
| Mobile | < 768px (base) |
| Tablet | ≥ 768px |
| Desktop | ≥ 1024px |
| Wide | ≥ 1280px |
Não decorar dimensões de modelos específicos — usar breakpoints onde o layout "parte".
Imagens responsivas
<img src="foto.jpg"
srcset="foto-480.jpg 480w, foto-960.jpg 960w"
sizes="(max-width: 600px) 480px, 960px"
alt="...">
img { max-width: 100%; height: auto; }
Acessibilidade (a11y)
WCAG essencial
WCAG 2.1 nível AA é o alvo prático.
- Contraste — texto normal ≥ 4.5:1; texto grande ≥ 3:1.
- Alt text — descritivo em imagens informativas;
alt=""em decorativas. - Teclado — tudo operável só com teclado (Tab, Enter, Espaço, setas).
- Foco visível — nunca remover
outlinesem alternativa clara. - Labels — todo input tem label associado.
- Hierarquia — headings em ordem (
h1→h2→h3), umh1por página. - Linguagem —
<html lang="pt">. - Movimento — respeitar
prefers-reduced-motion.
ARIA
Atributos que dão semântica quando HTML não chega:
<button aria-label="Fechar menu">✕</button>
<div role="alert">Erro: email inválido</div>
<nav aria-label="Navegação principal">...</nav>
<input aria-describedby="ajuda-pass">
<small id="ajuda-pass">Mínimo 10 caracteres</small>
Regra de ouro: "No ARIA is better than bad ARIA." HTML semântico nativo é preferível. <button> já é acessível; <div onclick> não.
Skip link
<a href="#main" class="skip-link">Saltar para o conteúdo</a>
...
<main id="main">...</main>
.skip-link {
position: absolute;
left: -9999px;
}
.skip-link:focus {
left: 16px;
top: 16px;
}
Testar
- Lighthouse (Chrome DevTools) — auditoria automática.
- axe DevTools — extensão de teste a11y.
- Navegação só por teclado — desligar o rato, usar Tab.
- Leitor de ecrã — VoiceOver (Mac), NVDA (Windows).
- Zoom 200% — layout não pode partir.
Workflow e ferramentas
Stack 2026
- Editor: VSCode + extensões (Live Server, Prettier, Emmet).
- DevTools do browser — Elements, Styles, responsive mode, Lighthouse.
- Frameworks CSS (opcionais): Tailwind (utility-first), Bootstrap (componentes).
- Sass — variáveis e nesting; menos necessário com CSS moderno (custom properties, nesting nativo).
- Git — versionamento.
- Deploy estático — Netlify, Vercel, GitHub Pages, Cloudflare Pages (grátis).
Performance
- Imagens em WebP/AVIF, dimensionadas correctamente.
- CSS e JS minificados em produção.
loading="lazy"em imagens abaixo da dobra.- Fontes web com
font-display: swap. - Evitar CSS/JS render-blocking.
Validação
- HTML: validator.w3.org.
- CSS: jigsaw.w3.org/css-validator.
- Lighthouse: performance, a11y, SEO, best practices.
Apêndices
A · Snippet base
<!DOCTYPE html>
<html lang="pt">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Página</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font-family: system-ui, sans-serif; line-height: 1.6; }
.container { max-width: 1100px; margin: 0 auto; padding: 16px; }
</style>
</head>
<body>
<header><h1>Título</h1></header>
<main class="container">...</main>
<footer>...</footer>
</body>
</html>
B · Glossário
A11y. Acessibilidade (a + 11 letras + y).
Box model. Modelo de caixa: content/padding/border/margin.
Flexbox. Layout 1D.
Grid. Layout 2D.
Media query. Regra CSS condicional ao ecrã.
Mobile-first. Desenhar primeiro para mobile.
Semântica. HTML com significado (não só <div>).
WCAG. Web Content Accessibility Guidelines.
C · Recursos
- MDN Web Docs · developer.mozilla.org — a referência.
- CSS-Tricks · css-tricks.com — guias Flexbox/Grid.
- Flexbox Froggy / Grid Garden — jogos para aprender.
- web.dev · Google — performance e a11y.
- A11Y Project · a11yproject.com.