Banner propaganda da DevMedia - Cursos de desenvolvimento web

Âncoras versus botões

visualizações Publicado em: 08/06/2016

Crédito: essa matéria é uma tradução e foi escrita por Ire Aderinokun. URL do original: Anchors vs Buttons

Introdução

Por muito tempo desenvolvedores web (inclusive eu) usamos elementos <a>, <div>, <span> e uma série de outros exceto o elemento <button> para criar componentes interativos clicáveis em uma página. Algo semelhante ao mostrado a seguir.

HTML

<a href="#" role="button" onclick="openMenuModal();">Navegação</a>  
Não faça isso

O atributo href definido para o elemento âncora recebe um valor tal que quando o usuário clica o link não acontece a esperada ação de navegação típica de quando se clica um link. Usa-se JavaScript para alterar a ação padrão do evento clique. Mas, existe um elemento HTML apropriado para exercer aquele comportamento que foi simulado com uso da JavaScript. Trata-se do elemento <button> ou mais especificamente o elemento <button type="button">.

HTML

<button type="button" onclick="openMenuModal();">Navegação</button>  

Apesar disto o elemento âncora vem sendo amplamente usado para disparar interações na página, e na maioria dos casos, de forma incorreta. Contudo, convém notar que o botão não é a solução para tudo e eu acredito que em alguns casos o uso da âncora é mais apropriado. Para entendermos o quando e o porquê vamos começar estabelecendo as diferenças entre âncoras e botões.

Diferenças entre âncoras e botões

Visualmente os elementos <a> e <button type="button"> podem ser exatamente iguais, pois para isso basta que sejam estilizados apropriadamente, porém semanticamente eles são diferentes e isso para usuários com necessidades especiais particularmente aqueles com restrições de exercer ações de apontar e clicar, tais como aqueles incapazes de usar o mouse, poderá ser desastroso.

Elemento âncora

O elemento <a> representa um hyperlink cujo destino é uma página ou uma seção dentro da própria página. O rótulo deste elemento é o seu conteúdo que poderá ser qualquer um, desde uma imagem até um elemento adicional não interativo tais como elementos <div>, <p>, etc.

Uma vez que o elemento <a> relaciona-se a um link, para ele estão disponíveis as pseudo-classes CSS :link e :visited. E também as pseudo-classes :hover, :active e :focus relacionadas à interação do usuário.

Ao se navegar com uso do teclado os elementos âncora podem ser "clicados" quando se pressiona a tecla Enter. Os leitores de tela, quando um link é clicado, esperam que o usuário navegue para uma página externa ou para uma seção na mesma página.

Elemento botão

O elemento <button>, ou mais especificamente o elemento<button type="button"> não faz nada. Ao contrário de outros tipos de botão, tal como o <button type="reset"> que reseta (limpa) os campos de um formulário o <button type="button"> não tem um comportamento padrão e em consequência não desencadeia nenhum tipo de ação.

Pelo fato de que nenhum link está associado ao botão, somente as pseudo-classes CSS de ação do usuário (:hover, :active e :focus) estão disponíveis para este elemento. Assim botões podem ser estilizados facilmente como se elementos âncora fossem.

Na navegação com uso de teclado, botões podem ser "clicados" ao se pressionar a tecla Enter ou a tecla para inserção de espaço, sendo esta a mais comumente usada. Para leitores de tela a expectativa de ação quando o usuário clica um botão na página é de que seja acionado um script JavaScript de interação. Alguns leitores de tela anunciam o elemento como sendo um botão dizem ao usuário: "click".

Quais são os problemas?

Problema com botões

Em primeiro lugar quero repetir que se a sua marcação se parece com a mostrada a seguir ...

<a href="#" role="button" onclick="openMenuModal();">Navegação</a>  
Não faça isso

... você deveria usar um botão.

Contudo, em alguns casos, usar um botão isoladamente não é necessariamente a solução mais adequada.

O elemento <button type="button">, como já dissemos, não faz nada. É preciso usar JavaScript para adicionar funcionalidade ao botão. Por outro lado, se JavaScript estiver desabilitado no dispositivo do usuário, ele não terá como interagir com o botão que no nosso exemplo seria acessar o menu de navegação.

Embora tenhamos feito tudo certo para leitores de tela usando uma marcação semântica bloqueamos acesso aos usuários com JavaScript desabilitado.

Problema com âncoras

A solução para estes casos é usar o elemento âncora modificando-o de duas formas distintas conforme descritas a seguir.

  1. Disponibilizar uma alternativa expressiva no atributo href;
  2. Alterar a semântica do elemento âncora de modo a que ele se pareça e se comporte como um botão para leitores de tela.

