Manual Completo de HTML5

De iniciante a avançado

Índice

  1. Introdução ao HTML5
  2. Estrutura básica de um documento HTML5
  3. Elementos essenciais
  4. Formatação de texto
  5. Imagens e multimédia
  6. Ligações e navegação
  7. Tabelas
  8. Formulários
  9. Elementos semânticos
  10. APIs do HTML5
  11. Canvas e SVG
  12. Armazenamento local
  13. Geolocalização
  14. Aplicações web offline
  15. Boas práticas e validação
  16. Referência rápida

1. Introdução ao HTML5

HTML5 é a quinta versão da linguagem de marcação de hipertexto (HyperText Markup Language), usada para criar páginas web. É uma evolução significativa em relação ao HTML4, introduzindo novos elementos, atributos e APIs que permitem criar aplicações web mais ricas e interactivas.

Principais novidades do HTML5:

  • Semântica melhorada: novos elementos como <header>, <nav>, <article>, <section>, <footer>
  • Suporte nativo para multimédia: elementos <audio> e <video>
  • Canvas 2D: desenho gráfico via JavaScript
  • Armazenamento local: maior capacidade que os cookies
  • Aplicações offline: funcionalidade sem ligação à internet
  • Geolocalização: API para aceder à localização do utilizador
  • Melhor acessibilidade: estrutura mais clara para leitores de ecrã

2. Estrutura básica de um documento HTML5

HTML
Preview
Copy
<!DOCTYPE html>
<html lang="pt-PT">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="Descrição da página">
    <title>Título da Página</title>
    <link rel="stylesheet" href="estilos.css">
</head>
<body>
    <!-- Conteúdo da página -->
    <h1>Olá, mundo!</h1>
    <p>Esta é a minha primeira página HTML5.</p>
</body>
</html>
 

