Menu responsivo com Flexbox: criar o menu e os submenus

Menu responsivo com Flexbox: criar o menu e os submenus

Posicionar elementos sempre foi um verdadeiro problema, mesmo com sistemas como block, inline-block ou table. Seja com floats ou com inline-block, não é raro esbarrar em complicações neste terreno. Felizmente houve avanços e hoje, com o abandono progressivo dos navegadores antigos como o Internet Explorer, podemos começar a alinhar os nossos elementos com a ajuda do módulo Flexbox. Neste tutorial vou mostrar-te como é fácil montar um menu em apenas algumas linhas.

Etapa 1 – A base

Antes de escrever CSS, vamos definir a base do nosso menu em HTML5.

html
<nav class="nav" role="navigation">
    <ul clas="menu">
        <li><a href="https://www.damienflandrin.fr/blog/post/#">Accueil</a></li>
        <li><a href="https://www.damienflandrin.fr/blog/post/#">Catégories</a></li>
        <li><a href="https://www.damienflandrin.fr/blog/post/#">À Propos de Moi</a></li>
        <li><a href="https://www.damienflandrin.fr/blog/post/#">Contact</a></li>
    </ul>
</nav>

Vamos aplicar um estilo de base ao menu:

css
.nav ul {
    margin: 0px;
    padding: 0px;
    background: tomato;
    list-style:none;
}

.nav a {
    padding: 1em;
    display: block;
    text-align:center;
    text-decoration: none;
}

Etapa 2 – O menu

Com as bases dos elementos assentes, podemos agora atacar o menu!

css
.nav .menu {
    display: flex; /*1*/
    flex-direction : row; /*2*/
    justify-content: center; /*3*/
}
  • 1 – Definimos a apresentação em modo flexbox.
  • 2 – Com flex-direction indicamos que os filhos do elemento atual se alinhem em linha.
  • 3 – justify-content permite alinhar os filhos à esquerda, ao centro ou à direita do elemento atual.

flexbox01.JPG

Em apenas 3 linhas já tens o princípio de um menu. Se precisares de o alinhar à direita, basta pôr flex-end na propriedade justify-content. Queres inverter a linha? Põe row-reverse em flex-direction. O Flexbox não é só mais simples, é também muito flexível. E se te dissesse que a versão para telemóvel ocupa uma única linha?

css
.nav .menu {
    display: flex; /*1*/
    flex-direction : row; /*2*/
    justify-content: center; /*3*/

@media(max-width: 450px) {
      flex-flow: column wrap; /*4*/
    }
}
  • 4 – Numa resolução de telemóvel, com a ajuda de flex-flow, que é um atalho de flex-direction e flex-wrap, mostramos os filhos em coluna e permitimos a mudança de linha.

flexbox02.JPG

E pronto. Bom, na realidade são 3, mas se ficarmos por aqui já temos uma primeira versão básica do nosso menu responsivo. Só que, como bem sabes, também há submenus, e é isso que vamos ver na etapa seguinte.

See the Pen Menu responsive avec Flexbox – 1 by Damien Flandrin (@dam62500) on CodePen.

Etapa 3 – Os submenus

Para montar um submenu vamos criar duas classes: has-children, que se aplica a um elemento do menu que tenha submenu, e a classe sous-menu.

html
<!-- notre menu flexbox -->
    <nav class="nav" role="navigation">
        <ul class="menu">
            <li><a href="https://www.damienflandrin.fr/blog/post/#">Accueil</a></li>
            <li class="has-children"><a href="https://www.damienflandrin.fr/blog/post/#">Catégories</a>
                <!-- sous menu-->
                <ul class="sous-menu">
                    <li><a href="https://www.damienflandrin.fr/blog/post/#">Item 1</a></li>
                    <li><a href="https://www.damienflandrin.fr/blog/post/#">Item 2</a></li>
                    <li class="has-children"><a href="https://www.damienflandrin.fr/blog/post/#">Item 3</a>
                        <!-- un sous menu dans un sous-menu-->
                        <ul class="sous-menu">
                            <li><a href="https://www.damienflandrin.fr/blog/post/#">Item 1</a></li>
                            <li><a href="https://www.damienflandrin.fr/blog/post/#">Item 2</a></li>
                            <li><a href="https://www.damienflandrin.fr/blog/post/#">Item 3</a></li>
                            <li><a href="https://www.damienflandrin.fr/blog/post/#">Item 4</a></li>
                        </ul>
                        <!-- /un sous menu dans un sous-menu-->
                    </li>
                    <li><a href="https://www.damienflandrin.fr/blog/post/#">Item 4</a></li>
                </ul>
                <!-- /sous menu-->
            </li>
            <li><a href="https://www.damienflandrin.fr/blog/post/#">À Propos de Moi</a></li>
            <li><a href="https://www.damienflandrin.fr/blog/post/#">Contact</a></li>
        </ul>
    </nav>
