Skip to content
This page has been auto-translated and may contain errors.View in English

HTML Semântico ​

docs.scrimba.com

Duas páginas podem parecer idênticas e ser construídas de formas bem diferentes por dentro. Uma usa elementos nomeados de acordo com o que eles contêm: um cabeçalho, uma navegação, uma área principal. A outra envolve tudo na mesma caixa anônima e depende de nomes de classe para diferenciar as partes. Na tela, você não percebe diferença nenhuma. Em qualquer outro aspecto, elas não são a mesma página. Escolher elementos pelo seu significado é o que o HTML semântico propõe.

O que significa "semântico" ​

Semântico significa "relacionado ao significado". Um elemento semântico é aquele cujo nome diz o que é o seu conteúdo. Um parágrafo fica dentro de um <p> porque é um parágrafo. Um menu de navegação fica dentro de um <nav> porque é navegação. O nome da tag identifica a coisa.

Você poderia construir quase qualquer página usando uma única caixa genérica e fazê-la parecer correta com estilização. Mas, nesse caso, nada na página diria o que ela é. Escolher o elemento que nomeia o conteúdo é como etiquetar as caixas quando você se muda de casa. Tudo ainda caberia em caixas simples e sem etiqueta, mas são as etiquetas que permitem que outra pessoa, ou um navegador, entenda o que há dentro sem precisar abrir cada uma delas.

Um elemento é semântico quando seu nome descreve o significado do seu conteúdo, e não a aparência desse conteúdo. <nav>, <article> e <button> são semânticos: eles dizem para que serve o conteúdo. <div> e <span> não são: são contêineres genéricos que não significam nada por si só.

O ganho é que o significado passa a existir na marcação, onde outras ferramentas conseguem lê-lo. Um navegador sabe que um <button> é clicável e pode receber foco pelo teclado sem que você precise fazer nada. Um leitor de tela pode anunciar um <nav> como uma região de navegação. Mecanismos de busca tratam um <article> como um conteúdo autocontido. Nada disso funciona se o elemento é apenas um <div> estilizado, porque um <div> não promete nada sobre o que ele contém.

Semântica é a diferença entre um elemento que carrega significado e um que carrega apenas pixels. Quando você escreve <nav>, você está fazendo mais do que desenhar uma caixa: está afirmando um fato sobre o documento — esta região é navegação. Esse fato é registrado na árvore de acessibilidade (a estrutura paralela que o navegador constrói junto com o DOM, descrevendo o papel e o estado de cada elemento para tecnologias assistivas), e é sobre ela que outras ferramentas, além de um usuário de mouse que consegue ver a tela, agem.

O teste prático é a substituição. Se você trocasse um elemento por um <div> puro e o estilizasse para parecer idêntico, o que você perderia? Para um <p> ou um wrapper decorativo, nada relevante. Para um <button>, você perderia o foco pelo teclado, o tratamento das teclas Enter e Espaço, e o anúncio de "botão" para um leitor de tela — e teria que reconstruir tudo isso manualmente. Essa lacuna é a semântica: o comportamento e o significado que o navegador oferece de graça porque o nome do elemento já disse a ele o que aquele conteúdo é. Escolher o elemento nomeado não é uma preferência de estilo, é o caminho mais barato para obter o comportamento correto.

JunoO que significa 'semântico' Semântico significa que a tag é nomeada de acordo com o que ela contém: um parágrafo dentro de um <p>, um menu dentro de um <nav>. Você poderia colocar tudo em caixas simples e estilizar para parecer igual, mas aí nada diria o que é. Pense nisso como etiquetar as caixas de mudança para que qualquer pessoa saiba o que tem dentro.
JunoO que significa 'semântico' Um elemento semântico nomeia o seu significado, um <div> não nomeia nada. A vantagem é que navegadores, leitores de tela e mecanismos de busca conseguem ler o significado direto da marcação. Recorra ao elemento que descreve o conteúdo, e deixe o <div> para quando realmente não houver nada a descrever.
JunoO que significa 'semântico' Aplique o teste de substituição: troque o elemento por um <div> estilizado e pergunte o que você perdeu. Se a resposta for foco pelo teclado, um papel na árvore de acessibilidade ou um anúncio de leitor de tela, isso é a semântica que você estava recebendo de graça. Reconstruir isso na mão sempre dá mais trabalho do que usar o elemento nomeado.

