Menú responsive con Flexbox: crear el menú y los submenús

Menú responsive con Flexbox: crear el menú y los submenús

El posicionamiento de los elementos siempre ha sido un problema real, incluso con sistemas como block, inline-block o table. Ya sea con floats o con inline-block, no es raro toparse con complicaciones en este terreno. Por suerte ha habido avances y hoy, con el abandono progresivo de los navegadores antiguos como Internet Explorer, podemos empezar a alinear nuestros elementos con la ayuda del módulo Flexbox. En este tutorial te voy a demostrar lo fácil que es montar un menú en unas pocas líneas.

Paso 1 – La base

Antes de escribir CSS, vamos a definir la base de nuestro menú en 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 a aplicar un estilo básico al menú:

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

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

Paso 2 – El menú

Una vez sentadas las bases de nuestros elementos, ¡ya podemos ponernos con el menú!

css
.nav .menu {
    display: flex; /*1*/
    flex-direction : row; /*2*/
    justify-content: center; /*3*/
}
  • 1 – Definimos la visualización en modo flexbox.
  • 2 – Con flex-direction indicamos que los hijos del elemento actual se alineen en fila.
  • 3 – justify-content permite alinear los hijos a la izquierda, en el centro o a la derecha del elemento actual.

flexbox01.JPG

En solo 3 líneas ya tienes el principio de un menú. Si necesitas alinearlo a la derecha, basta con poner flex-end en la propiedad justify-content. ¿Quieres invertir la fila? Pon row-reverse en flex-direction. Flexbox no solo es más sencillo, también es muy flexible. ¿Y si te dijera que la versión móvil ocupa una sola línea?

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

@media(max-width: 450px) {
      flex-flow: column wrap; /*4*/
    }
}
  • 4 – En una resolución de tipo móvil, con la ayuda de flex-flow, que es un atajo de flex-direction y flex-wrap, mostramos los hijos en columna y permitimos el salto de línea.

flexbox02.JPG

Y ya está. Bueno, en realidad son 3, pero si nos quedamos aquí ya tenemos una primera versión básica de nuestro menú responsive. Aunque ya lo sabes: también hay submenús, y eso es justo lo que veremos en el siguiente paso.

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

Paso 3 – Los submenús

Para montar un submenú vamos a crear dos clases: has-children, que se aplicará a un elemento del menú que tenga un submenú, y la clase 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 -->

Para mi ejemplo he decidido meter un submenú dentro de otro submenú (nivel inception), porque no es raro encontrarse con 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 el elemento en relativo para alinear el submenú respecto a su padre.
  • 2 – Si el cursor del ratón está sobre un elemento que contiene un submenú, mostramos el submenú en modo flexbox.
  • 3 – Definimos el comportamiento por defecto del submenú: de entrada debe estar oculto, se alinea en columna y le damos un tamaño mínimo de 100 px (no es obligatorio, pero en mi ejemplo el submenú quedaría ridículamente pequeño).
  • 4 – Alineamos el texto a la izquierda por una cuestión estética.
  • 5 – Alineamos el sub-submenú a la misma altura que su padre y a su derecha (right: 0 px; no funcionaría en un caso así).

flexbox03.JPG

Y ahora la versión responsive:

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 las interacciones con los usuarios de móvil y tableta, tira de JavaScript. Y si tienes submenús, monta además un menú deslizante: en este tutorial no lo he hecho, pero resulta mucho más cómodo para tus 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.

Compatibilidad de Flexbox

Flexbox está bastante bien soportado por los navegadores, pero hay algunos detalles que conviene conocer para afinar esa compatibilidad. Hoy ya se puede empezar a plantear su uso, y no cabe duda de que dentro de unos años veremos crecer mucho su presencia, incluso en los frameworks más conocidos como Bootstrap o Foundation.

Internet Explorer Firefox Chrome Safari Android
Compatible a partir de Internet Explorer 10 con el prefijo -ms-, sin prefijo por encima de la 10. De Firefox 19 a 21, usa el prefijo -moz-, sin prefijo por encima de la 21 Hasta la versión 28 con -webkit-, sin prefijo por encima de la 28 Hasta la 10 con -webkit-, sin prefijo por encima Con -webkit- hasta la versión 4.3, sin prefijo por encima

CSS

Damien Flandrin Desarrollador web desde 2010, creador de Gekkode y de Email Impact. Cada artículo se prueba en un proyecto real antes de publicarse. Contacto
Newsletter

Las nuevas pruebas, tutoriales y proyectos, por correo.

Pruebas reproducibles, código versionado, resultados fechados. Nunca spam.