<!-- /notre menu flexbox -->

No meu exemplo decidi meter um submenu dentro de outro submenu (nível inception), porque não é raro deparar com este tipo de casos.

css
  .has-children { /*1*/
    position: relative;
  }

.has-children:hover > .sous-menu { /*2*/
    display: flex;
  }

.sous-menu { /*3*/
    display: none;
    flex-flow: column wrap;
    min-width: 100px;
    position: absolute;
    background: dodgerblue;
  }

.sous-menu a { /*4*/
    text-align: left;
    color:white;
  }

.sous-menu .sous-menu { /*5*/
    top: 0px;
    left: 100%;
    background: #1e76d6;
  }
  • 1 – Posicionamos o elemento em relativo para alinhar o submenu em relação ao pai.
  • 2 – Se o cursor do rato estiver sobre um elemento que contém um submenu, mostramos o submenu em modo flexbox.
  • 3 – Definimos o comportamento por omissão do submenu: à partida tem de estar escondido, alinha-se em coluna e damos-lhe um tamanho mínimo de 100 px (não é obrigatório, mas no meu exemplo o submenu ficaria ridiculamente pequeno).
  • 4 – Alinhamos o texto à esquerda por uma questão estética.
  • 5 – Alinhamos o sub-submenu à mesma altura do pai e à sua direita (right: 0 px; não funcionaria num caso destes).

flexbox03.JPG

E agora a versão responsiva:

css
.sous-menu {
    display: none;
    flex-flow: column wrap;
    min-width: 100px;
    position: absolute;
    background: dodgerblue;
    @media(max-width: 450px) {
      position: static;
    }
}

.sous-menu.is-active {
        display: flex!important;
}

.sous-menu a { /*4*/
    text-align: left;
        @media(max-width: 450px) {
      text-align: center;
    }
    color:white;
  }

.sous-menu .sous-menu {
    top: 0px;
    left: 100%;
    background: #1e76d6;
}

flexbox04.JPG

Para as interações com os utilizadores de telemóvel e tablet, usa JavaScript. E se tiveres submenus, faz antes um menu deslizante: neste tutorial não o fiz, mas é bem mais confortável para os teus visitantes.

javascript
$('.sous-menu').click(function(){
    if ($(window).width() < 450) {
        if($(this).hasClass('is-active'))
            $(this).removeClass('is-active');
        else
            $(this).addClass('is-active');
    }
});

See the Pen Menu responsive avec Flexbox – 2 by Damien Flandrin (@dam62500) on CodePen.

Compatibilidade do Flexbox

O Flexbox é bastante bem suportado pelos navegadores, mas há alguns detalhes que convém conhecer para afinar esse suporte. Hoje já se pode começar a pensar em usá-lo e não há dúvida de que, dentro de alguns anos, veremos a sua presença crescer muito, mesmo nos frameworks mais conhecidos como o Bootstrap ou a Foundation.

Internet Explorer Firefox Chrome Safari Android
Suportado a partir do Internet Explorer 10 com o prefixo -ms-, sem prefixo acima do 10. Do Firefox 19 ao 21, usar o prefixo -moz-, sem prefixo acima do 21 Até à versão 28 com -webkit-, sem prefixo acima do 28 Até ao 10 com -webkit-, sem prefixo acima Com -webkit- até à versão 4.3, sem prefixo acima

CSS

Damien Flandrin Programador web desde 2010, criador da Gekkode e do Email Impact. Cada artigo é testado num projeto real antes de ser publicado. Contacto
Newsletter

Os novos testes, tutoriais e projetos, por e-mail.

Testes reproduzíveis, código versionado, resultados datados. Nunca spam.