Explicação dos elementos:

  • <!DOCTYPE html>: declaração do tipo de documento
  • <html lang="pt-PT">: elemento raiz com idioma definido
  • <head>: metadados e informações sobre o documento
  • <meta charset="UTF-8">: define a codificação de caracteres
  • `<meta name=”viewport”>
  • <title>: título que aparece no separador do navegador
  • <body>: conteúdo visível da página

3. Elementos essenciais

Cabeçalhos (Headings)

HTML
Preview
Copy
<h1>Título principal</h1>
<h2>Subtítulo</h2>
<h3>Sub-subtítulo</h3>
<h4>Título nível 4</h4>
<h5>Título nível 5</h5>
<h6>Título nível 6</h6>
 

Parágrafos e quebras de linha

HTML
Preview
Copy
<p>Este é um parágrafo de texto.</p>
<p>Este é outro parágrafo.<br>
Com uma quebra de linha dentro.</p>
 

Listas

HTML
Preview
Copy
<!-- Lista não ordenada -->
<ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
</ul>

<!-- Lista ordenada -->
<ol>
    <li>Primeiro item</li>
    <li>Segundo item</li>
    <li>Terceiro item</li>
</ol>

<!-- Lista de definições -->
<dl>
    <dt>HTML</dt>
    <dd>HyperText Markup Language</dd>
    <dt>CSS</dt>
    <dd>Cascading Style Sheets</dd>
</dl>
 

Divisões e contentores

HTML
Preview
Copy
<div class="container">
    <p>Conteúdo dentro de uma div</p>
</div>

<span class="destaque">Texto destacado</span>
 

4. Formatação de texto

Elementos de formatação inline

HTML
Preview
Copy
<p>Este texto tem <strong>ênfase forte</strong> e <em>ênfase itálica</em>.</p>
<p>Texto <mark>marcado</mark> e <del>removido</del>.</p>
<p>Texto <sub>subscrito</sub> e <sup>sobrescrito</sup>.</p>
<p>Pequeno texto: <small>Copyright 2024</small></p>
 

Citações

HTML
Preview
Copy
<blockquote cite="https://exemplo.com">
    <p>Esta é uma citação em bloco.</p>
</blockquote>

<p>Como disse alguém, <q cite="https://exemplo.com">esta é uma citação inline</q>.</p>
 

Código

HTML
Preview
Copy
<p>O comando <code>console.log()</code> é usado em JavaScript.</p>

<pre>
    <code>
function saudacao() {
    console.log("Olá, mundo!");
}
    </code>
</pre>
 

5. Imagens e multimédia

Imagens

HTML
Preview
Copy
<img src="imagem.jpg" 
     alt="Descrição da imagem" 
     width="300" 
     height="200"
     loading="lazy">
 

Áudio

HTML
Preview
Copy
<audio controls>
    <source src="musica.mp3" type="audio/mpeg">
    <source src="musica.ogg" type="audio/ogg">
    O seu navegador não suporta o elemento áudio.
</audio>
 

Vídeo

HTML
Preview
Copy
<video width="640" height="360" controls poster="miniatura.jpg">
    <source src="video.mp4" type="video/mp4">
    <source src="video.webm" type="video/webm">
    <track src="legendas.vtt" kind="subtitles" srclang="pt" label="Português">
    O seu navegador não suporta o elemento vídeo.
</video>
 

Figure e figcaption

HTML
Preview
Copy
<figure>
    <img src="grafico.png" alt="Gráfico de vendas">
    <figcaption>Figura 1: Evolução das vendas em 2024</figcaption>
</figure>
 

6. Ligações e navegação

Ligações externas

HTML
Preview
Copy
<a href="https://www.exemplo.com" target="_blank" rel="noopener noreferrer">
    Visitar exemplo.com
</a>
 

Ligações internas

HTML
Preview
Copy
<a href="#secao2">Ir para secção 2</a>

<!-- Mais tarde na página -->
<section id="secao2">
    <h2>Secção 2</h2>
    <p>Conteúdo da secção 2...</p>
</section>
 

Ligações de email e telefone

HTML
Preview
Copy
<a href="mailto:contacto@exemplo.com">Enviar email</a>
<a href="tel:+351123456789">Ligar para +351 123 456 789</a>
 

Navegação com nav

HTML
Preview
Copy
<nav>
    <ul>
        <li><a href="/">Início</a></li>
        <li><a href="/sobre">Sobre</a></li>
        <li><a href="/servicos">Serviços</a></li>
        <li><a href="/contacto">Contacto</a></li>
    </ul>
</nav>
 

7. Tabelas

Tabela básica

HTML
Preview
Copy
<table>
    <caption>Vendas mensais</caption>
    <thead>
        <tr>
            <th>Mês</th>
            <th>Vendas</th>
            <th>Lucro</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Janeiro</td>
            <td>1000€</td>
            <td>200€</td>
        </tr>
        <tr>
            <td>Fevereiro</td>
            <td>1200€</td>
            <td>250€</td>
        </tr>
    </tbody>
    <tfoot>
        <tr>
            <td>Total</td>
            <td>2200€</td>
            <td>450€</td>
        </tr>
    </tfoot>
</table>
 

Tabela com agrupamento

HTML
Preview
Copy
<table>
    <colgroup>
        <col span="2" style="background-color: #f0f0f0;">
        <col style="background-color: #e0e0e0;">
    </colgroup>
    <thead>
        <tr>
            <th scope="col">Produto</th>
            <th scope="col">Quantidade</th>
            <th scope="col">Preço</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Computador</td>
            <td>5</td>
            <td>800€</td>
        </tr>
    </tbody>
</table>
 

8. Formulários

Formulário básico

HTML
Preview
Copy
<form action="/processar" method="POST">
    <div>
        <label for="nome">Nome:</label>
        <input type="text" id="nome" name="nome" required>
    </div>
    
    <div>
        <label for="email">Email:</label>
        <input type="email" id="email" name="email" required>
    </div>
    
    <div>
        <label for="mensagem">Mensagem:</label>
        <textarea id="mensagem" name="mensagem" rows="5" cols="30"></textarea>
    </div>
    
    <button type="submit">Enviar</button>
</form>
 

Tipos de input HTML5

HTML
Preview
Copy
<form>
    <!-- Texto -->
    <input type="text" placeholder="Texto simples">
    
    <!-- Email -->
    <input type="email" placeholder="email@exemplo.com">
    
    <!-- Telefone -->
    <input type="tel" placeholder="+351 123 456 789">
    
    <!-- URL -->
    <input type="url" placeholder="https://exemplo.com">
    
    <!-- Número -->
    <input type="number" min="0" max="100" step="5">
    
    <!-- Intervalo -->
    <input type="range" min="0" max="100" value="50">
    
    <!-- Data -->
    <input type="date">
    
    <!-- Hora -->
    <input type="time">
    
    <!-- Data e hora local -->
    <input type="datetime-local">
    
    <!-- Mês -->
    <input type="month">
    
    <!-- Semana -->
    <input type="week">
    
    <!-- Cor -->
    <input type="color">
    
    <!-- Procura -->
    <input type="search" placeholder="Pesquisar...">
    
    <!-- Password -->
    <input type="password" placeholder="Palavra-passe">
    
    <!-- Ficheiro -->
    <input type="file" accept="image/*" multiple>
</form>
 

Elementos de formulário avançados

HTML
Preview
Copy
<form>
    <!-- Lista de opções -->
    <input list="browsers" name="browser">
    <datalist id="browsers">
        <option value="Chrome">
        <option value="Firefox">
        <option value="Safari">
        <option value="Edge">
    </datalist>
    
    <!-- Campo com medidor -->
    <label for="disco">Uso de disco:</label>
    <meter id="disco" value="6" min="0" max="10">6 de 10</meter>
    
    <!-- Progresso -->
    <label for="progresso">Progresso:</label>
    <progress id="progresso" value="70" max="100">70%</progress>
    
    <!-- Grupo de campos -->
    <fieldset>
        <legend>Informações pessoais</legend>
        <label for="nome">Nome:</label>
        <input type="text" id="nome" name="nome">
        
        <label for="idade">Idade:</label>
        <input type="number" id="idade" name="idade">
    </fieldset>
</form>
 

9. Elementos semânticos

Estrutura de uma página semântica

HTML
Preview
Copy
<!DOCTYPE html>
<html lang="pt-PT">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Exemplo Semântico</title>
</head>
<body>
    <header>
        <h1>Logo ou título do site</h1>
        <nav>
            <ul>
                <li><a href="/">Início</a></li>
                <li><a href="/sobre">Sobre</a></li>
                <li><a href="/contacto">Contacto</a></li>
            </ul>
        </nav>
    </header>
    
    <main>
        <article>
            <header>
                <h2>Título do artigo</h2>
                <p>Publicado em <time datetime="2024-01-15">15 de Janeiro de 2024</time></p>
            </header>
            
            <section>
                <h3>Introdução</h3>
                <p>Conteúdo da introdução...</p>
            </section>
            
            <section>
                <h3>Desenvolvimento</h3>
                <p>Conteúdo do desenvolvimento...</p>
            </section>
            
            <aside>
                <h4>Informação relacionada</h4>
                <p>Conteúdo complementar...</p>
            </aside>
        </article>
        
        <section>
            <h2>Outra secção</h2>
            <p>Conteúdo adicional...</p>
        </section>
    </main>
    
    <footer>
        <p>&copy; 2024 Nome do Site. Todos os direitos reservados.</p>
        <address>
            Contacto: <a href="mailto:info@exemplo.com">info@exemplo.com</a>
        </address>
    </footer>
</body>
</html>
 

Elementos semânticos detalhados

HTML
Preview
Copy
<!-- Detalhes expansíveis -->
<details>
    <summary>Clique para expandir</summary>
    <p>Conteúdo oculto que aparece quando clicado.</p>
</details>

<!-- Marcação de texto importante -->
<p>O <strong>HTML5</strong> é importante para a web moderna.</p>

<!-- Marcação de ênfase -->
<p>Este <em>texto</em> está em itálico por ênfase.</p>

<!-- Pequenas impressões -->
<p><small>© 2024 Todos os direitos reservados</small></p>

<!-- Marcação de tempo -->
<p>O evento ocorreu em <time datetime="2024-01-15">15 de Janeiro</time>.</p>
 

10. APIs do HTML5

Armazenamento local (LocalStorage)

HTML
Preview
Copy
<!DOCTYPE html>
<html>
<head>
    <title>LocalStorage Exemplo</title>
</head>
<body>
    <input type="text" id="dados" placeholder="Escreva algo">
    <button onclick="guardar()">Guardar</button>
    <button onclick="recuperar()">Recuperar</button>
    <p id="resultado"></p>

    <script>
        function guardar() {
            const valor = document.getElementById('dados').value;
            localStorage.setItem('meusDados', valor);
            alert('Dados guardados!');
        }
        
        function recuperar() {
            const valor = localStorage.getItem('meusDados');
            document.getElementById('resultado').textContent = valor || 'Nenhum dado encontrado';
        }
    </script>
</body>
</html>
 

Armazenamento de sessão (SessionStorage)

JavaScript
Copy
// Guardar dados na sessão
sessionStorage.setItem('usuario', 'João');

// Recuperar dados
const usuario = sessionStorage.getItem('usuario');

// Remover dados
sessionStorage.removeItem('usuario');

// Limpar tudo
sessionStorage.clear();
 

Geolocalização

HTML
Preview
Copy
<!DOCTYPE html>
<html>
<head>
    <title>Geolocalização</title>
</head>
<body>
    <button onclick="obterLocalizacao()">Obter minha localização</button>
    <p id="demo"></p>

    <script>
        function obterLocalizacao() {
            if (navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(mostrarPosicao, mostrarErro);
            } else {
                document.getElementById("demo").innerHTML = "Geolocalização não é suportada.";
            }
        }
        
        function mostrarPosicao(posicao) {
            document.getElementById("demo").innerHTML = 
                "Latitude: " + posicao.coords.latitude + 
                "<br>Longitude: " + posicao.coords.longitude;
        }
        
        function mostrarErro(erro) {
            switch(erro.code) {
                case erro.PERMISSION_DENIED:
                    document.getElementById("demo").innerHTML = "Utilizador negou a solicitação.";
                    break;
                case erro.POSITION_UNAVAILABLE:
                    document.getElementById("demo").innerHTML = "Informação de localização indisponível.";
                    break;
                case erro.TIMEOUT:
                    document.getElementById("demo").innerHTML = "A solicitação expirou.";
                    break;
                default:
                    document.getElementById("demo").innerHTML = "Ocorreu um erro desconhecido.";
                    break;
            }
        }
    </script>
</body>
</html>
 

Drag and Drop

HTML
Preview
Copy
<!DOCTYPE html>
<html>
<head>
    <title>Drag and Drop</title>
    <style>
        #div1 {
            width: 350px;
            height: 70px;
            padding: 10px;
            border: 1px solid #aaaaaa;
        }
    </style>
</head>
<body>
    <p>Arraste a imagem para a caixa:</p>
    
    <div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
    <br>
    <img id="drag1" src="img_logo.gif" draggable="true" ondragstart="drag(event)" width="336" height="69">

    <script>
        function allowDrop(ev) {
            ev.preventDefault();
        }
        
        function drag(ev) {
            ev.dataTransfer.setData("text", ev.target.id);
        }
        
        function drop(ev) {
            ev.preventDefault();
            var data = ev.dataTransfer.getData("text");
            ev.target.appendChild(document.getElementById(data));
        }
    </script>
</body>
</html>
 

11. Canvas e SVG

Canvas básico

HTML
Preview
Copy
<!DOCTYPE html>
<html>
<head>
    <title>Canvas Exemplo</title>
</head>
<body>
    <canvas id="myCanvas" width="200" height="100" style="border:1px solid #000000;">
        O seu navegador não suporta o elemento canvas.
    </canvas>

    <script>
        const canvas = document.getElementById("myCanvas");
        const ctx = canvas.getContext("2d");
        
        // Desenhar um retângulo
        ctx.fillStyle = "#FF0000";
        ctx.fillRect(10, 10, 150, 80);
        
        // Desenhar uma linha
        ctx.moveTo(0, 0);
        ctx.lineTo(200, 100);
        ctx.stroke();
        
        // Desenhar um círculo
        ctx.beginPath();
        ctx.arc(95, 50, 40, 0, 2 * Math.PI);
        ctx.stroke();
        
        // Texto
        ctx.font = "30px Arial";
        ctx.fillText("Olá", 10, 50);
    </script>
</body>
</html>
 

SVG básico

HTML
Preview
Copy
<!DOCTYPE html>
<html>
<head>
    <title>SVG Exemplo</title>
</head>
<body>
    <svg width="100" height="100">
        <circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
    </svg>
    
    <svg width="400" height="110">
        <rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
    </svg>
    
    <svg height="210" width="500">
        <polygon points="200,10 250,190 160,210" style="fill:lime;stroke:purple;stroke-width:1" />
    </svg>
    
    <svg height="60" width="200">
        <text x="0" y="15" fill="red" transform="rotate(30 20,40)">Olá SVG!</text>
    </svg>
</body>
</html>
 

Animação com Canvas

HTML
Preview
Copy
<!DOCTYPE html>
<html>
<head>
    <title>Animação Canvas</title>
</head>
<body>
    <canvas id="myCanvas" width="300" height="150" style="border:1px solid #000000;"></canvas>

    <script>
        const canvas = document.getElementById("myCanvas");
        const ctx = canvas.getContext("2d");
        
        let x = 0;
        let y = 75;
        let dx = 2;
        
        function desenhar() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.beginPath();
            ctx.arc(x, y, 20, 0, Math.PI * 2);
            ctx.fillStyle = "#0095DD";
            ctx.fill();
            ctx.closePath();
            
            x += dx;
            
            if(x + 20 > canvas.width || x - 20 < 0) {
                dx = -dx;
            }
        }
        
        setInterval(desenhar, 10);
    </script>
</body>
</html>
 

12. Armazenamento local

LocalStorage vs SessionStorage vs Cookies

Table
Copy
CaracterísticaLocalStorageSessionStorageCookies
Capacidade5-10MB5-10MB4KB
PersistênciaPermanenteSessãoDefinida
Envio ao servidorNãoNãoSim
AcessoQualquer janelaMesma janelaQualquer janela

Exemplo completo de LocalStorage

HTML
Preview
Copy
<!DOCTYPE html>
<html>
<head>
    <title>Gestor de Tarefas</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; }
        .tarefa { background: #f4f4f4; padding: 10px; margin: 5px 0; border-radius: 5px; }
        .completada { text-decoration: line-through; opacity: 0.6; }
        button { background: #333; color: white; padding: 5px 10px; border: none; cursor: pointer; }
        button:hover { background: #555; }
    </style>
</head>
<body>
    <h1>Minhas Tarefas</h1>
    
    <input type="text" id="novaTarefa" placeholder="Nova tarefa...">
    <button onclick="adicionarTarefa()">Adicionar</button>
    
    <div id="listaTarefas"></div>

    <script>
        // Carregar tarefas ao iniciar
        window.onload = function() {
            carregarTarefas();
        };
        
        function adicionarTarefa() {
            const input = document.getElementById('novaTarefa');
            const tarefa = input.value.trim();
            
            if (tarefa === '') {
                alert('Por favor, escreva uma tarefa!');
                return;
            }
            
            const tarefas = JSON.parse(localStorage.getItem('tarefas') || '[]');
            tarefas.push({
                id: Date.now(),
                texto: tarefa,
                completada: false
            });
            
            localStorage.setItem('tarefas', JSON.stringify(tarefas));
            input.value = '';
            carregarTarefas();
        }
        
        function carregarTarefas() {
            const tarefas = JSON.parse(localStorage.getItem('tarefas') || '[]');
            const lista = document.getElementById('listaTarefas');
            lista.innerHTML = '';
            
            tarefas.forEach(tarefa => {
                const div = document.createElement('div');
                div.className = 'tarefa' + (tarefa.completada ? ' completada' : '');
                div.innerHTML = `
                    <input type="checkbox" ${tarefa.completada ? 'checked' : ''} 
                           onchange="toggleTarefa(${tarefa.id})">
                    ${tarefa.texto}
                    <button onclick="removerTarefa(${tarefa.id})" style="float: right;">Remover</button>
                `;
                lista.appendChild(div);
            });
        }
        
        function toggleTarefa(id) {
            const tarefas = JSON.parse(localStorage.getItem('tarefas') || '[]');
            const tarefa = tarefas.find(t => t.id === id);
            if (tarefa) {
                tarefa.completada = !tarefa.completada;
                localStorage.setItem('tarefas', JSON.stringify(tarefas));
                carregarTarefas();
            }
        }
        
        function removerTarefa(id) {
            let tarefas = JSON.parse(localStorage.getItem('tarefas') || '[]');
            tarefas = tarefas.filter(t => t.id !== id);
            localStorage.setItem('tarefas', JSON.stringify(tarefas));
            carregarTarefas();
        }
    </script>
</body>
</html>
 

13. Geolocalização

Exemplo avançado de geolocalização

HTML
Preview
Copy
<!DOCTYPE html>
<html>
<head>
    <title>Geolocalização Avançada</title>
    <style>
        #mapa { width: 100%; height: 400px; border: 1px solid #ccc; margin-top: 20px; }
        .info { background: #f0f0f0; padding: 10px; margin: 10px 0; border-radius: 5px; }
    </style>
</head>
<body>
    <h1>Geolocalização</h1>
    
    <button onclick="obterLocalizacao()">Obter Localização</button>
    <button onclick="obterLocalizacaoContinua()">Seguir Localização</button>
    <button onclick="pararLocalizacao()">Parar Seguimento</button>
    
    <div id="info" class="info"></div>
    <div id="mapa"></div>

    <script>
        let watchId = null;
        
        function obterLocalizacao() {
            if (navigator.geolocation) {
                const options = {
                    enableHighAccuracy: true,
                    timeout: 5000,
                    maximumAge: 0
                };
                
                navigator.geolocation.getCurrentPosition(
                    mostrarPosicao, 
                    mostrarErro, 
                    options
                );
            } else {
                document.getElementById("info").innerHTML = "Geolocalização não suportada.";
            }
        }
        
        function obterLocalizacaoContinua() {
            if (navigator.geolocation) {
                const options = {
                    enableHighAccuracy: true,
                    timeout: 5000,
                    maximumAge: 0
                };
                
                watchId = navigator.geolocation.watchPosition(
                    mostrarPosicao, 
                    mostrarErro, 
                    options
                );
            }
        }
        
        function pararLocalizacao() {
            if (watchId !== null) {
                navigator.geolocation.clearWatch(watchId);
                watchId = null;
                document.getElementById("info").innerHTML += "<p>Seguimento parado.</p>";
            }
        }
        
        function mostrarPosicao(posicao) {
            const info = document.getElementById("info");
            const latitude = posicao.coords.latitude;
            const longitude = posicao.coords.longitude;
            const precisao = posicao.coords.accuracy;
            const altitude = posicao.coords.altitude;
            const precisaoAltitude = posicao.coords.altitudeAccuracy;
            const direcao = posicao.coords.heading;
            const velocidade = posicao.coords.speed;
            const timestamp = new Date(posicao.timestamp);
            
            info.innerHTML = `
                <h3>Informações de Localização</h3>
                <p><strong>Latitude:</strong> ${latitude.toFixed(6)}°</p>
                <p><strong>Longitude:</strong> ${longitude.toFixed(6)}°</p>
                <p><strong>Precisão:</strong> ${precisao.toFixed(0)} metros</p>
                <p><strong>Altitude:</strong> ${altitude ? altitude.toFixed(0) + ' metros' : 'Não disponível'}</p>
                <p><strong>Direção:</strong> ${direcao ? direcao.toFixed(0) + '°' : 'Não disponível'}</p>
                <p><strong>Velocidade:</strong> ${velocidade ? velocidade.toFixed(1) + ' m/s' : 'Não disponível'}</p>
                <p><strong>Timestamp:</strong> ${timestamp.toLocaleString('pt-PT')}</p>
            `;
            
            // Mostrar no mapa (simulado)
            mostrarMapa(latitude, longitude);
        }
        
        function mostrarMapa(lat, lng) {
            const mapa = document.getElementById("mapa");
            const mapUrl = `https://maps.googleapis.com/maps/api/staticmap?center=${lat},${lng}&zoom=15&size=600x400&markers=${lat},${lng}&key=YOUR_API_KEY`;
            
            mapa.innerHTML = `
                <h3>Mapa da Localização</h3>
                <p>Latitude: ${lat.toFixed(6)}, Longitude: ${lng.toFixed(6)}</p>
                <p>(Em produção, isto mostraria um mapa real)</p>
                <iframe 
                    width="100%" 
                    height="400" 
                    frameborder="0" 
                    scrolling="no" 
                    marginheight="0" 
                    marginwidth="0" 
                    src="https://www.openstreetmap.org/export/embed.html?bbox=${lng-0.01},${lat-0.01},${lng+0.01},${lat+0.01}&layer=mapnik&marker=${lat},${lng}">
                </iframe>
            `;
        }
        
        function mostrarErro(erro) {
            let mensagem = "";
            switch(erro.code) {
                case erro.PERMISSION_DENIED:
                    mensagem = "Utilizador negou o pedido de Geolocalização.";
                    break;
                case erro.POSITION_UNAVAILABLE:
                    mensagem = "Informação de localização indisponível.";
                    break;
                case erro.TIMEOUT:
                    mensagem = "O pedido para obter a localização expirou.";
                    break;
                case erro.UNKNOWN_ERROR:
                    mensagem = "Ocorreu um erro desconhecido.";
                    break;
            }
            document.getElementById("info").innerHTML = `<p style="color: red;">Erro: ${mensagem}</p>`;
        }
    </script>
