Ir al contenido principal

Tailwind max-*: el modificador inverso para media queries y container queries

Tailwind es mobile-first por defecto. La gran mayoría del trabajo usa los modificadores sm:, md:, lg:, xl: y 2xl: que aplican estilos desde un breakpoint hacia arriba. Pero hay casos en los que necesitas exactamente lo contrario: aplicar un estilo hasta un breakpoint y que desaparezca cuando la pantalla crece.

Para eso están los modificadores max-* (max-sm, max-md, max-lg, max-xl, max-2xl). Funcionan en Tailwind v3 y v4 con la misma sintaxis, y —lo importante— sirven tanto para media queries (responsive según viewport) como para container queries (responsive según el contenedor padre).

Cómo funcionan en media queries

max-sm:text-center aplica text-align: center solo cuando el viewport es menor a 640px. A partir de ahí desaparece. Es la inversa exacta de sm:text-center.

Modificador Aplica cuando viewport CSS equivalente max-sm: < 640px @media (width < 40rem) max-md: < 768px @media (width < 48rem) max-lg: < 1024px @media (width < 64rem) max-xl: < 1280px @media (width < 80rem) max-2xl: < 1536px @media (width < 96rem)

Combinándolos con los modificadores habituales

Aquí es donde max-* brilla de verdad: permite definir un rango entre dos breakpoints sin escribir CSS personalizado.

<!-- Solo aplica flex entre 768px y 1024px -->
<div class="md:max-lg:flex"></div>

El patrón breakpointMin:max-breakpointMax:utility se lee como "desde X hasta Y". Es la única forma limpia de targetear un rango concreto en Tailwind sin recurrir a clases CSS propias ni a breakpoints custom en config.

Ejemplos prácticos:

<!-- Visible solo en tablets (sm a md) -->
<div class="hidden sm:max-md:block"></div>
<!-- Padding mayor solo en desktop medio -->
<div class="lg:max-xl:p-8"></div>
<!-- Mensaje "rotar el dispositivo" solo en pantallas muy pequeñas -->
<p class="hidden max-sm:block">Mejor en horizontal.</p>

La misma sintaxis aplica a container queries

Las container queries son la otra cara del responsive moderno: en lugar de mirar el viewport global, miran el ancho del contenedor padre que tenga @container. Tailwind expone modificadores @sm, @md, @lg que se comportan igual que los responsive estándar pero contra el contenedor, no contra la ventana.

Y, igual que con media queries, existen sus versiones max:

<div class="@container">
  <div class="grid grid-cols-3 @max-md:grid-cols-1">
    <!-- 3 columnas por defecto;
         1 columna cuando el contenedor es menor a 448px -->
  </div>
</div>
Modificador Aplica cuando contenedor CSS equivalente @max-3xs: < 256px @container (width < 16rem) @max-2xs: < 288px @container (width < 18rem) @max-xs: < 320px @container (width < 20rem) @max-sm: < 384px @container (width < 24rem) @max-md: < 448px @container (width < 28rem) @max-lg: < 512px @container (width < 32rem)

Esto desbloquea componentes verdaderamente reutilizables. Un mismo card puede mostrar tres columnas cuando vive en una sidebar ancha y colapsar a una sola cuando vive en un slot estrecho, sin que el viewport global tenga nada que decir. La regla de diseño viaja con el componente, no con la página.

Caso práctico: hero que cambia de estructura solo en tablet

Imagina un hero que en móvil es vertical (texto arriba, imagen abajo), en tablet pasa a horizontal con la imagen a la derecha, y en desktop vuelve a ser vertical porque allí tienes espacio para una composición más grande con la imagen de fondo.

Antes de max-*, esto requería tres modificadores y a menudo revertir clases a mano. Con max-*:

<section class="flex flex-col sm:max-lg:flex-row lg:flex-col">
  ...
</section>

Una sola línea, intención clara: vertical por defecto, horizontal en el rango sm-lg, vertical otra vez de lg hacia arriba.

Cuándo NO usarlo

max-* es elegante pero no es siempre la respuesta. Si tu diseño es genuinamente mobile-first (móvil simple, desktop más rico), los modificadores estándar sm:/md:/lg: dejan el código más legible. max-* brilla cuando el diseño tiene reglas que se aplican por debajo de cierto tamaño: textos centrados solo en móvil, navegaciones colapsadas solo en tablet, fondos retirados solo en pantalla pequeña.

Como regla práctica: si te encuentras escribiendo lg:hidden para esconder algo solo en desktop, considera si max-lg:flex (mostrarlo solo bajo desktop) lee mejor para quien mantenga el código después.

Por qué importa que funcione en ambos contextos

Que max-* use la misma sintaxis en media queries y en container queries hace que el modelo mental sea uno solo: "aplica hasta X". No hay dos APIs que recordar según trabajes a nivel global o a nivel de componente. Es la coherencia que ha hecho que Tailwind escale como sistema y no como una colección de utilidades sueltas.

Para quien construye sitios donde conviven layouts globales (página) y componentes reutilizables (cards, sidebars, módulos repetidos), tener esa simetría entre max-* y @max-* es lo que permite mantener un único vocabulario mental sin saltar entre paradigmas.

Tailwind max-*: el modificador inverso para media queries y container queries