Se você usa <div> para tudo — wrapper de página, navegação, container de artigo, barra lateral — você não está sozinho. Era a abordagem padrão por anos. Mas o HTML tem elementos semânticos adequados desde o HTML5, e usá-los torna seu código mais fácil de ler, melhor para SEO e genuinamente mais acessível. Vamos mergulhar nos elementos que realmente importam.

A palavra "semântico" simplesmente significa que o elemento carrega significado além de sua apresentação visual. Um <div> não significa nada — é um bloco genérico. Um <nav> diz ao navegador, mecanismos de busca e tecnologia assistiva: "este contém links de navegação." Esse contexto não custa nada para adicionar e compensa de várias formas.

Por Que a Semântica Importa

Três benefícios reais, não teóricos:

  • SEO. Mecanismos de busca usam a estrutura do documento para entender a hierarquia do conteúdo. Um elemento <main> sinaliza o conteúdo principal. Um <article> dentro dele sinaliza uma peça independente. O Google usa esses sinais ao classificar páginas.
  • Acessibilidade. Leitores de tela expõem regiões de referência aos usuários. Com <nav>, <main> e <aside> no lugar, usuários de teclado podem pular diretamente para a seção desejada — sem pressionar Tab em cada link da página.
  • Manutenibilidade. Um novo desenvolvedor que lê seu template entende imediatamente a estrutura da página. <header>/<main>/<footer> é autodocumentado de uma forma que <div class="top">/<div class="content">/<div class="bottom"> não é.

Os Elementos Principais de Layout

Esses cinco elementos cuidam do esqueleto externo da maioria das páginas. Use-os em todas as páginas e você já ganhou metade da batalha semântica:

html
<body>
  <header>
    <a href="/" class="logo">MyBlog</a>
    <nav>
      <ul>
        <li><a href="/articles">Articles</a></li>
        <li><a href="/about">About</a></li>
        <li><a href="/contact">Contact</a></li>
      </ul>
    </nav>
  </header>

  <main>
    <!-- Primary page content goes here -->
  </main>

  <aside>
    <!-- Sidebar: related links, ads, author bio -->
  </aside>

  <footer>
    <p>&copy; 2026 MyBlog. All rights reserved.</p>
  </footer>
</body>
  • <header>. Conteúdo introdutório para a página ou seção. Geralmente contém o logotipo, título do site e navegação principal. Também pode ser usado dentro de <article> para o bloco de cabeçalho do próprio artigo.
  • <nav>. Um conjunto de links de navegação. Nem todo grupo de links precisa de <nav> — use-o para blocos de navegação principais como a navegação do site ou paginação.
  • <main>. O conteúdo dominante da página. Deve haver apenas um <main> por página, e não deve conter nada repetido entre páginas (cabeçalho, nav, rodapé).
  • <aside>. Conteúdo tangencialmente relacionado ao conteúdo principal. Barras laterais, citações em destaque, artigos relacionados. Leitores de tela expõem isso como um marco complementar.
  • <footer>. Rodapé para a página ou seção. Pode conter informações de copyright, navegação secundária, links de contato ou uma breve nota do autor.
Erro comum: <header> e <footer> não estão restritos ao nível de página. Cada <article> ou <section> pode ter seu próprio <header> e <footer>. Isso é especialmente útil para linhas de crédito de posts de blog e metadados de artigos.

article vs section — Quando Usar Cada Um

Este é o que mais confunde as pessoas. A regra prática que realmente funciona: se o conteúdo faria sentido se fosse distribuído de forma independente (por exemplo, publicado como uma entrada RSS ou compartilhado em outro site), é um <article>. Se só faz sentido como parte de um todo maior, é uma <section>.

html
<!-- article: self-contained, could stand alone -->
<article>
  <header>
    <h2>Understanding HTTP/2 Push</h2>
    <p>By Alice Chen — <time datetime="2026-03-15">March 15, 2026</time></p>
  </header>
  <p>HTTP/2 Server Push lets the server send resources...</p>
  <footer>
    <p>Tagged: <a href="/tags/http">HTTP</a>, <a href="/tags/performance">Performance</a></p>
  </footer>
</article>

