Skip to main content
Validação HTML

Valor inválido “tabpanel” para o atributo “role” no elemento “ul”.

Sobre este problema HTML

O validador W3C apresenta este erro porque os roles ARIA devem ser compatíveis com o elemento ao qual são aplicados. Um elemento <ul> tem um role ARIA implícito de list, e substituí-lo por tabpanel cria um conflito. O role tabpanel sinaliza às tecnologias assistivas que o elemento é um painel de conteúdo ativado por um separador correspondente. Quando este role é colocado num <ul>, os leitores de ecrã perdem o significado semântico da lista (contagem de itens, navegação da lista, etc.) enquanto também representam incorretamente a função do elemento na interface de separadores.

Isto é importante por várias razões:

  • Acessibilidade: Os utilizadores de leitores de ecrã dependem de roles corretos para navegar e compreender a estrutura da página. Um <ul> marcado como tabpanel confunde tanto a sua semântica de lista como o seu papel na interface de separadores.
  • Conformidade com as normas: A especificação ARIA em HTML define quais roles são permitidos em quais elementos. O role tabpanel não é permitido em <ul>.
  • Comportamento do navegador: Os navegadores podem lidar com roles conflituosos de forma inconsistente, levando a comportamentos imprevisíveis entre tecnologias assistivas.

A correção é simples: envolva o <ul> dentro de um elemento de contentor adequado (como um <div> ou <section>) e aplique o role tabpanel a esse contentor em vez disso.

Exemplos

Incorreto: role tabpanel num <ul>

Isto desencadeia o erro de validação porque tabpanel não é um role válido para <ul>:

<div role="tablist" aria-label="Recipe categories">
  <button role="tab" aria-controls="panel-1" aria-selected="true" id="tab-1">Appetizers</button>
  <button role="tab" aria-controls="panel-2" aria-selected="false" id="tab-2">Desserts</button>
</div>

<ul role="tabpanel" id="panel-1" aria-labelledby="tab-1">
  <li>Bruschetta</li>
  <li>Spring rolls</li>
</ul>

<ul role="tabpanel" id="panel-2" aria-labelledby="tab-2" hidden>
  <li>Tiramisu</li>
  <li>Cheesecake</li>
</ul>

Correto: role tabpanel num contentor que envolve o <ul>

Mova o role tabpanel para um <div> e aninhie o <ul> dentro dele. Isto preserva tanto a semântica do painel de separadores como a semântica da lista:

<div role="tablist" aria-label="Recipe categories">
  <button role="tab" aria-controls="panel-1" aria-selected="true" id="tab-1">Appetizers</button>
  <button role="tab" aria-controls="panel-2" aria-selected="false" id="tab-2">Desserts</button>
</div>

<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">
  <ul>
    <li>Bruschetta</li>
    <li>Spring rolls</li>
  </ul>
</div>

<div role="tabpanel" id="panel-2" aria-labelledby="tab-2" hidden>
  <ul>
    <li>Tiramisu</li>
    <li>Cheesecake</li>
  </ul>
</div>

Correto: usar <section> como painel de separadores

Um elemento <section> também funciona bem como contentor de painel de separadores, especialmente quando o conteúdo do painel é mais complexo:

<div role="tablist" aria-label="Project info">
  <button role="tab" aria-controls="tasks-panel" aria-selected="true" id="tasks-tab">Tasks</button>
  <button role="tab" aria-controls="notes-panel" aria-selected="false" id="notes-tab">Notes</button>
</div>

<section role="tabpanel" id="tasks-panel" aria-labelledby="tasks-tab">
  <h2>Current tasks</h2>
  <ul>
    <li>Review pull requests</li>
    <li>Update documentation</li>
  </ul>
</section>

<section role="tabpanel" id="notes-panel" aria-labelledby="notes-tab" hidden>
  <h2>Meeting notes</h2>
  <p>Discussed project timeline and milestones.</p>
</section>

Numa interface com separadores devidamente estruturada:

  • O role tablist vai no contentor que contém os botões de separadores.
  • Cada gatilho de separador recebe role="tab" com aria-controls a apontar para o id do seu painel.
  • Cada painel de conteúdo recebe role="tabpanel" num contentor genérico como <div> ou <section>, com aria-labelledby a referenciar o id do separador correspondente.
  • Elementos de lista como <ul> e <ol> devem permanecer dentro do painel como conteúdo regular, mantendo a sua semântica nativa de lista.

Encontre problemas como este automaticamente

O Rocket Validator analisa milhares de páginas em segundos, detetando problemas HTML em todo o seu site.

Ajude-nos a melhorar os nossos guias

Este guia foi útil?

Pronto para validar os seus sites?
Comece o seu teste gratuito hoje.