Os elementos de marco (landmark) ​

Existe um punhado de elementos criados para marcar as grandes regiões de uma página. São esses os primeiros a que você deve recorrer:

  • <header> é o topo de uma página ou seção: um logo, um título, uma introdução.
  • <nav> é um conjunto de links de navegação, como o menu principal.
  • <main> é o conteúdo principal, o motivo pelo qual a página existe.
  • <section> é um bloco agrupado de conteúdo relacionado, normalmente com seu próprio título.
  • <article> é uma peça autocontida que ainda faria sentido isolada, como um post de blog ou uma notícia.
  • <aside> é conteúdo à parte: links relacionados, uma nota, um anúncio.
  • <footer> é o rodapé de uma página ou seção: direitos autorais, dados de contato, informações em letras pequenas.

A regra é sempre a mesma. Se uma região é navegação, ela fica dentro de um <nav>, não de um <div>. Se é o rodapé, fica dentro de um <footer>. Você nomeia a região com o elemento que corresponde a ela.

html
<header>
  <h1>Cozinha da Mara</h1>
  <nav>
    <a href="/recipes">Receitas</a>
    <a href="/about">Sobre</a>
  </nav>
</header>
<main>
  <h2>Jantares de semana</h2>
  <p>Refeições rápidas para depois do trabalho.</p>
</main>
<footer>
  <p>Feito em Lisboa.</p>
</footer>

Sete elementos dividem uma página em suas regiões principais, e juntos são chamados de elementos de marco (landmarks) porque cada um marca uma região até a qual um leitor ou uma ferramenta pode navegar:

  • <header> introduz o contêiner mais próximo dele: no topo da página, contém a identidade visual do site; dentro de um <article>, contém o título e a assinatura daquele artigo.
  • <nav> envolve um bloco de links de navegação. Use-o para os links relevantes, como o menu principal ou um sumário, não para qualquer link isolado da página.
  • <main> contém o conteúdo principal do documento, a parte exclusiva daquela página, e não algo repetido em todo o site.
  • <section> agrupa conteúdo relacionado que pertence junto, normalmente introduzido por um título.
  • <article> é uma unidade completa e independente: um post, um comentário, um card de produto. O teste é: será que faria sentido tirar esse trecho e exibi-lo isolado?
  • <aside> contém conteúdo tangencial ao que o rodeia: uma barra lateral, uma citação destacada, links relacionados.
  • <footer> fecha o contêiner mais próximo dele com o material de encerramento: autoria, links, texto legal.

A ideia central é que a maioria desses elementos é contextual. Um <header> e um <footer> descrevem o que quer que esteja ao redor deles, então uma única página pode ter vários de cada um: um par para a página inteira e um para cada <article>. <main> é a exceção, tratada na próxima seção.

html
<article>
  <header>
    <h2>Sopa de tomate assado</h2>
    <p>Por Kwame, 20 minutos</p>
  </header>
  <p>Corte os tomates pela metade e asse até ficarem macios.</p>
  <footer>
    <p>Serve quatro pessoas.</p>
  </footer>
</article>

Os sete elementos de região são os landmarks do HTML: elementos que expõem uma região navegável na árvore de acessibilidade. Cada um corresponde a um papel (role) que a tecnologia assistiva consegue listar e entre os quais pode saltar, o que é o verdadeiro motivo pelo qual eles importam, além de deixar o código-fonte organizado.

  • <header> corresponde ao papel banner no nível da página, mas não quando está aninhado dentro de um <article>, <aside>, <main>, <nav> ou <section>, caso em que é apenas um grupo introdutório sem papel de landmark.
  • <footer> reflete isso: contentinfo no nível da página, e um grupo simples quando aninhado dentro de um desses elementos de seccionamento.
  • <nav> corresponde ao papel navigation. Uma página costuma ter mais de um, um menu principal e uma lista de conteúdo dentro da página, e é aí que entra a rotulagem descrita mais adiante.
  • <main> corresponde ao papel main e marca o conteúdo principal. Há apenas um por página.
  • <aside> corresponde ao papel complementary: conteúdo que apoia o conteúdo principal, mas se mantém separado dele.
  • <section> só se torna um landmark do tipo region quando tem um nome acessível, normalmente vindo de um título associado a ela; um <section> sem nome não expõe nenhum landmark e, para a árvore de acessibilidade, é quase equivalente a um <div>.
  • <article> carrega o papel article, uma composição autocontida, que ferramentas conseguem enumerar, mas que não é um landmark de navegação no mesmo sentido que os outros.

