Menu off-canvas responsive con Tailwind y Alpine

tailwindcss-1633184775.jpg
Solucionex
29
Oct 21

Ya os hemos hablado de TailwindCSS en otras ocasiones (aquí y aquí) y también de Alpine.js. Hoy vamos a maquetar un menú responsive off-canvas con estas dos herramientas de una manera muy sencilla.

Para empezar crearemos la estructura en HTML del nuestro menú. Simplemente un div que posicionaremos en la parte derecha de la pantalla y ocupará un ancho limitado, salvo en dispositivo móviles que abarcará todo el ancho de la pantalla. Para que el menú no esté visible añadimos las utilidad translate-x-full.

<div class="absolute top-0 right-0 w-full md:w-80 h-screen bg-white translate-x-full">
  <ul class="flex flex-col">
   <li><a href="#">Item 1</a></li>
   <li><a href="#">Item 2</a></li>
   <li><a href="#">Item 3</a></li>
   <li><a href="#">Item 4</a></li>
  </ul>
</div>

En el <body> de nuestro documento inicializaremos la variable open con la directiva de AlpineJS x-data. Como el menú no estará visible inicialmente le asignaremos el valor false.

x-data="{ open: false }"

Para continuar necesitamos un botón que abra y cierre el menú. También irá colocado en la esquina superior derecha, encima del menú

<button type=”button” class="absolute right-4 top-4 z-40" @click="open = !open"> Menu </button>

Con @click="open = !open" cambiamos el valor de la variable open, en función de si está abierto o cerrado.

Ahora retomaremos el código inicial del menú y le añadiremos las clases necesarias para que el menú aparezca al pulsar el botón.

:class="{'translate-x-0': open, 'translate-x-full': !open}”

Además le añadiremos las clases transform y duration-300 para que haga una transición suave desde la parte derecha de la pantalla hasta su posición. El código resultante:

<div class="absolute top-0 right-0 w-full md:w-80 h-screen bg-white translate-x-full transform duration-300"
:class="{'translate-x-0': open, 'translate-x-full': !open}”>
  <ul class="flex flex-col">
    <li><a href="#">Item 1</a></li>
    <li><a href="#">Item 2</a></li>
    <li><a href="#">Item 3</a></li>
    <li><a href="#">Item 4</a></li>
  </ul>
</div>