Observe a marcação a seguir que esclarece o que foi dito.

<a href="#navigation-alternative" role="button" onclick="openMenu();">Navegação</a>

Assim, se o dispositivo do usuário está com JavaScript desabilitado o acesso ao conteúdo da navegão será possível. Adicionalmente, uma vez que o botão é "clicável" com uso da tecla de espaço é possível atrelar o evento click à âncora-botão como mostrado a seguir.

var bindSpaceKey = function(anchor) {  
    anchor.addEventListener('keyup', function(event) {
        if (event.keyCode == 32) { anchor.click(); }
    })
}
var anchorButtons = document.querySelectorAll('a[role="button"]');  
for ( var i = 0; i < anchorButtons.length; i++ ) {  
    bindSpaceKey( anchorButtons[i] );
}

Na minha opinião, embora esta solução seja melhor do que usar um botão, ela não é perfeita. Primeiro: se JavaScript não está habilitado o elemento âncora deverá ser semanticamente um link e não um botão. Mas, uma vez que definimos role="button" para a âncora, ela será sempre um botão para os leitores de tela, mesmo nos casos em que não o é.

Segundo: ainda que tenhamos definido role="button" para a âncora eu não estou inteiramente convencida de que isso faça da âncora um elemento exatamente igual a um botão. Ainda que os leitores de tela e demais agentes de usuário devam tratá-la como um botão, não está garantido que o farão.

Qual é a solução

Estamos diante de um dilema.

O elemento <button> é semanticamente correto, mas não atende o quesito melhoria progressiva (progressive enhancement) e, ao contrário, o elemento <a> atende o quesito melhoria progressiva, mas é semanticamente impróprio.

Assim, a única solução que eu vejo é alterar o elemento usado baseado nas circunstâncias. Em nome da consistência e da semântica, vamos usar JavaScript para vincular a tecla de espaço ao evento click em <a role="button">. Quando Javascript estiver desabilitado o elemento permanece como um link regular e semanticamente correto. Mas, quando Javascript estiver habilitado o elemento âncora é trocado por um elemento botão.

Na marcação HTML usamos um link regular sem modificações. Observe a seguir a solução proposta.

<a href="#navigation-alternative" class="anchorButton">Navegação</a>  

Se JavaScript estiver habilitado usamos esta linguagem para trocar todas as âncoras por botões.

var changeAnchorToButton = function(anchor) {

    // Criar elemento botão com os mesmos conteúdos e atributos das âncoras
    var button = document.createElement('button');
    button.setAttribute('type', 'button');
    button.innerHTML = anchor.innerHTML;
    button.id = anchor.id;
    for ( var i = 0; i < anchor.classList.length; i++ ) {
        button.classList.add(anchor.classList[i]);
    }

    // Substitui âncoras por botões
    var anchorParent = anchor.parentNode;
    anchorParent.replaceChild(button, anchor);
}
var anchorButtons = document.getElementsByClassName('anchorButton');  
for ( var i = 0; i < anchorButtons.length; i++ ) {  
    changeAnchorToButton( anchorButtons[i] );
}

Podemos estilizar o seletor .anchorButton de modo que tanto <a> quanto <button> sejam visualmente iguais como mostrado a seguir.

.anchorButton {
  /* Resets */
  font-family: sans-serif;
  font-size: 16px;
  color: #000;
  border: 1px solid #000;
  border-radius: 0;
  background-color: transparent;

  margin: 0;
  padding: 0;
  height: auto;
  width: auto;
  cursor: pointer;

  /* Mais estilos... */
}
a.anchorButton {  
  /* Estilos para elementos <a> */
  text-decoration: none;
}
button.anchorButton {  
  /* Estilos para elementos <button> */
  -webkit-appearance: none;
  -moz-appearance: none;
}

Embora esta solução seja radical, foi a única que eu consegui desenvolver atendendo os critérios de consistência visual, semântica e acessibilidade. E, a estilização conveniente do seletor .anchorButton não afetará a consistência visual da página como um todo.

Crédito: essa matéria é uma tradução e foi escrita por Ire Aderinokun. URL do original: Anchors vs Buttons

Conheça os livros do Maujor®

Clique a "capinha" para visitar o site do livro

capa livro jQuery capa livro ajaxjQuery capa livro css capa livro html capa livro javascript capa livro html5 capa livro css3 capa livro jQuery Mobile capa livro jQuery UI capa livro SVG capa livro RWD capa livro foundation capa livro HTML5 e CSS3 capa livro Bootstrap3 capa livro Sass e Compass

topo