O objetivo de design é um documento que um usuário não visual consiga percorrer tão rápido quanto um usuário visual percorre o layout com os olhos. Um leitor de tela pode produzir uma lista de todos os landmarks e deixar o usuário saltar direto para "main" ou "navigation" sem precisar ouvir o conteúdo intermediário. Isso só funciona se as regiões estiverem marcadas com elementos de landmark reais. Uma página cheia de <div>s de ponta a ponta produz um documento sem nenhum landmark, e o único jeito de percorrê-lo é de cima a baixo.

html
<body>
  <header>            <!-- banner: nível de página -->
    <nav>...</nav>    <!-- navigation -->
  </header>
  <main>              <!-- main: a única região principal -->
    <article>...</article>
    <aside>...</aside> <!-- complementary -->
  </main>
  <footer>...</footer> <!-- contentinfo: nível de página -->
</body>
JunoOs elementos de marco (landmark) Há sete tags de região que vale conhecer: <header>, <nav>, <main>, <section>, <article>, <aside> e <footer>. Cada uma nomeia uma parte da página, e você escolhe a que corresponde à região que está construindo. Você não precisa memorizá-las hoje, elas vão aparecer várias vezes até você fixar.
JunoOs elementos de marco (landmark) Sete elementos dividem uma página em regiões, e a maioria deles descreve o que estiver ao redor, então <header> e <footer> podem aparecer mais de uma vez. O teste do <article> me poupou muita indecisão: será que isso funcionaria isolado, se você o tirasse do lugar? Se sim, é um article; se for um bloco agrupado com um título, é uma section.
JunoOs elementos de marco (landmark) Esses são os landmarks, e cada um corresponde a um papel para o qual um leitor de tela pode saltar, e é por isso que eles superam uma pilha de <div>s. Duas pegadinhas que valem lembrar: <header> e <footer> só se tornam os landmarks banner e contentinfo no nível mais alto, e uma <section> só é landmark depois que tem um nome acessível. Uma section sem nome é basicamente uma div para a tecnologia assistiva.

div e span, a alternativa não semântica ​

Nem toda parte de uma página tem um significado que valha a pena nomear. Às vezes você só precisa de uma caixa para agrupar coisas e estilizá-las, ou envolver algumas palavras para colori-las. Para isso existem dois elementos simples, sem significado próprio.

<div> é um bloco genérico: um contêiner vazio que você usa quando nenhum outro elemento se encaixa. <span> é a mesma ideia para um trecho pequeno de texto dentro de uma linha. Nenhum dos dois diz nada sobre seu conteúdo. Eles existem puramente como ganchos para estilização e agrupamento.

html
<p>O total de hoje é <span class="price">R$ 42,00</span>.</p>

<div class="card">
  <h2>Oferta especial</h2>
  <p>Compre um e leve outro, em todos os macarrões.</p>
</div>

O <span> envolve um preço para que você possa colori-lo. O <div> agrupa um card para que você possa colocar uma borda em volta dele. Recorra a esses elementos apenas quando nada mais significativo se encaixar, porque eles não dizem nada ao navegador sobre o que há dentro.

<div> e <span> são os dois elementos sem nenhum significado, e é exatamente para isso que servem. Um <div> é um contêiner genérico de nível de bloco; um <span> é um contêiner genérico em linha. Você os usa como ganchos de estilização: um lugar para aplicar uma classe ou um id quando você precisa agrupar ou direcionar conteúdo, mas não há nada significativo a dizer sobre ele.

html
<div class="grid">
  <article class="card">...</article>
  <article class="card">...</article>
</div>