</body>
</html>
 

14. Aplicações web offline

Manifesto da aplicação (manifest.json)

JSON
Copy
{
    "name": "Minha App Offline",
    "short_name": "AppOffline",
    "description": "Uma aplicação que funciona offline",
    "start_url": "/index.html",
    "display": "standalone",
    "background_color": "#ffffff",
    "theme_color": "#000000",
    "icons": [
        {
            "src": "icon-192.png",
            "sizes": "192x192",
            "type": "image/png"
        },
        {
            "src": "icon-512.png",
            "sizes": "512x512",
            "type": "image/png"
        }
    ]
}
 

HTML com manifesto

HTML
Preview
Copy
<!DOCTYPE html>
<html lang="pt-PT" manifest="cache.manifest">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>App Offline</title>
    <link rel="manifest" href="manifest.json">
    <style>
        body { 
            font-family: Arial, sans-serif; 
            max-width: 800px; 
            margin: 0 auto; 
            padding: 20px; 
            text-align: center;
        }
        .online { color: green; }
        .offline { color: red; }
        button { 
            padding: 10px 20px; 
            margin: 10px; 
            font-size: 16px; 
            cursor: pointer; 
        }
    </style>
</head>
<body>
    <h1>Aplicação Offline</h1>
    
    <div id="estado"></div>
    
    <div id="conteudo">
        <h2>Conteúdo Principal</h2>
        <p>Esta aplicação funciona mesmo sem ligação à internet!</p>
        
        <button onclick="guardarDados()">Guardar Dados Localmente</button>
        <button onclick="recuperarDados()">Recuperar Dados</button>
        
        <div id="resultado"></div>
    </div>

    <script>
        // Detectar estado da ligação
        function atualizarEstado() {
            const estado = document.getElementById('estado');
            if (navigator.onLine) {
                estado.innerHTML = '<p class="online">✓ Online</p>';
            } else {
                estado.innerHTML = '<p class="offline">✗ Offline</p>';
            }
        }
        
        // Atualizar estado quando a ligação muda
        window.addEventListener('online', atualizarEstado);
        window.addEventListener('offline', atualizarEstado);
        
        // Estado inicial
        atualizarEstado();
        
        // Guardar dados localmente
        function guardarDados() {
            const dados = {
                timestamp: new Date().toISOString(),
                dados: 'Informação importante',
                versao: '1.0'
            };
            
            localStorage.setItem('dadosApp', JSON.stringify(dados));
            document.getElementById('resultado').innerHTML = '<p>Dados guardados com sucesso!</p>';
        }
        
        // Recuperar dados
        function recuperarDados() {
            const dadosGuardados = localStorage.getItem('dadosApp');
            if (dadosGuardados) {
                const dados = JSON.parse(dadosGuardados);
                document.getElementById('resultado').innerHTML = `
                    <h3>Dados Recuperados:</h3>
                    <p><strong>Timestamp:</strong> ${dados.timestamp}</p>
                    <p><strong>Dados:</strong> ${dados.dados}</p>
                    <p><strong>Versão:</strong> ${dados.versao}</p>
                `;
            } else {
                document.getElementById('resultado').innerHTML = '<p>Nenhum dado encontrado.</p>';
            }
        }
        
        // Service Worker para funcionamento offline
        if ('serviceWorker' in navigator) {
            navigator.serviceWorker.register('sw.js')
                .then(() => console.log('Service Worker registado com sucesso'))
                .catch(err => console.log('Erro ao registar Service Worker:', err));
        }
    </script>
