IvoGomes.com

Voltar ao início

Navegação sem listas: um teste de acessibilidade

Desde o início da web que os links de navegação são normalmente colocados numa lista não ordenada (<ul>) em que cada item é identificado na lista por um <li>.

<ul>
   <li><a href="#">Link 1</a></li>
   <li><a href="#">Link 2</a></li>
   <li>...</li>
</ul>

Em termos de acessibilidade isto é vantajoso porque os leitores de ecrã vão sempre ler "lista com X itens" e depois vão ler cada item da lista individualmente. No final, alguns ainda comunicam "fim da lista".

HTML5

Com a chegada do HTML5, apareceram algumas tags mais semânticas que permitem dar significado a alguns elementos na página. Entre essas novas tags destaca-se a <nav>.

À medida que o HTML5 ia ganhando popularidade e suporte por parte dos browsers, os web designers começaram a aproveitar as vantagens das novas tags, e assim, a navegação passou de uma simples lista para uma lista dentro de um bloco de navegação:

<nav>
   <ul>
      <li><a href="#">Link 1</a></li>
      <li><a href="#">Link 2</a></li>
      <li>...</li>
   </ul>
</nav>

Na melhoria contínua de acessibilidade, passou a ser recomendado adicionar um "ARIA role" à navegação, para que os browsers que não tenham ainda suporte total para as novas tags possam reconhecer o seu significado semântico. Assim, o <nav> passou a ser acompanhado, de forma redundante, pelo seu "role" <nav role="navigation">, assim:

<nav role="navigation">
   <ul>
      <li><a href="#">Link 1</a></li>
      <li><a href="#">Link 2</a></li>
      <li>...</li>
   </ul>
</nav>

No entanto, em todo os browsers que testei, com ou sem "role" o elemento de navegação era corretamente identificado pelos leitores de ecrã. Apenas em browsers mais antigos (ex: IE8) ele é ignorado, mas se vamos usar tags de HTML5 e queremos na mesma dar suporte a browsers antigos, usamos o HTML5Shiv, um script que permite que browsers antigos interpretem corretamente as novas tags de HTML.

Com este script, até o IE8 interpretou corretamente o bloco de navegação no leitor de ecrã, o que indica que não é necessário ter a redundância do "role" quando o próprio elemento <nav> já tem esse significado de forma intrínseca.

Nos últimos anos tem sido assim que a maior parte dos blocos de navegação tem sido escrito pelos web designers, em nome da acessibilidade e da semântica das novas tags HTML5. Mas será assim tão melhor do que o método antigo?

Como os leitores de ecrã interpretam os dois tipos de navegação?

Se testarmos a navegação apenas com a lista (ul) versus a navegação com a lista dentro do bloco de navegação (nav > ul), vemos que o segundo caso acaba por ser bastante mais verboso para os utilizadores, e como tal, potencialmente mais confuso.

Fazendo um teste com os 3 leitores de ecrã mais populares do mercado, os resultados foram os seguintes:

Tipo de navegação JAWS VoiceOver NVDA
ul > li > a Todos os leitores de ecrã comunicam "Lista de X itens"
nav > ul > li > a Comunica "Região de navegação" e depois "Lista de X itens" Ignora o bloco de navegação e comunica apenas "Lista de X itens" Comunica "Marca: navegação" e depois "Lista de X itens"

Como podemos ver, à exceção do VoiceOver da Apple, os outros leitores de ecrã comunicam tanto a região de navegação como a lista de itens, resultando assim em mais ruído auditivo para o utilizador que está a navegar na página. O VoiceOver ignora completamente o bloco de navegação e comunica apenas uma lista normal.

E se não usarmos listas?

O que acontece se colocarmos apenas uma lista de links dentro de um bloco de navegação <nav>?

O código é válido em HTML5 e teoricamente vamos reduzir a quantidade de informação verbalizada pelo leitor de ecrã, ao mesmo tempo que damos um significado semântico à navegação (algo que com um simples <ul> não é possível, pois não podemos simplesmente adicionar um role="navigation" a este tipo de elemento).

<nav>
   <a href="#">Link 1</a>
   <a href="#">Link 2</a>
   <a href="#">...</a>
</nav>

Olhando para este markup podem achar que isto não faz sentido, mas se formos ler as especificações do HTML5 para o <nav>, isto é uma solução válida.

A nav element doesn't have to contain a list, it can contain other kinds of content as well. In this navigation block, links are provided in prose.

Adicionalmente, podemos ter outros elementos (que sejam ARIA landmarks) que podem ter navegação própria sem esta estar contida numa lista.

Not all groups of links on a page need to be in a nav element — the element is primarily intended for sections that consist of major navigation blocks. In particular, it is common for footers to have a short list of links to various pages of a site, such as the terms of service, the home page, and a copyright page. The footer element alone is sufficient for such cases; while a nav element can be used in such cases, it is usually unnecessary.

Por exemplo, ter uma navegação no <footer> da seguinte maneira, também é válido.

<footer>
   <a href="#">Link 1</a>
   <a href="#">Link 2</a>
   <a href="#">...</a>
</footer>

Em termos de markup, esta solução é bastante mais simples, pois temos apenas a relação directa nav > a em vez de nav > ul > li > a.

Testando nos leitores de ecrã, obtemos a seguinte verbalização para este elemento:

Tipo de navegação JAWS VoiceOver NVDA
nav > a "Região de navegação" "Navegação com X itens" "Marca: navegação"

