En esta página

Flexbox y Grid con Tailwind

14 min lectura TextoCap. 2 — Layout y responsive

Flexbox y Grid en Tailwind

Tailwind convierte las poderosas APIs de CSS Flexbox y Grid en utilidades simples y legibles. En lugar de escribir display: flex; align-items: center; justify-content: space-between;, escribes flex items-center justify-between. El resultado es el mismo, pero la velocidad de desarrollo es mucho mayor.

Flexbox

Activar Flexbox

<div class="flex">...</div>          <!-- display: flex -->
<div class="inline-flex">...</div>   <!-- display: inline-flex -->

Dirección del eje principal

<div class="flex flex-row">...</div>         <!-- Horizontal (default) -->
<div class="flex flex-row-reverse">...</div> <!-- Horizontal al revés -->
<div class="flex flex-col">...</div>         <!-- Vertical -->
<div class="flex flex-col-reverse">...</div> <!-- Vertical al revés -->

Alineación en el eje cruzado (align-items)

<div class="flex items-start">...</div>    <!-- align-items: flex-start -->
<div class="flex items-center">...</div>   <!-- align-items: center -->
<div class="flex items-end">...</div>      <!-- align-items: flex-end -->
<div class="flex items-stretch">...</div>  <!-- align-items: stretch (default) -->
<div class="flex items-baseline">...</div> <!-- align-items: baseline -->

Distribución en el eje principal (justify-content)

<div class="flex justify-start">...</div>    <!-- flex-start (default) -->
<div class="flex justify-center">...</div>   <!-- center -->
<div class="flex justify-end">...</div>      <!-- flex-end -->
<div class="flex justify-between">...</div>  <!-- space-between -->
<div class="flex justify-around">...</div>   <!-- space-around -->
<div class="flex justify-evenly">...</div>   <!-- space-evenly -->

Gap (espacio entre hijos)

<div class="flex gap-4">...</div>    <!-- gap: 1rem en ambos ejes -->
<div class="flex gap-x-6 gap-y-3">...</div> <!-- horizontal y vertical diferentes -->

El gap es la forma moderna de espaciar elementos flex, mucho más limpia que usar margin-right en cada hijo.

Flex grow, shrink y basis

<!-- flex-1: el elemento crece para ocupar el espacio disponible -->
<div class="flex">
  <div class="flex-none w-64">Sidebar fijo de 16rem</div>
  <div class="flex-1">Contenido principal que ocupa el resto</div>
</div>

<!-- flex-auto: crece y encoge, respeta el tamaño natural -->
<nav class="flex gap-2">
  <a href="/" class="flex-auto text-center py-2">Inicio</a>
  <a href="/cursos" class="flex-auto text-center py-2">Cursos</a>
  <a href="/blog" class="flex-auto text-center py-2">Blog</a>
</nav>

<!-- Controlar grow y shrink individualmente -->
<div class="flex">
  <div class="grow">Crece</div>
  <div class="shrink-0">No encoge (evita overflow)</div>
</div>

Wrapping

<!-- flex-wrap: los hijos se pueden mover a la siguiente línea -->
<div class="flex flex-wrap gap-3">
  <span class="bg-blue-100 text-blue-800 px-3 py-1 rounded-full text-sm">JavaScript</span>
  <span class="bg-green-100 text-green-800 px-3 py-1 rounded-full text-sm">TypeScript</span>
  <span class="bg-purple-100 text-purple-800 px-3 py-1 rounded-full text-sm">Angular</span>
  <span class="bg-yellow-100 text-yellow-800 px-3 py-1 rounded-full text-sm">React</span>
  <span class="bg-red-100 text-red-800 px-3 py-1 rounded-full text-sm">Vue</span>
</div>

Alineación individual con self

<div class="flex items-center h-24">
  <div class="self-start">Arriba</div>
  <div class="self-center">Centro (heredado del padre)</div>
  <div class="self-end">Abajo</div>
  <div class="self-stretch">Ocupa toda la altura</div>
</div>

Ejemplo práctico: navbar completa

<header class="sticky top-0 z-50 bg-white/80 backdrop-blur-md border-b border-gray-100">
  <nav class="flex items-center justify-between px-6 py-4 max-w-7xl mx-auto">

    <!-- Logo -->
    <a href="/" class="flex items-center gap-2 font-bold text-xl text-gray-900">
      <svg class="w-7 h-7 text-blue-600" viewBox="0 0 24 24" fill="currentColor">
        <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/>
      </svg>
      MiApp
    </a>

    <!-- Links centrales -->
    <ul class="hidden md:flex items-center gap-6">
      <li><a href="/cursos" class="text-gray-600 hover:text-gray-900 font-medium transition-colors">Cursos</a></li>
      <li><a href="/rutas" class="text-gray-600 hover:text-gray-900 font-medium transition-colors">Rutas</a></li>
      <li><a href="/blog" class="text-gray-600 hover:text-gray-900 font-medium transition-colors">Blog</a></li>
    </ul>

    <!-- Acciones -->
    <div class="flex items-center gap-3">
      <a href="/login" class="text-gray-600 hover:text-gray-900 font-medium">Entrar</a>
      <a
        href="/registro"
        class="bg-blue-600 hover:bg-blue-700 text-white font-semibold
               px-4 py-2 rounded-lg transition-colors"
      >
        Empezar gratis
      </a>
    </div>
  </nav>