</body>
</html>
 

Service Worker (sw.js)

JavaScript
Copy
const CACHE_NAME = 'app-offline-v1';
const urlsToCache = [
    '/',
    '/index.html',
    '/estilos.css',
    '/script.js',
    '/manifest.json'
];

// Instalar Service Worker
self.addEventListener('install', event => {
    event.waitUntil(
        caches.open(CACHE_NAME)
            .then(cache => {
                console.log('Cache aberto');
                return cache.addAll(urlsToCache);
            })
    );
});

// Interceptar pedidos
self.addEventListener('fetch', event => {
    event.respondWith(
        caches.match(event.request)
            .then(response => {
                // Devolver do cache ou fazer pedido à rede
                return response || fetch(event.request);
            })
    );
});

// Actualizar Service Worker
self.addEventListener('activate', event => {
    const cacheWhitelist = [CACHE_NAME];
    event.waitUntil(
        caches.keys().then(cacheNames => {
            return Promise.all(
                cacheNames.map(cacheName => {
                    if (cacheWhitelist.indexOf(cacheName) === -1) {
                        return caches.delete(cacheName);
                    }
                })
            );
        })
    );
});
 

Cache Manifest (cache.manifest)

Copy
CACHE MANIFEST
# v1.0 - 2024-01-15