Todos os leitores de ecrã comunicam corretamente o bloco de navegação, sendo que o VoiceOver vai um pouco mais longe e indica também o número de itens, como nas listas.

Testando com utilizadores reais

Com base neste resultados, fiz o teste com alguns utilizadores cegos (utilizadores regulares de leitores de ecrã) para saber a sua opinião sobre qual das navegações era mais intuitiva.

O primeiro feedback recebido é de que não há grandes diferenças de navegabilidade entre as várias versões. No entanto, a versão com nav > ul > li > a, por ser mais verbosa (na maior parte dos leitores de ecrã são lidas ambas as informações: "região de navegação" e "lista com X itens"), foi a menos preferida.

Com base nos testes efetuados e no feedback de utilizadores reais, concluo que a solução de ter uma lista de links diretamente num bloco <nav> é uma solução eficaz, que mantém a semântica do elemento, e não é demasiado verbosa para o utilizador.

A solução que engloba uma <ul> dentro de um bloco <nav> (que é a que o que vemos com maior frequência por aí) acaba por ser a pior de todas, pois cria uma redundância denecessária no código e na verbalização feita pelo leitor de ecrã.

Então e os sub-menus?

Com as listas, criar sub-menus é trivial. Basta iniciar uma nova lista dentro do elemento que queremos que tenha sub-itens. Podemos criar sub-níveis infinitamente, no entanto, por questões de usabilidade, não se recomendam mais do que 3 níveis de navegação.

<nav>
   <ul>
      <li><a href="#">Link 1</a></li>
      <li><a href="#">Link 2</a>
         <ul>
            <li><a href="#">Sub-link 1</a></li>
            <li><a href="#">Sub-link 2</a></li>
            <li>...</li>
         </ul>
      </li>
      <li>...</li>
   </ul>
</nav>

Infelizmente, o uso do elemento <nav> não contempla (de forma semântica) o aninhamento de sub-navegações. Qualquer combinação de nav > nav resulta numa confusão por parte dos leitores de ecrã, que não percebem que é uma navegação dentro de outra navegação, e tratam-na como duas navegações iguais, uma a meio da outra.

Uma possível solução é usar o atributo aria-owns para dar esse significado hierárquico. Segundo as especificações, podemos criar uma relação "pai/filho" entre dois elementos no DOM usando este atributo, assim:

<nav role="navigation">
   <a href="#">Link 1</a>
   <a href="#" aria-owns="SubLink2">Link 2</a>
   <nav id="SubLink2">
      <a href="#">Sub-link 1</a>
      <a href="#">Sub-link 2</a>
   </nav>
   <a href="#" aria-owns="SubLink3">Link 3</a>
   <nav id="SubLink3">
      <a href="#">Sub-link 1</a>
      <a href="#">Sub-link 2</a>
   </nav>
   <a href="#">Link 4</a>
</nav>

No entanto, nos testes com leitores de ecrã, não é muito claro a perceção destes níveis hierárquicos. Essencialmente, o leitor de ecrã acaba por comunicar apenas uma região de navegação a meio de outra região de navegação, sem que se perceba a sua relação "pai/filho".

Adicionalmente, uma vez que o elemento "pai" é um <a>, antes de passar a ler o elemento filho <div>, o leitor de ecrã comunica "link região de navegação", ou seja, associa o tipo dos dois elementos (link e região de navegação) e comunica os dois de forma concatenada, resultando em mais confusão para o utilizador.

Para tentar resolver este problema, tentei colocar os links dentro de um elemento diferente, ex: um <span>:

<nav role="navigation">
   <span><a href="#">Atualidade</a></span>
   <span aria-owns="SubLink2"><a href="#">Desporto</a></span>
   <nav id="SubLink2" role="navigation">
      <span><a href="#">Porto</a></span>
      <span><a href="#">Benfica</a></span>
   </nav>
   <span aria-owns="SubLink3"><a href="#">Economia</a></span>
   <nav id="SubLink3" role="navigation">
      <span><a href="#">Finanças</a></span>
      <span><a href="#">Dinheiro</a></span>
   </nav>
   <span><a href="#">Tecnologia</a></span>
</nav>

Isto resolveu o problema da confusão anterior, no entanto continua a não ser fácil de navegar, pois nem todos os leitores de ecrã comunicam o fim das regiões de navegação (tal como fazem com as listas), o que faz com que os utilizadores não percebam que terminou o sub-menu e já estão a ouvir o link de navegação de topo que vem a seguir.

Conclusão

Com base nestes dados, para uma navegação simples (apenas um nivel hierárquico) é melhor usar um markup simples como nav > a ou até mesmo footer > a.

Para navegações mais complexas, com vários níveis hierárquicos, em termos de acessibilidade é melhor manter o uso de listas, pois estas permitem que o browser consiga perceber o que está dentro do quê, criando assim uma árvore lógica dos conteúdos.

Outras soluções? Opiniões? Sugestões? Escrevam nos comentários abaixo ;)


Atualização: O capítulo sobre os sub-menus foi rescrito para testar o atributo aria-owns.


0 Comentários

Comente este artigo!

Comente!

* Campo obrigatório, de modo a aparecer o seu nome como autor do comentário

* Campo obrigatório, mas não será mostrado no site

* Campo obrigatório, convém escrever alguma coisa ;)

São permitidas algumas tags HTML, como
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>