1. Web Design
  2. UX/UI
  3. Navigation

Cómo Crear una Navegación Off-Canvas con CSS Grid

El patrón off-canvas es una solución clásica para la navegación en sitios responsivos. Cuando la ventana de visualización es suficientemente pequeña para garantizarlo, la navegación voluminosa se oculta "off-canvas" y solo se muestra cuando la activas nuevamente.
Scroll to top

Spanish (Español) translation by Eva Collados Pascual (you can also view the original English article)

El patrón off-canvas es una solución clásica para la navegación en sitios responsivos. Cuando la ventana de visualización es suficientemente pequeña para garantizarlo, la navegación voluminosa se oculta "off-canvas" y solo se muestra cuando la activas nuevamente.

Hoy vamos a crear una navegación off-canvas usando CSS para conseguir el cambio (sin requerir JavaScript) y nuestro buen amigo Grid para construir la estructura de la página. Aquí tienes la página de muestra completa de lo que vamos a estar intentando conseguir.

La Estructura de Página Básica

Empecemos construyendo una página básica; estamos buscando algo como esto:

Semantic page structure
Estructura semántica de la página

Esta es una estructura de página semántica típica; verás que todo se mantiene en una sola columna para los viewports pequeños, después los laterales reaparecen en las pantallas más grandes. El elemento <nav> está destacado en azul para aportar más claridad.

Aquí está la estructura de nuestro código: 

1
<header role="banner">
2
    <h1>Header</h1>
3
</header>
4
  
5
<nav id="nav" role="navigation">    
6
    <ul>
7
        <li>
8
            <a href="#">Item 1</a>
9
        </li>
10
        <li>
11
            <a href="#">Item 2</a>
12
        </li>
13
        <li>
14
            <a href="#">Item 3</a>
15
        </li>
16
    </ul>
17
</nav>
18
  
19
<section role="main">
20
    <article>
21
        <h2>Article</h2>
22
        <p>Curabitur orci lacus, auctor ut facilisis nec, ultricies quis nibh. Phasellus id diam sollicitudin, malesuada turpis id, gravida erat. Maecenas placerat elit vel hendrerit convallis. Sed in mauris ut justo vulputate viverra feugiat ac dui. Fusce feugiat arcu in vehicula vehicula. Donec varius justo at nulla aliquet volutpat.</p> 
23
        <p>Ut id rutrum eros. Nulla tristique, magna et mattis vulputate, mi eros suscipit turpis, nec bibendum turpis nunc feugiat sapien. Nunc arcu est, lacinia id diam quis, sagittis euismod neque. Nullam fringilla velit sed porta gravida. Proin eu vulputate libero. Ut a lacinia enim. Etiam venenatis mauris et orci tempor congue. Sed tempor eros et ultricies congue. Aenean sed efficitur orci. Nulla vel tempus mi.</p>
24
        <p>Ut cursus suscipit augue, id sagittis nibh faucibus eget. Etiam suscipit ipsum eu augue ultricies, at rhoncus mi faucibus. In et tellus vitae leo scelerisque fringilla nec at nunc.</p>
25
    </article>
26
</section>
27
  
28
<aside>
29
    <h3>Aside</h3>
30
</aside>
31
  
32
<footer>
33
    <h3>Footer</h3>
34
</footer>

Ahora, añadamos algunos estilos visuales y algunas reglas Grid.

Convirtiéndolo un poquito Griddy

Comienza envolviendo todos tus elementos estructurales en un elemento contenedor de algún tipo–éste será nuestro contenedor para Grid. Yo estoy usando <div class="container"></div>.

Ahora añade algunos estilos grid básicos:

1
.container {
2
  display: grid;
3
  grid-template-columns: 1fr;
4
  grid-gap: 10px;
5
}

Aquí estamos declarando que el contenedor debería ser display:grid;, que debería tener una sola columna de una unidad fraccionaria (no estrictamente necesario en este momento, pero lo hemos añadido para ser rigurosos) y que el espacio entre todos los elementos de la retícula debe ser 10px.

Después añade un par de estilos visuales para aclarar las cosas un poco más:

1
.container > * {
2
  color: #353535;
3
  font-size: 1.2em;
4
  line-height: 1.5;
5
  padding: 20px;
6
  background: #d0cfc5;
7
}
8
9
.container nav {
10
  background: #136fd2;
11
}
12
13
nav ul {
14
  list-style: none;
15
  margin: 0;
16
  padding: 0;
17
}
18
19
nav a {
20
  color: #d0cfc5
21
}
22
23
nav a:hover {
24
  text-decoration: none;
25
}