CACHE:
index.html
estilos.css
script.js
imagens/logo.png
imagens/fundo.jpg

NETWORK:
*

FALLBACK:
/ offline.html
 

15. Boas práticas e validação

Boas práticas gerais

1. Estrutura semântica

HTML
Preview
Copy
<!-- ✓ Correcto -->
<article>
    <header>
        <h1>Título do artigo</h1>
        <p>Publicado em <time datetime="2024-01-15">15 de Janeiro</time></p>
    </header>
    <p>Conteúdo do artigo...</p>
</article>

<!-- ✗ Incorrecto -->
<div class="artigo">
    <div class="cabecalho">
        <div class="titulo">Título do artigo</div>
    </div>
    <div class="conteudo">Conteúdo do artigo...</div>
</div>
 

2. Acessibilidade

HTML
Preview
Copy
<!-- Imagens com texto alternativo -->
<img src="grafico-vendas.jpg" alt="Gráfico mostrando aumento de 20% nas vendas em 2024">

<!-- Formulários com labels -->
<label for="email">Email:</label>
<input type="email" id="email" name="email" required aria-describedby="email-ajuda">
<div id="email-ajuda">Introduza o seu endereço de email</div>

<!-- Navegação por teclado -->
<button onclick="funcao()" onkeypress="funcao()">Clique ou pressione Enter</button>
 