O <div class="grid"> existe só para organizar os cards em uma grade. Essa é uma função visual, não uma função de significado, então um <div> é a escolha correta, não um recurso pelo qual você deve se sentir mal. O erro é o contrário: usar um <div> para algo que tem significado. Um <div> clicável deveria ser um <button>, um <div> cheio de links de navegação deveria ser um <nav>, um <div> que envolve um post inteiro deveria ser um <article>. Quando não há significado, apenas uma necessidade de layout ou estilização, <div> e <span> são a resposta certa.

<div> e <span> são os elementos semanticamente vazios: um bloco genérico e um contêiner genérico em linha, respectivamente, sem papel na árvore de acessibilidade e sem significado para nenhuma ferramenta. Eles são a escolha correta para uma única função, o gancho apresentacional: um elemento que existe unicamente para receber estilização ou agrupar elementos filhos para fins de layout, e que não carrega nenhuma informação que um leitor de tela ou um mecanismo de busca deveria anunciar.

O valor de ter um elemento sem nenhum significado é que ele mantém os elementos significativos honestos. Um wrapper de grade, uma linha de flexbox, um contexto de posicionamento: essas são necessidades reais sem conteúdo semântico, e forçar um elemento significativo nesses casos seria uma mentira na marcação. Uma <section> usada só para uma cor de fundo está afirmando ser uma região que não é. Então a regra vale nos dois sentidos. Não recorra a um <div> quando um elemento nomeado se encaixa, e não recorra a um elemento nomeado quando tudo que você precisa é de uma caixa.

O modo de falha a observar é o <div> interativo: um elemento ao qual se atribui um manipulador de clique em JavaScript para que se comporte como um botão ou um link. Ele renderiza e reage a cliques do mouse, então parece estar completo, mas não tem papel definido, não está na ordem de tabulação, não responde a Enter ou Espaço, e um leitor de tela não anuncia nada. Recriar tudo isso com tabindex, role e manipuladores de tecla é uma reimplementação frágil de um <button> que já existe. Se algo se comporta como um controle, use o elemento de controle; deixe <div> e <span> para as partes que são só pixels, sempre.

Junodiv e span, a alternativa não semântica<div> é uma caixa simples e <span> é um envoltório simples para algumas palavras, e nenhum dos dois significa nada. Use-os quando você só precisa agrupar ou estilizar algo e nenhum elemento nomeado se encaixa. Se a coisa realmente tem um significado, como um menu ou um botão, use o elemento correspondente em vez disso.
Junodiv e span, a alternativa não semântica Um <div> ou <span> é a escolha certa quando a única função é layout ou estilização, sem nenhum significado a declarar. Não se sinta mal por usá-los, sinta-se mal pelo contrário: um <div> clicável que deveria ser um <button>, ou um <div> de wrapper que deveria ser um <article>. Elemento vazio para significado vazio, elemento nomeado para significado real.
Junodiv e span, a alternativa não semântica<div> e <span> não têm papel na árvore de acessibilidade, e é justamente por isso que são certos para ganchos de estilização puros e errados para qualquer coisa com significado. O que vai te pegar é o <div> interativo com um manipulador de clique: sem foco, sem teclado, sem anúncio, e uma pilha de remendos com tabindex e role para imitar o que o <button> te dá de graça. Se algo se comporta como um controle, transforme-o no controle.

Escolhendo o elemento certo ​

Quando você não tiver certeza de qual elemento usar, faça uma pergunta simples: o que é essa coisa? Não o que ela parece, mas o que ela é. A resposta costuma indicar o elemento por si só. Uma fileira de links no topo é navegação, então é um <nav>. Um bloco de letras pequenas no final é um rodapé, então é um <footer>. Um preço que você quer colorir não é realmente nada específico, então é um <span>.

Comece a partir do significado, e só recorra a um <div> ou <span> quando a resposta real for "isso é só uma caixa". Criar esse hábito desde já faz com que suas páginas se descrevam por si mesmas, e isso compensa no momento em que você, ou qualquer outra pessoa, precisar reler a marcação.

Escolher o elemento certo é uma decisão rápida que você pode aplicar toda vez. Pergunte o que é o conteúdo, e deixe a resposta escolher o elemento:

  • É algo completo por si só, que faria sentido isolado? <article>.
  • É um bloco agrupado de conteúdo relacionado com um título? <section>.
  • É navegação? <nav>. É uma introdução a uma região? <header>. É um encerramento? <footer>.
  • É conteúdo lateral que apoia o conteúdo principal? <aside>.
  • Não há significado, apenas uma necessidade de layout ou estilização? <div>, ou <span> dentro de uma linha.