Hacerla Responsiva

Añadamos una media query, de forma que cuando la ventana o pantalla alcancen cierta medida (nosotros vamos a indicar 600px) la maquetación cambie.

1
@media only screen and (min-width: 600px) {
2
    
3
  /* grid */
4
  .container {
5
    grid-template-columns: repeat(4, 1fr);
6
  }
7
  
8
  /* specific item styles */
9
10
  .container header,
11
  .container nav,
12
  .container footer {
13
    grid-column: span 4;
14
  }
15
  .container section {
16
    grid-column: span 3;
17
  }
18
  
19
}

Así que ahora, en las pantallas grandes, la retícula cambia a grid-template-columns: repeat(4, 1fr);. Esto nos da como resultado cuatro columnas de igual anchura, así que después tendremos que indicar la anchura de cada uno de nuestros elementos estructurales. El header, nav y footer se extenderán todos 4 (a través de cuatro columnas) mientras que la section se extenderá a través de tres, dejando un espacio de una columna para el aside cuya anchura se adaptará automáticamente. 

Por último, algunos estilos para modificar el aspecto de la navegación: 

1
  /* nav styles */
2
  nav ul li {
3
    display: inline-block;
4
    padding: 0 20px 0 0;
5
  }

Esto es lo que tenemos hasta ahora:

Please accept marketing cookies to load this content.

Aventurarse Fuera del Lienzo (Off-Canvas)

Este es un ejemplo perfecto sobre como el posicionamiento a través de CSS puede funcionar todavía con elementos estructurales, incluso dentro de una Retícula declarada. Vamos a coger nuestra navegación, eliminarla del flujo del resto del documento y ubicarla fuera del lienzo. Los otros elementos de la retícula se situarán en su lugar perfectamente.

Empecemos con otra media query. Todavía tenemos nuestra query min-witdh, pero esta vez sólo queremos aplicar estilo a los elementos hasta una max-width. Hasta que nuestro alcanza ese mágico 600px en el que deseamos posicionar la navegación fuera del lienzo.

1
@media only screen and (max-width: 599px) {
2
  
3
    #nav {
4
        position: fixed; /* or choose `absolute` depending on desired behavior*/
5
        top: 0;
6
        bottom: 0;
7
        width: 300px;
8
        left: -340px;
9
        transition: left .3s ease-in-out;
10
    }
11
  
12
}

Le hemos asignado a la navegación una anchura fija, posicionándola a la izquierda lo suficiente como para ocultarla completamente. Hemos usado la posición fixed también, así que puedes usar además absolute dependiendo de si quieres que la navegación se deslice con la ventana o no.

También habrás advertido la regla transition, que tendrá efecto una vez creados alguno controles para realizar los cambios.

Alternar

Habiendo hecho desaparecer nuestra navegación, ahora necesitamos algunos controles para traerla de vuelta cuando la necesitemos. Añadamos un enlace para desencadenarla y otro para cerrarla nuevamente.

Añade esto en el header:

1
<a class="toggle open" href="#nav">open</a>

y esto a la navegación:

1
<a class="toggle close" href="#">close</a>
2
<!-- you might also want to use a “×” -->

No necesitamos que el enlace de apertura esté visible en las pantallas grandes, así que ocultamos los elementos con la clase .toggle dentro de nuestra media query min-width:

1
  .toggle {
2
      display: none;
3
    }

:target

Lo importante en los enlaces de arriba es la presencia de un "fragmento identificador" (el #nav en href). Estos identificadores los usan los navegadores para dirigirse directamente a elementos específicos en una página.  En este caso, estamos dirigiéndonos a cualquier elemento que contenga el id "nav", y una vez haya sido localizado le podemos aplicar estilo mediante la pseudo clase :target. ¡Sin necesidad de JavaScript!

Añade lo siguiente a nuestra media query max-width:

1
  #nav:target {
2
      left: 0;
3
    }

¡Esto es todo! Este es nuestro alternador.

Esto es lo que tenemos ahora:

Please accept marketing cookies to load this content.

Necesitarás echar un vistazo a la muestra de página completa para apreciar al completo lo que estamos haciendo.

Conclusión

¡Y ya lo tenemos! Hemos aplicado estilo de forma mínima de para no salirnos del camino, pero siéntete libre y dale exactamente la apariencia que deseas.

Podrías preferir un alternador con JavaScript, en lugar de usar :target, en cuyo caso tendrás todas las piezas en su sitio para que funcione igualmente.

¡Espero que hayas disfrutado de este pequeño ejercicio con la Retícula, manténte atento a lo que está por venir!

Recursos Útiles