</header>

CSS Grid

Activar Grid

<div class="grid">...</div>         <!-- display: grid -->
<div class="inline-grid">...</div>  <!-- display: inline-grid -->

Columnas con grid-cols-*

<div class="grid grid-cols-1">...</div>   <!-- 1 columna -->
<div class="grid grid-cols-2">...</div>   <!-- 2 columnas iguales -->
<div class="grid grid-cols-3">...</div>   <!-- 3 columnas iguales -->
<div class="grid grid-cols-4">...</div>   <!-- 4 columnas iguales -->
<div class="grid grid-cols-12">...</div>  <!-- 12 columnas (grid de sistema) -->

<!-- Columnas con valor arbitrario -->
<div class="grid grid-cols-[250px_1fr]">
  <!-- Sidebar de 250px + contenido flexible -->
</div>

<div class="grid grid-cols-[repeat(auto-fill,minmax(280px,1fr))]">
  <!-- Grid auto-responsive sin media queries -->
</div>

Span de columnas y filas

<div class="grid grid-cols-4 gap-4">
  <!-- Ocupa 2 columnas -->
  <div class="col-span-2 bg-blue-100 p-4">Ancho doble</div>
  <div class="bg-green-100 p-4">Normal</div>
  <div class="bg-green-100 p-4">Normal</div>

  <!-- Ocupa todas las columnas -->
  <div class="col-span-full bg-purple-100 p-4">Ancho completo</div>
</div>

<!-- Grid con filas explícitas -->
<div class="grid grid-cols-3 grid-rows-2 gap-4 h-64">
  <div class="row-span-2 bg-blue-200 rounded">Ocupa 2 filas</div>
  <div class="bg-green-200 rounded">1x1</div>
  <div class="bg-yellow-200 rounded">1x1</div>
  <div class="col-span-2 bg-red-200 rounded">Ocupa 2 columnas</div>
</div>

Gap en Grid

<div class="grid grid-cols-3 gap-4">...</div>       <!-- gap uniforme -->
<div class="grid grid-cols-3 gap-x-8 gap-y-4">...</div> <!-- horizontal y vertical -->

Colocación automática con auto-rows y auto-cols

<!-- Todas las filas auto-generadas tendrán 200px de alto -->
<div class="grid grid-cols-3 auto-rows-[200px] gap-4">
  <div class="bg-blue-200">...</div>
  <div class="bg-green-200">...</div>
  <!-- Más elementos que crean nuevas filas automáticamente -->
</div>

<!-- auto-rows con minmax para filas que crecen -->
<div class="grid grid-cols-2 auto-rows-[minmax(100px,auto)] gap-4">
  ...
</div>

Colocación explícita con col-start y row-start

<div class="grid grid-cols-4 grid-rows-3 gap-4">
  <!-- Empieza en columna 2, ocupa 2 columnas -->
  <div class="col-start-2 col-span-2 row-start-1 bg-blue-200 p-4">
    Centrado en el grid
  </div>

  <!-- Esquina inferior derecha -->
  <div class="col-start-4 row-start-3 bg-red-200 p-4">
    Posición explícita
  </div>
</div>

Ejemplo práctico: layout de bento

El "bento grid" es uno de los patrones de diseño más populares actualmente. Tailwind lo hace muy sencillo:

<section class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 auto-rows-[200px] gap-4 p-6">

  <!-- Tarjeta grande — ocupa 2x2 -->
  <div
    class="sm:col-span-2 sm:row-span-2 bg-gradient-to-br from-blue-500 to-purple-600
           rounded-3xl p-8 text-white flex flex-col justify-between"
  >
    <h2 class="text-3xl font-bold">Aprende a tu ritmo</h2>
    <p class="text-blue-100">Más de 100 lecciones disponibles</p>
  </div>

  <!-- Tarjetas pequeñas -->
  <div class="bg-amber-400 rounded-3xl p-6 flex flex-col justify-between">
    <span class="text-4xl">⚡</span>
    <p class="font-semibold text-amber-900">Actualizaciones semanales</p>
  </div>

  <div class="bg-pink-500 rounded-3xl p-6 flex flex-col justify-between">
    <span class="text-4xl">🎯</span>
    <p class="font-semibold text-white">Proyectos reales</p>
  </div>

  <!-- Tarjeta ancha en la tercera fila -->
  <div
    class="sm:col-span-2 bg-gray-900 rounded-3xl p-6 flex items-center gap-4"
  >
    <div class="text-5xl">👥</div>
    <div>
      <p class="text-white font-bold text-xl">+5,000 estudiantes</p>
      <p class="text-gray-400 text-sm">Comunidad activa</p>
    </div>
  </div>