3. SEO (Search Engine Optimization)

HTML
Preview
Copy
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="Descrição breve e relevante da página (150-160 caracteres)">
    <meta name="keywords" content="palavras-chave, relevantes, para, a, página">
    <meta name="author" content="Nome do autor">
    <meta property="og:title" content="Título da página para redes sociais">
    <meta property="og:description" content="Descrição para redes sociais">
    <meta property="og:image" content="https://exemplo.com/imagem.jpg">
    <meta property="og:url" content="https://exemplo.com/pagina">
    <title>Título da página - Nome do Site</title>
    <link rel="canonical" href="https://exemplo.com/pagina">
</head>
 

4. Performance

HTML
Preview
Copy
<!-- Imagens otimizadas -->
<img src="imagem.webp" 
     srcset="imagem-400.webp 400w, imagem-800.webp 800w, imagem-1200.webp 1200w"
     sizes="(max-width: 400px) 400px, (max-width: 800px) 800px, 1200px"
     alt="Descrição da imagem"
     loading="lazy">

<!-- CSS crítico inline -->
<style>
    /* Estilos críticos para o conteúdo acima da dobra */
    body { margin: 0; font-family: Arial, sans-serif; }
    header { background: #333; color: white; }
</style>

<!-- CSS não-crítico carregado assincronamente -->
<link rel="preload" href="estilos.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
 

5. Segurança

HTML
Preview
Copy
<!-- Formulários com proteção CSRF -->
<form action="/submeter" method="POST">
    <input type="hidden" name="csrf_token" value="token_unico_aqui">
    <!-- resto do formulário -->
</form>

<!-- Links externos com segurança -->
<a href="https://externo.com" target="_blank" rel="noopener noreferrer">Link externo</a>

<!-- Conteúdo de terceiros com sandbox -->
<iframe src="https://externo.com" sandbox="allow-scripts allow-same-origin"></iframe>
 

Ferramentas de validação

1. W3C Validator

HTML
Preview
Copy
<!-- Use o validador online em: https://validator.w3.org/ -->
<!-- Ou instale extensões para o seu editor -->
 

2. Ferramentas de desenvolvedor do navegador

JavaScript
Copy
// Console para verificar erros
console.log('Mensagem de debug');
console.error('Erro detectado');
console.warn('Aviso');

// Verificar performance
console.time('operacao');
// código a medir
console.timeEnd('operacao');
 

3. Lighthouse (Chrome DevTools)

HTML
Preview
Copy
<!-- Execute auditorias de:
- Performance
- Acessibilidade
- Boas práticas
- SEO
- PWA
-->
 

Checklist de validação

Antes de publicar:

  • [ ] HTML válido sem erros
  • [ ] Todos os formulários têm labels
  • [ ] Imagens têm alt text
  • [ ] Página é responsiva
  • [ ] Títulos estão hierarquizados (h1, h2, h3…)
  • [ ] Meta tags de SEO estão presentes
  • [ ] Favicon está configurado
  • [ ] Sitemap XML criado
  • [ ] robots.txt configurado
  • [ ] Performance testada
  • [ ] Acessibilidade verificada
  • [ ] Cross-browser testing realizado
  • [ ] SSL/TLS ativado (HTTPS)

16. Referência rápida

Elementos HTML5 por categoria

Estrutura do documento

HTML
Preview
Copy
<!DOCTYPE html>
<html>, <head>, <title>, <meta>, <link>, <style>, <script>, <body>
 

Estrutura semântica

HTML
Preview
Copy
<header>, <nav>, <main>, <article>, <section>, <aside>, <footer>, <address>
 

Agrupamento de conteúdo

HTML
Preview
Copy
<p>, <hr>, <pre>, <blockquote>, <ol>, <ul>, <li>, <dl>, <dt>, <dd>, <figure>, <figcaption>, <div>
 

Semântica de texto

HTML
Preview
Copy
<a>, <em>, <strong>, <small>, <s>, <cite>, <q>, <dfn>, <abbr>, <ruby>, <rt>, <rp>, <data>, <time>, <code>, <var>, <samp>, <kbd>, <sub>, <sup>, <i>, <b>, <u>, <mark>, <span>, <br>, <wbr>
 

Multimédia

HTML
Preview
Copy
<img>, <audio>, <video>, <source>, <track>, <canvas>, <svg>
 

Tabelas

HTML
Preview
Copy
<table>, <caption>, <colgroup>, <col>, <tbody>, <thead>, <tfoot>, <tr>, <td>, <th>
 

Formulários

HTML
Preview
Copy
<form>, <fieldset>, <legend>, <label>, <input>, <button>, <select>, <datalist>, <optgroup>, <option>, <textarea>, <output>, <progress>, <meter>
 

Elementos interactivos

HTML
Preview
Copy
<details>, <summary>, <dialog>, <menu>
 

Scripts

HTML
Preview
Copy
<script>, <noscript>, <template>, <slot>, <canvas>
 

Atributos globais

HTML
Preview
Copy
accesskey, class, contenteditable, data-*, dir, draggable, hidden, id, lang, spellcheck, style, tabindex, title, translate
 

Tipos de input HTML5

HTML
Preview
Copy
text, password, email, url, tel, search, number, range, date, month, week, time, datetime-local, color, file, checkbox, radio, submit, reset, button, image, hidden
 

APIs HTML5 principais

  • Canvas: Desenho 2D/3D
  • SVG: Gráficos vetoriais
  • Audio/Video: Multimédia nativo
  • Geolocation: Localização GPS
  • LocalStorage: Armazenamento persistente
  • SessionStorage: Armazenamento de sessão
  • Web Workers: Processamento paralelo
  • WebSockets: Comunicação em tempo real
  • Server-Sent Events: Push do servidor
  • Drag and Drop: Arrastar e largar
  • Application Cache: Aplicações offline
  • History: Manipulação do histórico
  • Cross-document messaging: Comunicação entre janelas
  • Web Storage: Armazenamento local
  • IndexedDB: Base de dados local

Recursos adicionais

Editores recomendados

  • Visual Studio Code (gratuito)
  • Sublime Text
  • Atom (gratuito)
  • WebStorm

Ferramentas online

Documentação oficial

Recursos para aprender mais