<!-- section: thematic grouping within a page -->
<section>
  <h2>Related Articles</h2>
  <ul>
    <li><a href="/http3-quic">HTTP/3 and QUIC Explained</a></li>
    <li><a href="/cdn-strategy">CDN Strategy for Global Apps</a></li>
  </ul>
</section>

<section> sempre deve ter um cabeçalho (<h2> até <h6>). Se sua seção não tem cabeçalho, geralmente é um sinal de que você deve usar um <div> em vez disso. A especificação WHATWG é clara: <section> é para agrupamentos temáticos, não divisões de layout arbitrárias.

figure, figcaption, time e address

Quatro elementos que os desenvolvedores costumam ignorar, mas que precisam com frequência:

html
<!-- figure + figcaption: images, code blocks, diagrams, charts -->
<figure>
  <img src="/images/latency-chart.png" alt="P99 latency over 24 hours showing a spike at 14:30">
  <figcaption>Figure 1: API latency during the Tuesday incident (UTC).</figcaption>
</figure>

<!-- A code block as a figure (totally valid) -->
<figure>
  <pre><code>const result = await db.query('SELECT * FROM users WHERE active = true');</code></pre>
  <figcaption>Listing 1: Basic active user query.</figcaption>
</figure>

<!-- time: machine-readable dates and times -->
<p>Published <time datetime="2026-04-16T09:00:00Z">April 16, 2026</time></p>
<p>Sale ends in <time datetime="PT2H30M">2 hours 30 minutes</time></p>

<!-- address: contact info for nearest article or body ancestor -->
<address>
  Written by <a href="mailto:[email protected]">Alice Chen</a>.<br>
  123 Dev Street, San Francisco, CA.
</address>
  • <figure>. Qualquer conteúdo independente referenciado no fluxo principal — imagens, listagens de código, gráficos, vídeos. O ponto-chave: poderia ser movido para um apêndice sem interromper a leitura.
  • <figcaption>. A legenda para um <figure>. Deve ser o primeiro ou último filho de <figure>. Fornece uma associação semântica entre a legenda e o conteúdo que um <p> abaixo de uma imagem não fornece.
  • <time>. Datas legíveis por humanos com um atributo datetime legível por máquina. O valor de datetime usa o formato ISO 8601. Mecanismos de busca usam isso para marcação de eventos e sinais de atualidade.
  • <address>. Informações de contato para o ancestral <article> mais próximo (ou todo o <body>). Não é um elemento de endereço geral — é especificamente para informações de contato do autor do conteúdo ou proprietário do site.

O Anti-Padrão Divitis

"Divitis" é o que acontece quando cada elemento do seu HTML é um <div>. Aqui está um exemplo real de antes/depois que mostra o problema:

html
<!-- Before: divitis -->
<div class="page">
  <div class="header">
    <div class="brand">TechBlog</div>
    <div class="nav">
      <div class="nav-item"><a href="/posts">Posts</a></div>
    </div>
  </div>
  <div class="post">
    <div class="post-title">Why TypeScript Is Worth It</div>
    <div class="post-meta">By Bob — Jan 2026</div>
    <div class="post-body">TypeScript adds static types to JavaScript...</div>
  </div>
</div>

<!-- After: semantic HTML -->
<body>
  <header>
    <span class="brand">TechBlog</span>
    <nav>
      <a href="/posts">Posts</a>
    </nav>
  </header>
  <main>
    <article>
      <header>
        <h1>Why TypeScript Is Worth It</h1>
        <p>By Bob — <time datetime="2026-01-10">January 10, 2026</time></p>
      </header>
      <p>TypeScript adds static types to JavaScript...</p>
    </article>
  </main>
</body>

A versão semântica é mais curta, requer menos nomes de classes CSS, e fornece ao navegador e ferramentas assistivas tudo o que precisam para entender a estrutura da página. Você ainda pode estilizar tudo da mesma forma com CSS — elementos semânticos não impõem restrições visuais.

Atributos ARIA — Um Último Recurso, Não o Primeiro Passo

Atributos ARIA permitem adicionar significado semântico a elementos que não o têm nativamente. O problema é que os desenvolvedores frequentemente recorrem ao ARIA quando um elemento HTML semântico faria o trabalho melhor. A primeira regra do ARIA: não use ARIA se puder usar HTML nativo.