</section>

Ejemplo práctico: dashboard con sidebar

<div class="grid grid-cols-[240px_1fr] min-h-screen">

  <!-- Sidebar -->
  <aside class="bg-gray-900 text-white p-6 flex flex-col gap-2">
    <h1 class="text-xl font-bold mb-6 px-3">Dashboard</h1>
    <a href="#" class="flex items-center gap-3 px-3 py-2 rounded-lg bg-white/10">
      <span>📊</span> Resumen
    </a>
    <a href="#" class="flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-white/10">
      <span>📚</span> Cursos
    </a>
    <a href="#" class="flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-white/10">
      <span>⚙️</span> Configuración
    </a>
  </aside>

  <!-- Contenido principal -->
  <main class="bg-gray-50 p-8">
    <h2 class="text-2xl font-bold text-gray-900 mb-6">Bienvenido de vuelta</h2>

    <!-- Stats grid dentro del main -->
    <div class="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4">
      <div class="bg-white rounded-xl p-6 shadow-sm">
        <p class="text-sm text-gray-500">Cursos activos</p>
        <p class="text-3xl font-bold text-gray-900 mt-1">3</p>
      </div>
      <!-- ... más stats -->
    </div>
  </main>
</div>

Flexbox y Grid juntos

Los mejores layouts combinan Flex y Grid según la necesidad de cada nivel:

<!-- Grid para el layout macro de la página -->
<div class="grid grid-cols-[1fr_300px] gap-8 max-w-6xl mx-auto px-6 py-12">

  <!-- Contenido principal (Grid de artículos) -->
  <main class="grid gap-6 auto-rows-min">
    <article class="flex gap-4 bg-white rounded-xl p-6 shadow-sm">
      <img src="thumb.jpg" alt="" class="w-16 h-16 rounded-lg object-cover flex-none" />
      <!-- Flex para el contenido interno del artículo -->
      <div class="flex flex-col justify-between min-w-0">
        <h2 class="font-semibold text-gray-900 truncate">Título del artículo</h2>
        <div class="flex items-center gap-2 text-sm text-gray-500 mt-auto">
          <span>12 min</span>
          <span>•</span>
          <span>Intermedio</span>
        </div>
      </div>
    </article>
  </main>

  <!-- Sidebar (Flex para su contenido interno) -->
  <aside class="flex flex-col gap-6">
    <div class="bg-white rounded-xl p-6 shadow-sm">
      <h3 class="font-semibold mb-4">Cursos populares</h3>
      <!-- ... -->
    </div>
  </aside>
</div>

Resumen

Flexbox en Tailwind: flex, flex-col, items-center, justify-between, gap-4, flex-1, flex-none, flex-wrap. Grid en Tailwind: grid, grid-cols-3, gap-4, col-span-2, col-span-full, auto-rows-[200px]. La combinación de ambos sistemas te permite construir layouts complejos y responsivos sin escribir una sola línea de CSS.

flex-1 vs grow vs flex-auto
flex-1 (flex: 1 1 0%) distribuye el espacio disponible ignorando el tamaño base del elemento. flex-auto (flex: 1 1 auto) lo distribuye respetando el tamaño natural. Para layouts donde quieres que todos los hijos tengan el mismo ancho, usa flex-1.
Cuándo usar Flex vs Grid
Usa Flexbox para distribución en una sola dimensión (filas O columnas): navbars, botones con iconos, listas horizontales. Usa Grid para distribución en dos dimensiones (filas Y columnas): layouts de página, galerías, dashboards. Puedes anidar ambos.
<!-- Barra de navegación con Flexbox -->
<nav class="flex items-center justify-between px-6 py-4 bg-white shadow-sm">
  <a href="/" class="font-bold text-xl text-gray-900">Logo</a>

  <!-- Links de navegación -->
  <ul class="flex items-center gap-8">
    <li><a href="/cursos" class="text-gray-600 hover:text-gray-900">Cursos</a></li>
    <li><a href="/blog" class="text-gray-600 hover:text-gray-900">Blog</a></li>
    <li><a href="/precios" class="text-gray-600 hover:text-gray-900">Precios</a></li>
  </ul>

  <!-- CTA -->
  <a
    href="/registro"
    class="bg-blue-600 text-white px-4 py-2 rounded-lg
           font-medium hover:bg-blue-700 transition-colors"
  >
    Empezar gratis
  </a>
</nav>