Una de las tareas que más pereza me da en el desarrollo de un sitio responsive es la creación del menú de navegación. Hablo del desarrollo, de escribir el código, no de su diseño que es muy divertido. No se trata de una pereza insuperable es que simplemente implica escribir mucho código en diferentes lenguajes (CSS, HTML y JavaScript) y frena un poco el proceso de llevar el diseño de Sketch al navegador.

Existen librerías y plugins que te ayudan en esta labor pero es algo que me gusta pensarlo bien y saber exactamente cómo se comporta. Vaya, que me gusta escribir el código.

Cuando tuve que hacer el menú de este sitio me tomé mi tiempo. Leí mucho y me entretuve en hacerlo paso a paso. Tengo las notas tomadas por varios sitios así que quiero reunirlo todo en este post y, ya de paso, si te sirve pues mucho mejor. También estaré muy agradecido si me haces algún comentario que me ayude a mejorar este proceso. El post ha quedado un poco extenso, mil palabras. Más allá de los detalles del código, lo ideal es que nos centremos en los conceptos, en porqué y cómo se da cada paso. Bueno, ahí vamos.

Objetivos
El objetivo es crear un menú de navegación alineado a la derecha en la versión de escritorio que pasa a ser un panel lateral en la versión móvil. Al tocar en el enlace de menú toda la página se desplaza hacia la izquierda mostrando el menú. Aquí tienes una animación:

menu-responsive-iphone
Paso 1. El diseño
Aunque en la fase de creación del CSS sigo el método mobile first al diseñar empecé por la versión de escritorio. El menú no puede ser más sencillo (ya lo ves arriba).
Para la versión móvil quería que el menú estuviera en un panel lateral oculto. Al tocar sobre el icono de menú aparece desde la derecha. Tampoco invento nada, un comportamiento de lo más estándar y natural.

Paso 2. El código HTML
La estructura HTML también es bastante clara y directa:


<nav class="navigation" id="main-navigation">
  <div>
    <ul>
      <li><a href="">Trabajos</a></li>
      <li><a href="">Blog</a></li>
      <!-- Los enlaces que necesites -->
    </ul>
  </div>
</nav>

Al elemento nav le damos la clase navigation que contendrá los estilos del menú. También le asigno un id a nav “main-navigation” que usaré más tarde en el código de JavaScript.

También vamos a necesitar un enlace encargado de mostrar el menú en la versión móvil:

Captura de pantalla 2014-07-24 09.26.32


<a class="navigation-toggle" href="#" id="nav-open">Nav</a>

 

Paso 3. El CSS
Empiezamos por definir el estilo que se verá en la versión móvil. Básicamente definimos el ancho del panel (15 em y lo «sacamos» de la pantalla posicionándolo absolutamente y dándole la misma distancia que el ancho: right: -15em).

/* Definimos un ancho y lo movemos a la derecha
.navigation{
  width: 15em;
  right: -15em; 
  position: absolute;
  overflow: hidden;
  display: block;
  height: 10000%;
  background-color: #000;
}

A continuación damos el estilo para la versión de escritorio:

/* En escritorio reseteamos el max-height y lo posicionamos relativamente */
@media only screen and (min-width: 37.5em){
.navigation{
  max-height: inherit; 
  position: relative;
  right: inherit; //anulamos su posición fuera de la pantalla
  width: auto; //le damos todo el ancho que necesite
  background: transparent;
}
}

Estos estilos definen el contenedor global del menú. El estilo de cada elemento del menú también cambia: en la versión móvil va uno debajo de otro mientras que en pantallas más anchas se disponen en horizontal:


.navigation li{
  display: block; //los elementos van uno debajo de otro
}
@media only screen and (min-width: 37.5em){
.navigation li{
  display: inline-block; //los elementos van en línea
}
}

Con esto ya tenemos un menú que en pantallas estrechas no se ve, queda a la derecha de la pantalla y que en pantallas anchas se muestra en horizontal alineado a la derecha.

El enlace que despliega el menú no tiene tampoco ningún misterio: una caja de 50 x 50 px posicionada arriba a la derecha.


.navigation-toggle {
  width: 50px;
  height: 50px;
  position: absolute;
  top: 10px;
  right: 0px;
}
/* Ocultamos el enlace en pantallas anchas */
@media only screen and (min-width: 37.5em){
  .navigation-toggle{
    width: 0;
    height: 0;
  }
}

Paso 4. El JavaScript
El código JavaScript es el encargado de mostrar el menú cuando tocamos en el icono de menú en la versión móvil.
Necesitamos dos funciones:
1. para mostrar el menú (open_nav())
2. para ocultar (close_nav())

Lo que va a hacer la función open_nav() es añadir una clase (panel-nav) a la etiqueta html que será la encargada de desplazar toda la página 15 em hacia la izquierda. Realmente no movemos el panel de navegación sino todo el sitio. Todo el html de la página (la página y el menú que queda a la derecha) está contenido en una capa con id #wrapper.


function open_nav() {
    $j('html').addClass('panel-nav');
    is_open = 1;
}

function close_nav() {
     $j('html').removeClass('panel-nav');
     is_open = 0;
}

Al aplicar la clase .nav-js a html podemos definir en el CSS .nav-js #wrapper y decirle que se mueva 15 em a la izquierda:


.nav-js #wrapper{
  -webkit-transform:translate(-15em, 0) scale(1, 1);
     -moz-transform:translate(-15em, 0) scale(1, 1);
      -ms-transform:translate(-15em, 0) scale(1, 1);
       -o-transform:translate(-15em, 0) scale(1, 1);
	  transform:translate(-15em, 0) scale(1, 1);
}

Hemos definido las funciones que aplican y quitan la clase .panel-nav, nos queda lanzarlas cuando el usuario toca el enlace de ménu:


//Evaluamos el tipo de evento:
//touchstart para dispositivos táctiles
//mouseup para el resto
var tipoEvento = ((document.ontouchstart !== null) ? 'mouseup' : 'touchstart');

$j(document).on(tipoEvento, function(e) {
  if (is_open === 1) { // si está abierto
    if (!$j(e.target).closest("#main-navigation").length > 0) { 
         //y no pincho en navegación
         close_nav(); //ciérrate
    }
   } else { // si está cerrado
      if ($j(e.target).closest("#nav-open").length > 0) { 
         //y pincho en nav open
         open_nav(); //abro
      }
   }
});

Es interesante observar el uso de closest. Me volví loco para conseguir que el menú se ocultara cuando el usuario tocaba en cualquier lugar de la pantalla excepto en el panel del menú. Con closest puedo ver si ha tocado en algún punto del panel o no.

Con esto ya tendríamos todo listo para que al tocar el menú se desplace toda la página y el menú sea visible.

See the Pen HzoIm by Ernesto Jiménez (@ernestojimenez) on CodePen.

Me gustaba más este efecto de desplazamiento que simplemente el menú se superpusiera sobre el contenido.

Este elemento lleva muchos más estilos aplicados en el sitio real, he intentado simplificar las declaraciones a efectos didácticos. Iba a escribir todo este proceso en mi chuletario pero me ha parecido más interesante publicarlo aquí. Espero que tener todo el proceso detallado aquí me ayude a ser más ágil la próxima vez que desarrolle un menú responsive (hoy mismo).

¿Te ha gustado el post? Puedes seguirme en Twitter o en Facebook donde seguimos hablando de diseño web