A bifurcação mais complicada é <section> versus <article> versus <div>. Percorra-a em ordem. Se o bloco pudesse se sustentar isoladamente, é um <article>. Se não, mas é um grupo temático com o seu próprio título, é uma <section>. Se não tem título e nem significado, e existe apenas para ser estilizado ou organizado no layout, é um <div>. Uma <section> quase sempre deveria ter um título; se você não conseguir pensar em um, isso é um forte indício de que você queria um <div>.

html
<main>
  <section>
    <h2>Últimos posts</h2>
    <article>
      <h3>Por que troquei para HTML puro</h3>
      <p>...</p>
    </article>
    <article>
      <h3>O caso contra frameworks pesados</h3>
      <p>...</p>
    </article>
  </section>
</main>

Aqui a <section> é um grupo temático, "últimos posts", e cada post dentro dela é um <article> porque se sustenta isoladamente. O aninhamento reflete o significado.

Escolher bem se resume a ler o significado primeiro e nunca o layout, mas algumas regras tornam as decisões mais comuns quase automáticas.

Existe exatamente um <main> por página. Ele marca o conteúdo principal, a parte exclusiva daquela página, e não o cabeçalho, a navegação e o rodapé, que se repetem em todo o site. Mais de um <main> na árvore de acessibilidade dá a um usuário de leitor de tela dois destinos "main" e nenhuma forma de saber qual é o verdadeiro, então mantenha-o singular. Tudo que é comum ao site inteiro fica fora dele.

A outra regra que costuma importar bastante é rotular landmarks repetidos. Quando uma página tem dois elementos do mesmo tipo de landmark, um <nav> principal e um sumário dentro da página, ambos são anunciados como "navigation" e o usuário não consegue diferenciá-los. Você resolve isso com aria-label, um atributo que fornece um nome acessível curto para uma região sem exibir nada na tela:

html
<nav aria-label="Principal">
  <a href="/">Início</a>
  <a href="/blog">Blog</a>
</nav>

<nav aria-label="Nesta página">
  <a href="#intro">Introdução</a>
  <a href="#setup">Configuração</a>
</nav>

Agora as duas regiões são anunciadas como "navegação Principal" e "navegação Nesta página", e a lista de landmarks fica utilizável. Aplique a mesma rotulagem a qualquer landmark repetido, incluindo <aside> ou <section>. Para <section>, lembre-se de que ela só se torna um landmark depois que tem algum nome acessível, seja a partir de um título associado ou de um aria-label.

A regra por trás de tudo isso: a marcação é uma descrição legível por máquina do documento, lida por leitores de tela, crawlers de busca, ferramentas de modo leitura e por você mesmo no futuro. Escolher elementos pelo significado é o que torna essa descrição verdadeira. Layout é trabalho do CSS, e toda vez que você se pegar escolhendo um elemento pela aparência, você entrou no território do CSS usando a ferramenta errada.

JunoEscolhendo o elemento certo Quando você ficar em dúvida, pergunte o que a coisa é, não o que ela parece. Navegação é um <nav>, letras pequenas são um <footer>, uma caixa simples que você quer estilizar é um <div>. Comece pelo significado sempre, e suas páginas acabam se descrevendo por si mesmas.
JunoEscolhendo o elemento certo Passe pela lista rápida: se sustenta isolado é um <article>, grupo temático com título é uma <section>, sem significado e só para estilizar é um <div>. O critério que resolve a maioria das dúvidas entre section e div: se você não consegue dar um título para aquilo, você queria um <div>. Deixe o significado escolher a tag e o aninhamento se resolve por conta própria.
JunoEscolhendo o elemento certo Duas regras carregam a maior parte do peso: exatamente um <main> por página, e rotular landmarks repetidos com aria-label para que dois navs não sejam anunciados como "navigation" os dois. Lembre-se de que uma <section> só é landmark depois que tem um nome acessível. Escolha elementos pelo significado e deixe a aparência para o CSS, porque no momento em que você escolhe uma tag pela forma como ela renderiza, você está fazendo o trabalho do CSS com a ferramenta errada.