Criar e desenvolver conteúdos, animações e aplicações multimédia para dispositivos móveis (UC02210)
- Introdução
- 1. O contexto móvel: o que distingue do desktop
- 2. Abordagens de desenvolvimento: nativa, híbrida, web app e PWA
- 3. Configurar e parametrizar a ferramenta de desenvolvimento
- 4. Usabilidade e desenho de interface móvel
- 5. A viewport e o desenho adaptativo
- 6. Gestos, estados de toque e interatividade programada
- 7. Animação e movimento com atenção à acessibilidade
- 8. Desempenho e as métricas reais da web
- 9. Otimização de imagens e de tipos de letra
- 10. PWA: manifest, service worker e funcionamento offline
- 11. Acessibilidade em dispositivos móveis
- 12. Testar e depurar a navegação e a compatibilidade
- 13. Exportar e publicar aplicações
- Erros comuns
- Glossário
- Síntese
- Exercícios resolvidos
Há um pacote premium desta unidade: um PowerPoint editável de 100 ou mais diapositivos, um manual em PDF e dois testes com correção. Esta sebenta continua gratuita.
Introdução
Mais de metade do tráfego web mundial já vem de telemóveis. Um site ou uma aplicação que funcione bem num computador de secretária e mal num telemóvel perde a maioria dos seus utilizadores logo nos primeiros segundos. Esta sebenta ensina a criar, desenvolver e testar conteúdos, animações e aplicações multimédia pensados de raiz para dispositivos móveis, e não a "encolher" um site de desktop.
O percurso segue o trabalho real de quem desenvolve para móvel: primeiro entender o que distingue o contexto móvel do desktop; depois escolher a abordagem de desenvolvimento certa para cada projeto (nativa, híbrida, web app ou PWA); configurar a ferramenta de desenvolvimento; desenhar uma interface usável para dedos, não para ratos; construir um layout adaptativo; programar gestos e interatividade; animar com atenção ao desempenho e à acessibilidade; medir e otimizar com as métricas reais da web; transformar o projeto numa PWA que funciona offline; garantir acessibilidade; testar em dispositivo real; e por fim exportar e publicar.
Objetivos de aprendizagem (referencial): configurar e parametrizar a ferramenta de desenvolvimento de plataformas móveis; desenvolver conteúdos, animações e aplicações multimédia para dispositivos móveis; programar as aplicações multimédia e a interatividade; testar a navegação e a compatibilidade; e exportar e publicar aplicações.
1. O contexto móvel: o que distingue do desktop
Desenhar para móvel não é redimensionar um site de computador. O contexto de uso é radicalmente diferente e cada diferença tem consequências diretas no desenho e na programação.
| Dimensão | Desktop | Móvel |
|---|---|---|
| Entrada | rato e teclado, apontar com precisão | dedo, área de contacto imprecisa |
| Ecrã | grande, muitas vezes fixo | pequeno, retrato ou paisagem, várias densidades |
| Rede | cabo ou wi-fi estável | 3G, 4G, 5G, wi-fi instável, variável |
| Energia | ligado à corrente | bateria limitada |
| Contexto | sentado, atenção dedicada | em movimento, uma mão, distraído |
| Sensores | raros | GPS, acelerómetro, câmara, microfone |
| Interrupções | poucas | chamadas, notificações, outras apps |
Consequências práticas: os alvos de toque têm de ser maiores do que o cursor de um rato; o texto tem de ser legível sem dar zoom; as imagens e o código têm de pesar pouco, porque a rede é variável e cara; as animações têm de correr suavemente numa bateria limitada; e a interface tem de assumir que o utilizador usa uma mão só, muitas vezes em movimento.
Este é o fio condutor de toda a unidade: cada decisão de desenho e de código responde a uma destas diferenças.
2. Abordagens de desenvolvimento: nativa, híbrida, web app e PWA
Antes de desenhar seja o que for, decide-se como a aplicação vai chegar ao utilizador. Há quatro caminhos, com compromissos diferentes.
- Aplicação nativa. Escrita na linguagem própria de cada plataforma (Swift/SwiftUI no iOS, Kotlin no Android). Acesso total ao hardware e às APIs do sistema, desempenho máximo, mas exige uma equipa e um código por plataforma, e passa sempre pela revisão da loja.
- Aplicação híbrida. Um único código-fonte gera aplicações para várias plataformas (React Native, Flutter, Ionic com Capacitor). Aproxima-se do desempenho nativo e acede à maioria do hardware através de plugins, com um esforço de desenvolvimento muito menor do que duas apps nativas.
- Web app. Um site com comportamento de aplicação, construído em HTML, CSS e JavaScript, que corre dentro de um browser. Não precisa de instalação nem de passar por loja nenhuma, mas o acesso ao hardware do dispositivo é limitado.
- PWA (Progressive Web App). Uma web app reforçada: instala-se no ecrã principal, funciona offline e pode enviar notificações, mantendo a base em HTML, CSS e JavaScript. É o melhor dos dois mundos para muitos casos de uso.
Quando escolher cada uma
| Situação | Abordagem recomendada |
|---|---|
| Jogo com gráficos 3D exigentes | Nativa |
| App que usa muito a câmara, sensores ou pagamentos complexos | Nativa ou híbrida |
| Equipa pequena, orçamento limitado, várias plataformas | Híbrida ou PWA |
| Conteúdo informativo, catálogo, blog, formulário | Web app ou PWA |
| Precisa de funcionar offline e ter ícone no ecrã, sem loja | PWA |
Exemplo resolvido · escolher a abordagem para um caso real
Uma escola de música quer uma aplicação para os alunos consultarem o horário das aulas, marcarem salas de ensaio e receberem um aviso quando uma aula for cancelada, mesmo com pouca rede no bairro. Não precisa de câmara nem de sensores avançados, e o orçamento é limitado.
Resolução: a escolha certa é uma PWA. Não justifica o custo de duas apps nativas; precisa de funcionar com rede fraca (o service worker resolve isso); precisa de avisos (as notificações push de uma PWA chegam); e o aluno pode instalá-la a partir do browser, sem passar pela loja.
3. Configurar e parametrizar a ferramenta de desenvolvimento
Antes de escrever a primeira linha, configura-se o ambiente de trabalho de plataformas móveis.
- Editor/IDE: o Visual Studio Code (gratuito) serve para web app e PWA; para híbrida ou nativa, o Android Studio (Android, gratuito) e o Xcode (iOS, gratuito, só em macOS).
- Emuladores e simuladores: o Android Studio traz o AVD Manager (Android Virtual Device) para emular vários telemóveis e versões de Android; o Xcode traz o Simulator para iOS.
- Modo de dispositivo no browser: as DevTools de Chrome e Firefox simulam ecrãs, densidades e até a velocidade da rede, sem instalar nada.
- A meta tag da viewport: todo o projeto de web ou PWA começa com esta linha no
<head>, que diz ao browser móvel para não fingir ser um ecrã de desktop:
<meta name="viewport" content="width=device-width, initial-scale=1">
- Permissões do projeto: em Android declaram-se no
AndroidManifest.xml(e as perigosas são pedidas ao utilizador em execução); em iOS oInfo.plistleva o texto que justifica o acesso (por exemploNSCameraUsageDescription). Numa PWA não há permissões nomanifest.json: a câmara, a localização e as notificações pedem-se em execução, através das APIs do browser (Notification.requestPermission(),navigator.geolocation), depois de um gesto do utilizador e só em HTTPS.
Exemplo resolvido · ativar o modo de dispositivo no Chrome DevTools
- Abrir a página no Chrome, premir
F12(ouCmd+Option+Ino Mac). - Clicar no ícone de telemóvel/tablet no canto superior esquerdo do painel (Toggle device toolbar).
- Escolher um dispositivo da lista (ex.: iPhone 14, Pixel 7) ou definir uma resolução personalizada.
- No menu de rede, escolher "Slow 3G" para simular a rede móvel real.
- Recarregar a página e observar o que muda: layout, tamanho de texto, tempo de carregamento.
Sem a meta viewport, este passo mostraria a página encolhida a fingir ser um ecrã de 980px, o erro mais comum de quem começa em desenvolvimento móvel.
4. Usabilidade e desenho de interface móvel
A usabilidade assenta em quatro princípios: feedback ao utilizador (a interface responde de imediato a cada toque), eficiência (poucos passos até ao objetivo), consistência (os mesmos gestos fazem sempre a mesma coisa) e facilidade de aprendizagem (usa-se sem manual).
A zona do polegar
A maioria dos utilizadores segura o telemóvel com uma mão e navega com o polegar. O ecrã divide-se em zonas de alcance:
- Zona fácil (verde): terço inferior do ecrã, onde o polegar chega sem esforço.
- Zona média (amarela): centro do ecrã.
- Zona difícil (vermelha): topo, sobretudo os cantos opostos ao polegar.
Regra prática: ações frequentes e importantes vão na zona fácil (navegação principal, botão de ação primária); informação de leitura e ações raras podem ir mais acima.
Área mínima de toque
Um dedo não é um cursor de rato. A área mínima recomendada para qualquer elemento tocável é 44×44 pontos no iOS e 48×48dp no Android, com espaço à volta para não tocar no botão errado. Um botão de 20px de altura pode parecer bem desenhado num ecrã de computador e ser impossível de tocar num telemóvel.
Hierarquia visual e navegação
- Hierarquia visual: o elemento mais importante do ecrã destaca-se por tamanho, cor ou posição; o olhar deve saber para onde ir primeiro sem pensar.
- Padrões de navegação móvel: barra de navegação inferior (bottom navigation) para as 3 a 5 secções principais; menu de hambúrguer para opções secundárias; separadores (tabs) para alternar entre vistas relacionadas.
- Ícones e elementos visuais compreensíveis: usar símbolos que o utilizador já reconhece de outras apps (lupa para pesquisa, engrenagem para definições); acompanhar de texto quando o ícone for ambíguo.
Exemplo resolvido · corrigir um botão fora da área mínima
Um botão de "Confirmar" tem width: 60px; height: 24px; e está a meio de uma lista de campos de formulário, colado a um botão de "Cancelar" igual, sem espaço entre eles.
Resolução: aumentar para min-height: 48px; min-width: 96px;, adicionar padding: 12px 24px; para a área de toque crescer sem depender só do texto, e afastar os dois botões com gap: 16px;. Colocar "Confirmar" na zona fácil (fundo do ecrã) e "Cancelar" ao lado, mas menos destacado, para reduzir toques acidentais.
5. A viewport e o desenho adaptativo
O design responsivo adapta o mesmo conteúdo a diferentes tamanhos de ecrã, do telemóvel ao ecrã de alta resolução, sem duplicar código.
Media queries
As media queries aplicam regras CSS só a partir de certas condições, tipicamente a largura do ecrã:
/* base: estilos para o telemóvel */
.cartao { flex-direction: column; }
/* a partir de 768px (tablet) */
@media (min-width: 768px) {
.cartao { flex-direction: row; }
}
/* a partir de 1024px (desktop) */
@media (min-width: 1024px) {
.cartao { max-width: 960px; margin: 0 auto; }
}
A boa prática é mobile-first: escrever primeiro o estilo do ecrã pequeno e ir acrescentando regras para ecrãs maiores com min-width, em vez do inverso.
Unidades relativas
Usar unidades relativas em vez de pixels fixos permite que o layout se adapte ao tamanho de letra e ao ecrã do utilizador:
| Unidade | Relativa a | Uso típico |
|---|---|---|
rem |
tamanho de letra da raiz (html) |
espaçamentos, tamanhos de fonte |
em |
tamanho de letra do elemento pai | espaçamentos dentro de um componente |
% |
dimensão do elemento pai | larguras de contentores |
vw / vh |
largura/altura da janela | elementos a ecrã inteiro |
Imagens adaptativas
O srcset e o sizes deixam o browser escolher a imagem certa para o ecrã e a densidade do utilizador, sem transferir mais dados do que precisa:
<img src="hero-800.jpg"
srcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1200.jpg 1200w"
sizes="(max-width: 600px) 100vw, 50vw"
alt="Capa do evento de música ao vivo">
O elemento <picture> vai mais longe: permite servir formatos diferentes (WebP para quem suporta, JPEG como alternativa) consoante o dispositivo.
Exemplo resolvido · breakpoint com imagem adaptativa
Uma página de catálogo mostra uma imagem grande de topo (hero) e uma grelha de produtos. No telemóvel, a grelha deve ter 1 coluna; no tablet, 2; no desktop, 4.
.grelha { display: grid; grid-template-columns: 1fr; gap: 1rem; }
@media (min-width: 600px) {
.grelha { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
.grelha { grid-template-columns: repeat(4, 1fr); }
}
A imagem de topo usa srcset com três larguras, para o telemóvel nunca transferir a versão de 1200px pensada para o desktop.
6. Gestos, estados de toque e interatividade programada
Esta é a realização central de programar a aplicação, não apenas desenhá-la: transformar um layout estático numa interface que responde ao toque.
Gestos comuns
- Tap: um toque, equivalente ao clique.
- Double tap: dois toques rápidos, usado para dar zoom ou "gostar".
- Long press (premir longo): ativa um menu de contexto ou uma seleção.
- Swipe (deslizar): navega entre ecrãs, fecha notificações, revela ações.
- Pinch (beliscar): aproxima ou afasta com dois dedos, para zoom.
- Drag (arrastar): move um elemento, reordena uma lista.
Estados de toque
Cada elemento interativo deve ter estados visuais claros, porque não há cursor a passar por cima a avisar que algo é clicável:
- Default: o estado em repouso.
- Active/pressed: o instante em que o dedo toca, com feedback imediato (mudança de cor, leve escala).
- Focus: quando navegado por teclado externo ou leitor de ecrã, precisa de um contorno visível.
- Disabled: visualmente distinto, sem resposta ao toque.
.botao { transition: transform 0.1s, background-color 0.1s; }
.botao:active { transform: scale(0.97); background-color: var(--cor-primaria-escura); }
.botao:focus-visible { outline: 3px solid var(--cor-foco); outline-offset: 2px; }
.botao:disabled { opacity: 0.5; pointer-events: none; }
Programar a interatividade com JavaScript
Os eventos de toque (touchstart, touchmove, touchend) e, de forma mais moderna e unificada, os Pointer Events (pointerdown, pointermove, pointerup), permitem programar gestos personalizados que não existem em CSS puro.
Exemplo resolvido · carrossel de imagens com swipe
Programar um carrossel simples que avança de imagem com um gesto de deslizar horizontal:
const carrossel = document.querySelector('.carrossel');
let inicioX = 0;
carrossel.addEventListener('touchstart', (evento) => {
inicioX = evento.touches[0].clientX;
});
carrossel.addEventListener('touchend', (evento) => {
const fimX = evento.changedTouches[0].clientX;
const distancia = fimX - inicioX;
if (Math.abs(distancia) > 50) { // limiar mínimo para contar como swipe
if (distancia < 0) {
avancarImagem();
} else {
recuarImagem();
}
}
});
O limiar de 50 pixels evita que um pequeno tremor do dedo dispare o gesto por engano. É esta lógica, entre o desenho da interface e o código que a torna viva, que separa uma aplicação multimédia interativa de um simples documento a ser lido.
7. Animação e movimento com atenção à acessibilidade
A animação orienta a atenção, dá feedback e torna a interface mais agradável, mas em móvel tem um custo real: bateria e desempenho.
Como animar bem
- Animar apenas
transformeopacitysempre que possível: estas propriedades são aceleradas pela placa gráfica (GPU) e não obrigam o browser a recalcular o layout de toda a página. - Evitar animar
width,height,topouleftdiretamente, porque forçam o browser a recalcular o layout em cada frame (reflow), o que engasga a animação em telemóveis mais fracos. - Para animações controladas por JavaScript, usar
requestAnimationFrame, que sincroniza a atualização com a taxa de refrescamento do ecrã, em vez desetInterval.
.cartao-entrada {
transform: translateY(20px);
opacity: 0;
transition: transform 0.3s ease-out, opacity 0.3s ease-out;
}
.cartao-entrada.visivel {
transform: translateY(0);
opacity: 1;
}
Respeitar quem não quer movimento
Algumas pessoas têm perturbações vestibulares ou de atenção a quem o movimento no ecrã causa tonturas ou desconforto real. O sistema operativo tem uma definição de acessibilidade para "reduzir a moção", que o CSS pode ler:
@media (prefers-reduced-motion: reduce) {
.cartao-entrada {
transition: none;
transform: none;
opacity: 1;
}
}
Com esta media query, quem ativou "reduzir movimento" nas definições do telemóvel recebe a interface pronta, sem a animação de entrada, mas continua a ver e a usar tudo.
Exemplo resolvido · aplicar prefers-reduced-motion a um carrossel automático
Um carrossel de imagens na página inicial muda de imagem automaticamente a cada 4 segundos, com um efeito de deslizamento.
Resolução: envolver o avanço automático numa verificação em JavaScript e desligar a transição em CSS:
const prefereMenosMovimento = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (!prefereMenosMovimento) {
setInterval(avancarCarrossel, 4000);
}
@media (prefers-reduced-motion: reduce) {
.carrossel-slide { transition: none; }
}
O carrossel continua a mostrar as imagens (por clique manual, por exemplo), mas deixa de as trocar sozinho com movimento, respeitando a escolha do utilizador.
8. Desempenho e as métricas reais da web
"Parece rápido" não chega. A Google definiu três métricas objetivas, os Core Web Vitals, que medem a experiência real de quem usa o site, sobretudo em rede móvel.
| Métrica | Mede | Bom | A melhorar | Mau |
|---|---|---|---|---|
| LCP (Largest Contentful Paint) | tempo até o maior elemento visível aparecer | até 2,5s | até 4s | acima de 4s |
| CLS (Cumulative Layout Shift) | quanto o layout "salta" enquanto carrega | até 0,1 | até 0,25 | acima de 0,25 |
| INP (Interaction to Next Paint) | tempo entre um toque e a resposta visual | até 200ms | até 500ms | acima de 500ms |
O que degrada estas métricas em rede móvel
- LCP alto: imagens de topo demasiado grandes, fontes que bloqueiam a leitura, servidor lento, ausência de
preloadno recurso principal. - CLS alto: imagens e anúncios sem dimensões reservadas (o texto "salta" quando a imagem carrega por cima), fontes personalizadas que trocam de tamanho ao carregar, conteúdo inserido dinamicamente acima do que já estava visível.
- INP alto: JavaScript pesado a bloquear a interface principal (main thread), demasiados scripts de terceiros (anúncios, análise de tráfego), animações mal otimizadas (ver capítulo anterior).
Em rede móvel, tudo isto agrava-se: a latência de uma rede 4G é muito maior do que a de um wi-fi de escritório, e cada pedido extra ao servidor custa tempo real.
Exemplo resolvido · diagnosticar e corrigir um LCP alto
O Lighthouse (integrado nas DevTools do Chrome, gratuito) reporta um LCP de 5,8 segundos numa página de destino, com a imagem de fundo do cabeçalho identificada como o elemento LCP.
Resolução:
- Confirmar no separador Network que a imagem pesa 2,4 MB, um ficheiro PNG sem compressão.
- Converter para WebP e comprimir (ver capítulo 9), reduzindo para cerca de 180 KB.
- Adicionar
<link rel="preload" as="image" href="hero.webp">no<head>, para o browser começar a descarregá-la mais cedo. - Repetir a medição no Lighthouse: LCP desce para 2,1 segundos, dentro da faixa "bom".
9. Otimização de imagens e de tipos de letra
As imagens e os tipos de letra são, tipicamente, o maior peso de uma página. Otimizá-los é a forma mais eficaz de melhorar o desempenho em rede móvel.
Imagens
- Formatos modernos: WebP e AVIF pesam muito menos do que JPEG ou PNG para a mesma qualidade visual, com suporte já alargado nos browsers móveis.
- Compressão: ferramentas gratuitas como o Squoosh (da Google, direto no browser) ou o TinyPNG reduzem o peso sem perda visível de qualidade.
- Carregamento preguiçoso (lazy loading): o atributo
loading="lazy"adia o carregamento de imagens fora do ecrã inicial, poupando dados e acelerando o arranque. - Dimensões corretas: nunca servir uma imagem de 3000px de largura para um ecrã de 400px; usar
srcsetcomo visto no capítulo 5.
<img src="produto.webp" loading="lazy" width="400" height="300" alt="Colar artesanal em prata">
Os atributos width e height no HTML reservam o espaço antes de a imagem carregar, o que reduz diretamente o CLS.
Tipos de letra
font-display: swap: mostra o texto com uma fonte alternativa enquanto a personalizada carrega, em vez de deixar o texto invisível.- Subconjunto de carateres (subsetting): incluir só os carateres realmente usados (por exemplo, só latim, sem cirílico) reduz o peso do ficheiro de fonte.
preconnectepreload: avisar o browser cedo de que vai precisar de um domínio de fontes ou de um ficheiro concreto.- Fontes variáveis: um único ficheiro cobre vários pesos (regular, negrito), em vez de um ficheiro por peso.
- Tipos de letra do sistema: quando a marca o permite, usar a fonte nativa do sistema operativo (
-apple-system, Roboto) elimina por completo o download de tipo de letra.
@font-face {
font-family: 'Marca';
src: url('marca-variable.woff2') format('woff2-variations');
font-weight: 400 700;
font-display: swap;
}
10. PWA: manifest, service worker e funcionamento offline
Uma Progressive Web App transforma uma web app numa aplicação instalável e resiliente, sem sair de HTML, CSS e JavaScript.
O ficheiro manifest.json
Descreve a aplicação para o sistema operativo poder instalá-la:
{
"name": "Horário da Escola de Música",
"short_name": "Horário",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#1a1e5d",
"icons": [
{ "src": "icone-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "icone-512.png", "sizes": "512x512", "type": "image/png" }
]
}
display: standaloneremove a barra de endereço do browser, para parecer uma app nativa.start_urldefine o que abre quando o utilizador toca no ícone.- Os ícones em duas resoluções cobrem os diferentes ecrãs e lançadores.
O service worker
É um script que corre em segundo plano, entre a aplicação e a rede, e que sobrevive mesmo com a aba fechada. Tem um ciclo de vida próprio:
- install: regista o service worker e pode pré-guardar os ficheiros essenciais em cache.
- activate: limpa caches antigas de versões anteriores.
- fetch: intercepta cada pedido de rede e decide se responde a partir da cache ou vai buscar à rede.
Estratégias de cache
| Estratégia | Como funciona | Usa-se para |
|---|---|---|
| Cache first | tenta a cache; só vai à rede se faltar | ícones, tipos de letra, ficheiros estáticos |
| Network first | tenta a rede; usa a cache se falhar | conteúdo que muda (horário, preços) |
| Stale-while-revalidate | responde da cache já, atualiza em segundo plano | listas que podem ficar um pouco desatualizadas |
Exemplo resolvido · service worker básico com cache first
const CACHE = 'horario-v1';
const FICHEIROS = ['/', '/estilo.css', '/app.js', '/icone-192.png'];
self.addEventListener('install', (evento) => {
evento.waitUntil(
caches.open(CACHE).then((cache) => cache.addAll(FICHEIROS))
);
});
self.addEventListener('fetch', (evento) => {
evento.respondWith(
caches.match(evento.request).then((resposta) => resposta || fetch(evento.request))
);
});
Com isto instalado, a aplicação abre mesmo sem rede: o ecrã principal, o estilo e o script vêm da cache. Para não escrever este código à mão em projetos maiores, a biblioteca gratuita Workbox (da Google) gera estas estratégias automaticamente.
11. Acessibilidade em dispositivos móveis
Uma aplicação acessível serve mais pessoas, incluindo quem tem baixa visão, daltonismo, dificuldades motoras ou usa um leitor de ecrã. Em móvel, o ecrã pequeno torna estes cuidados ainda mais decisivos.
- Contraste: a norma WCAG exige um rácio mínimo de 4,5:1 entre o texto e o fundo (3:1 para texto grande). Ferramentas gratuitas como o WebAIM Contrast Checker ou o painel de acessibilidade das DevTools verificam este valor em segundos.
- Tamanho de texto: nunca fixar um tamanho de letra tão pequeno que obrigue a dar zoom; e nunca desativar o zoom do utilizador com
user-scalable=nona viewport, uma prática que prejudica quem precisa de ampliar o texto. - Leitores de ecrã: o VoiceOver (iOS) e o TalkBack (Android) leem a interface em voz alta. Para funcionarem bem, as imagens precisam de
altdescritivo, os botões precisam de texto ou dearia-label, e a ordem do HTML deve seguir a ordem lógica de leitura. - Foco visível: quem navega com teclado externo, controlo de comutador (switch control) ou apontador adaptado precisa de ver claramente qual o elemento em foco, com
:focus-visible(ver capítulo 6), nunca removido comoutline: nonesem substituto.
Exemplo resolvido · corrigir um contraste insuficiente
Um botão de "Ver mais" está escrito a cinzento claro (#aaaaaa) sobre fundo branco, um rácio de cerca de 2,3:1, abaixo do mínimo.
Resolução: escurecer o texto para #5a5a5a (rácio acima de 4,5:1 sobre branco), confirmado no verificador de contraste, mantendo a mesma paleta visual da marca mas com legibilidade garantida para quem tem baixa visão.
12. Testar e depurar a navegação e a compatibilidade
Nenhuma aplicação está pronta sem ser testada fora do computador de quem a construiu.
Testar em dispositivo real
Os emuladores e simuladores são úteis, mas não substituem um telemóvel real: só ele mostra a velocidade de rede verdadeira, o comportamento do ecrã tátil, o consumo de bateria e as particularidades de cada fabricante.
Depuração remota (remote debugging)
- Android + Chrome: ligar o telemóvel por USB, ativar as "Opções de programador", e abrir
chrome://inspectno computador. Aparece a lista de páginas abertas no telemóvel, com acesso completo às DevTools. - iOS + Safari: ligar o iPhone por USB, ativar o "Web Inspector" nas definições de Safari do telemóvel, e abrir o menu Programar no Safari do Mac.
Com a depuração remota, corrigem-se erros de JavaScript, inspeciona-se o CSS real aplicado e mede-se o desempenho tal como o utilizador o vive, não como o computador de desenvolvimento o simula.
Ferramentas de teste gratuitas
- Lighthouse: audita desempenho, acessibilidade, boas práticas e SEO, direto nas DevTools ou em
PageSpeed Insights. A instalabilidade de uma PWA verifica-se em Application > Manifest. - WebPageTest: mede o carregamento a partir de localizações e redes reais, incluindo perfis de rede móvel.
- Firebase Test Lab / BrowserStack (níveis gratuitos): correm a aplicação em várias combinações reais de dispositivo e sistema operativo sem ser preciso possuir cada um.
Checklist de compatibilidade
- A aplicação funciona em Android e em iOS, nas duas orientações (retrato e paisagem).
- Os gestos e os alvos de toque respondem corretamente em ecrãs pequenos e grandes.
- A rede lenta (throttling "Slow 3G") não deixa a aplicação inutilizável.
- Testado com pelo menos um leitor de ecrã (VoiceOver ou TalkBack).
13. Exportar e publicar aplicações
A última etapa transforma o projeto testado num produto que chega ao utilizador final.
Publicar uma PWA
- Alojar em HTTPS obrigatoriamente: o service worker não regista em ligações inseguras.
- Verificar a instalabilidade no separador Application das DevTools do Chrome (secções Manifest e Service workers), que mostra se o manifest e o service worker cumprem os critérios de instalação. O Lighthouse (desempenho, acessibilidade, boas práticas e SEO) continua a servir para medir o LCP e o CLS, mas já não tem categoria de PWA.
- Testar o ícone de "Adicionar ao ecrã principal" em Android e em iOS.
- Opcionalmente, submeter a listagens como a PWA Builder (Microsoft, gratuita), que ajuda a empacotar a PWA também para as lojas de aplicações.
Publicar uma aplicação híbrida ou nativa
- Gerar o pacote de instalação: AAB (Android App Bundle) para a Play Store, IPA para a App Store.
- Assinar digitalmente o pacote com um certificado próprio do programador.
- Submeter na Play Console (Android) ou na App Store Connect (iOS), com capturas de ecrã, descrição e política de privacidade.
- Aguardar a revisão da loja: o Android é geralmente automático e rápido; a Apple faz revisão manual e pode pedir correções.
Checklist final antes de publicar
- Ícones e imagens de loja nos tamanhos exigidos por cada plataforma.
- Versão testada em pelo menos dois dispositivos reais diferentes.
- Política de privacidade publicada, sobretudo se a app recolher dados pessoais.
- Número de versão atualizado, para permitir atualizações futuras.
Erros comuns
- Desenhar primeiro para desktop e "encolher" depois. Perde-se a lógica de polegar e a hierarquia própria do móvel.
- Esquecer a meta viewport. O browser móvel assume um ecrã de 980px e mostra tudo minúsculo.
- Botões e alvos de toque demasiado pequenos ou colados. Provoca toques errados e frustração.
- Animar
width,height,topouleftem vez detransform. Engasga a animação em telemóveis mais fracos. - Ignorar o
prefers-reduced-motion. Prejudica utilizadores com sensibilidade ao movimento. - Servir imagens gigantes sem
srcsetnem compressão. Dispara o LCP e consome dados do utilizador. - Desativar o zoom do utilizador (
user-scalable=no). Impede quem precisa de ampliar o texto. - Testar só no emulador, nunca em dispositivo real. Esconde problemas reais de rede, bateria e toque.
- Publicar uma PWA sem HTTPS. O service worker simplesmente não regista.
Glossário
- PWA: Progressive Web App, aplicação web instalável que funciona offline.
- Viewport: a área visível do ecrã onde a página é desenhada; controlada pela meta tag
viewport. - Media query: regra CSS que aplica estilos conforme condições do ecrã, como a largura.
- Zona do polegar: a área do ecrã que a mão alcança com facilidade quando segura o telemóvel.
- Service worker: script em segundo plano que intercepta pedidos de rede e permite trabalho offline.
- Manifest: ficheiro JSON que descreve a PWA ao sistema operativo (nome, ícones, cor, ecrã inicial).
- LCP: Largest Contentful Paint, tempo até o maior elemento visível aparecer.
- CLS: Cumulative Layout Shift, medida de quanto o layout se desloca durante o carregamento.
- INP: Interaction to Next Paint, tempo entre um toque e a resposta visual seguinte.
- Lazy loading: carregamento preguiçoso, adiado até o elemento se aproximar do ecrã visível.
- srcset: atributo HTML que oferece várias versões de uma imagem para o browser escolher.
- Prefers-reduced-motion: definição do sistema que pede menos animação, lida por media query.
- Remote debugging: depuração de uma aplicação num dispositivo real a partir do computador.
- AAB / IPA: formatos de pacote de instalação para a Play Store (Android) e a App Store (iOS).
Síntese
Desenvolver para móvel começa por entender o contexto (toque, ecrã pequeno, rede variável, bateria limitada) e escolher a abordagem certa (nativa, híbrida, web app ou PWA). Sobre essa base, desenha-se uma interface usável para o polegar, com um layout adaptativo feito de media queries, unidades relativas e imagens adaptativas. Programa-se a interatividade com gestos e eventos de toque, e anima-se com transform e opacity, sempre a respeitar prefers-reduced-motion. Mede-se o resultado com as métricas reais da web, LCP, CLS e INP, e otimizam-se imagens e tipos de letra para pesarem pouco em rede móvel. Uma PWA acrescenta manifest, service worker e funcionamento offline. Garante-se acessibilidade de contraste, texto, leitores de ecrã e foco visível, testa-se em dispositivo real com depuração remota, e só então se exporta e publica a aplicação.
Exercícios resolvidos
1. Um cliente pede uma aplicação de meditação guiada com áudio, que precisa de funcionar offline e não tem orçamento para duas equipas de desenvolvimento nativo. Que abordagem recomendas e porquê?
Resolução: uma PWA. Cobre o requisito de funcionar offline através do service worker, não exige duas equipas nativas, permite instalação no ecrã principal, e é suficiente para reproduzir áudio e mostrar conteúdo, sem precisar do acesso profundo ao hardware que só o nativo oferece.
2. Uma página tem um LCP de 6,2 segundos. A imagem principal pesa 3 MB em PNG e não tem srcset. Descreve as correções, por ordem de impacto.
Resolução: primeiro, converter a imagem para WebP e comprimir com o Squoosh, o que costuma reduzir o peso em 80% ou mais; segundo, adicionar
srcsetcom várias larguras, para o telemóvel não transferir a versão de desktop; terceiro, adicionar<link rel="preload">para o browser começar a descarregar a imagem mais cedo. Estas três correções, isoladas ou juntas, costumam trazer o LCP para dentro da faixa "bom" (até 2,5s).
3. Um botão de like anima com left e top em JavaScript com setInterval, e engasga em telemóveis Android mais antigos. Corrige o código, em traços gerais.
Resolução: substituir a animação de
left/topportransform: translate(...), que é acelerada pela GPU e não obriga a recalcular o layout; substituirsetIntervalporrequestAnimationFrame, que sincroniza com o ecrã; e envolver a animação numa verificação deprefers-reduced-motion, para respeitar quem desativou o movimento.
4. Explica a diferença entre a estratégia de cache "cache first" e "network first" num service worker, e dá um exemplo de quando usar cada uma nesta UC.
Resolução: cache first responde sempre a partir da cache, só indo à rede se o ficheiro não existir lá; serve para ficheiros estáticos que quase nunca mudam, como ícones e tipos de letra. Network first tenta sempre a rede primeiro, e só usa a cache se a rede falhar; serve para conteúdo que muda, como o horário das aulas do exemplo do capítulo 2, onde mostrar dados desatualizados sem tentar atualizar primeiro seria um erro.
5. Uma aplicação tem texto cinzento claro sobre fundo branco e desativou o zoom do utilizador. Identifica os dois problemas de acessibilidade e corrige-os.
Resolução: primeiro problema, contraste insuficiente: o texto deve cumprir o rácio mínimo de 4,5:1, verificável com o WebAIM Contrast Checker, e corrige-se escurecendo a cor do texto. Segundo problema, zoom desativado com
user-scalable=no: deve remover-se essa restrição da meta viewport, porque impede utilizadores com baixa visão de ampliar o conteúdo, uma barreira de acessibilidade grave.