Exemplo de menu mobile (responsivo) acessível
Postado em 22/07/2016 por Luiz Volso
Com o crescimento do uso de smartphones para acesso à conteúdo online, desenvolvedores precisam adaptar seus documentos HTML às novas tendências. Assim surgiu o design responsivo e com ele o menu mobile, aquele que fica no cantinho superior da tela e na grande maioria das vezes tem o famoso ícone das três barrinhas empilhadas.
Esse artigo demonstra uma forma (dentre várias possíveis) de criar um menu desses com um diferencial: acessível pelo teclado.
Marcação HTML do Menu
Primeiramente a marcação HTML do menu:
<nav>
<h2 aria-haspopup="true" tabindex="0" id="abremenu">Menu Principal</h2>
<ul class="menu" aria-expanded="false" aria-hidden="true">
<li role="menuitem"><a href="#">Início</a></li>
<li role="menuitem"><a href="#">Serviços</a></li>
<li role="menuitem"><a href="#">Produtos</a></li>
<li role="menuitem"><a href="#">Contato</a></li>
</ul>
</nav>
O título <h2>
vai servir de gatilho para abrir o menu, foi adicionado um ID para facilitar com os seletores jQuery e um tabindex="0"
que serve para o elemento ser adicionado ao fluxo de navegação quando utilizada a tecla TAB.
O atributo aria-haspopup="true"
indica ao agente de usuário que existe um submenu adiante, o menu possui aria-expanded="false"
indicando que está retraído e também aria-hidden="true"
indicando que ele está escondido. Os itens li
possuem o atributo role="menuitem"
indicando que cada ítem faz parte do menu.
Vamos adicionar uma folha de estilos CSS de reset:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
Adicionamos alguns estilos CSS para configurar os estados iniciais dos elementos do menu e também adicionar algumas melhorias visuais:
body{
font-family: 'Verdana';
}
header{
background-color: #ECECEC;
position: relative;
height: 80px;
}
nav h2{
text-indent: -9999px;
background-color: #666;
width: 60px;
height: 60px;
margin: 10px;
float: left;
cursor: pointer;
}
.menu{
position: absolute;
left: -200px;
top: 80px;
width: 200px;
background-color: #ECECEC;
}
.menu[aria-hidden="true"]{
display: none;
}
.menu a{
display: block;
padding: 0 24px;
line-height: 50px;
font-size: 1.5em;
text-decoration: none;
color: #666;
}
.menu a:hover, .menu a:focus{
background-color: #666;
color: #ECECEC;
}
O menu precisa funcionar obrigatoriament com o mouse e teclado, quando forem adicionados os códigos jQuery na camada de comportamento isso deve ser levado em consideração. Primeiramente criamos duas funções, uma para abrir e outra para fechar o menu, ambas utilizam o animate
do jQuery para posicionar o menu fora da tela e trazê-lo de volta. Além a animação, quando o menu é aberto, alteramos aria-hidden="true"
para false
e aria-expanded="false"
para true
.
function fechaMenu(){
$('.menu').animate({ 'left':'-200px' }, 200, function(){
$(this).attr({'aria-hidden': true, 'aria-expanded': false});
});
}
function abreMenu(){
$('.menu').attr({'aria-hidden': false, 'aria-expanded': true}).animate({ 'left' : 0 }, 200);
}
Agora a parte do jQuery que vai controlar a abertura e fechamento do menu:
$('document').ready(function(){
// Verifica se o menu está aberto, se não, abre, tanto no clique quanto no foco
$('#abremenu').on('click focusin', function(){
if($('.menu').attr('aria-hidden') == 'true'){
abreMenu();
}
});
// Na perda de algum elemento dentro de nav, fecha-se o menu
$('nav').focusout(function(){
setTimeout(function(){
var el = $(document.activeElement);
if($('nav').find(el).length == 0) {
fechaMenu();
}
}, 100);
});
});
Tanto o click
quanto o focusin
servem para abrir o menu. Em focusout
há uma verificação para detectar se o elemento que tem o foco atual está contido no menu, se não, este é fechado. Foi adicionada uma função de timeout devido a um pequeno atraso que o navegador tem para trocar o elemento que possui o foco.
Para encerrar, mais algumas pequenas melhorias no comportamento. Fechar o menu clicando fora dele e também pressionando a tecla ESC.
$('document').ready(function(){
// Para fechar o menu caso o usuário clique fora dele,
// O clique no documento todo é monitorado, fechando o menu
$(document).click(function(){
fechaMenu();
});
// Paramos a propagação do clique caso este seja dentro do menu
$('nav').click(function(){
event.stopPropagation();
});
// Fechar o menu caso a tecla ESC seja pressionada
$(document).on('keyup', function (e){
if (e.keyCode === 27) {
fechaMenu();
}
});
});
Espero que o artigo seja útil, deixe suas dúvidas ou opniões nos comentários abaixo e sucesso!
Um abraço.