html
<!-- Wrong: using ARIA where native HTML works -->
<div role="navigation">
  <a href="/home">Home</a>
</div>

<!-- Right: just use the semantic element -->
<nav>
  <a href="/home">Home</a>
</nav>

<!-- ARIA is appropriate here: custom widget with no HTML equivalent -->
<div
  role="tablist"
  aria-label="Code examples"
>
  <button role="tab" aria-selected="true" aria-controls="panel-js">JavaScript</button>
  <button role="tab" aria-selected="false" aria-controls="panel-py">Python</button>
</div>

Use ARIA para widgets interativos que o HTML nativo não cobre — painéis de abas, comboboxes, visualizações em árvore, seletores de data. Para marcos estruturais como navegação, cabeçalhos e conteúdo principal, sempre use elementos nativos.

Uma Estrutura Completa de Página de Post de Blog

Veja como fica uma página de post de blog completamente semântica. Este é o padrão usado em sites que têm boas pontuações em auditorias de acessibilidade sem esforço extra:

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Why TypeScript Is Worth It — TechBlog</title>
</head>
<body>
  <header>
    <a href="/" class="logo">TechBlog</a>
    <nav aria-label="Site navigation">
      <ul>
        <li><a href="/posts">Posts</a></li>
        <li><a href="/topics">Topics</a></li>
        <li><a href="/about">About</a></li>
      </ul>
    </nav>
  </header>

  <main>
    <article>
      <header>
        <h1>Why TypeScript Is Worth It</h1>
        <address>
          By <a rel="author" href="/authors/bob">Bob Martinez</a>
        </address>
        <p>Published <time datetime="2026-01-10">January 10, 2026</time></p>
      </header>

      <section>
        <h2>The Setup Cost Is Real but Front-Loaded</h2>
        <p>TypeScript adds a compilation step and requires type annotations...</p>

        <figure>
          <pre><code>interface User {
  id: number;
  name: string;
  email: string;
}</code></pre>
          <figcaption>Listing 1: A typed User interface catches shape errors at compile time.</figcaption>
        </figure>
      </section>

      <section>
        <h2>Where TypeScript Pays Off</h2>
        <p>The ROI kicks in as team size and codebase complexity grows...</p>
      </section>

      <footer>
        <p>
          Tagged: <a href="/tags/typescript">TypeScript</a>,
          <a href="/tags/javascript">JavaScript</a>
        </p>
      </footer>
    </article>

    <aside aria-label="Related articles">
      <h2>You Might Also Like</h2>
      <ul>
        <li><a href="/ts-vs-js">TypeScript vs JavaScript — A Practical Comparison</a></li>
        <li><a href="/ts-generics">TypeScript Generics Explained</a></li>
      </ul>
    </aside>
  </main>

  <footer>
    <nav aria-label="Footer navigation">
      <a href="/privacy">Privacy</a>
      <a href="/terms">Terms</a>
    </nav>
    <p><small>&copy; 2026 TechBlog</small></p>
  </footer>
</body>
</html>

Observe o uso duplo de <header> e <footer> — uma vez no nível de página, uma vez dentro de <article>. Isso é intencional e correto. Também observe dois elementos <nav> com valores distintos de aria-label — isso evita que leitores de tela listem duas regiões de "navegação" idênticas.

Referência Rápida: Ferramentas que Ajudam

Se você está trabalhando com HTML e quer limpar ou validar sua marcação, o Formatador HTML vai deixar seu código bem indentado, e o Validador HTML captura erros estruturais como tags não fechadas e atributos obrigatórios ausentes. Para uma auditoria de acessibilidade mais profunda, o web.dev/accessibility tem excelentes diagnósticos e explicações.

Conclusão

HTML semântico não é sobre seguir regras por si só — é sobre escrever código que comunica claramente ao navegador, mecanismos de busca, ferramentas assistivas e ao próximo desenvolvedor que lê seu template. Os elementos principais são simples: <header>, <nav>, <main>, <article>, <section>, <aside> e <footer> cobrem a grande maioria das estruturas de página reais. Adicione <figure>, <time> e <address> onde couberem, recorra ao ARIA apenas quando o HTML nativo for insuficiente, e você terá uma marcação genuinamente prazerosa de trabalhar.