Grid
CSS Grid es un sistema de maquetación que te permite organizar elementos en una rejilla bidimensional, es decir, en filas y columnas, como si fuera una hoja de cálculo o un tablero. Grid te permite crear diseños web complejos de una manera mucho más sencilla y predecible que los métodos antiguos (como float o position).
La rejilla
Los elementos básicos de este nuevo esquema son los siguientes:
- Contenedor: es el elemento padre, en su interior estarán los elementos (ítems). Lo activas con display: grid;. Todas las reglas principales del diseño (cuántas columnas, qué tamaño tienen, el espacio entre ellas) se definen aquí.
- Ítem: Cada uno de los hijos(elementos) directos del contenedor. Tú decides cómo se colocan estos hijos dentro de la rejilla que has definido en el padre.
Cuando hablamos de grid, podemos hacer referencia a:
- Grid Lines (Líneas de la Rejilla): Las líneas horizontales y verticales que dividen la rejilla. Son como las líneas de una libreta de cuadros.
- Grid Tracks (Pistas): El espacio entre dos líneas de la rejilla. Básicamente, son tus columnas o filas.
- Grid Cell (Celda): El espacio donde se cruzan una fila y una columna. Es la unidad más pequeña de la rejilla.
- Grid Area (Área): Un espacio rectangular que puede ocupar una o más celdas.
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
Uno de los valores que podemos usar con la propiedad display es, inline-grid. Esto hará que dicho elemento se comporte como un elemento de línea (como si fuera un span o una img), pero con los siguientes extras:
- Ocupa solo el ancho necesario para su contenido.
- Permite que otros elementos se coloquen a su lado en la misma línea, si hay espacio disponible.
- A diferencia de un display: inline normal, sí puedes definirle un ancho (width) y un alto (height).
En resumen: display: inline-grid crea una rejilla que fluye con el contenido de la página, como si fuera una palabra más en un párrafo.
¿Cuándo usar display: grid y cuándo display: inline-grid?
- Usa display: grid para maquetar secciones grandes de tu página, como el layout principal, una galería de imágenes que ocupa todo el ancho de la sección o una lista de artículos.
- Usa display: inline-grid para componentes más pequeños que necesitan alinearse con otros elementos en la misma línea, como un grupo de botones, un pequeño widget de información o iconos que deben mantener una estructura de rejilla interna.
¿Qué es la unidad fr? La unidad fr (fracción) es una de las mejores cosas de Grid. Representa una fracción del espacio disponible en el contenedor. 1fr 1fr 1fr significa "divide el espacio en 3 partes iguales". Si usaras 2fr 1fr 1fr, la primera columna sería el doble de ancha que las otras dos.
repeat
La función repeat() en CSS Grid es una herramienta que nos va a permitir definir columnas y filas de manera más eficiente. En lugar de escribir múltiples valores repetitivos, puedes usar repeat() para simplificar tu código. Los valores que puede aceptar son variados y se adaptan a distintas necesidades de diseño.
Los valores que puede tener la función repeat():
Número de Repeticiones y Tamaño
La sintaxis más básica de repeat() incluye dos argumentos principales: el número de veces que se debe repetir un valor y el tamaño de esa repetición.
Un número explícito: Puedes especificar un número entero positivo para indicar cuántas veces se repetirá una pista (columna o fila).
.container {
display: grid;
grid-template-columns: repeat(3, 100px); /* Crea 3 columnas de 100px cada una */
}Tamaño de la pista: El segundo argumento define el tamaño de cada repetición. Puede ser cualquier unidad de longitud válida en CSS, como:
- Píxeles (px): Unidades fijas.
- Porcentajes (%): Relativos al contenedor.
- Unidades fraccionarias (fr): Distribuyen el espacio sobrante de manera proporcional.
- min-content: El tamaño mínimo del contenido de la celda.
- max-content: El tamaño máximo del contenido de la celda.
- auto: Se ajusta al contenido.
- La función minmax(): Permite definir un rango de tamaño, con un valor mínimo y uno máximo.
Palabras clave para la reproducción automática:
En lugar de un número fijo, puedes usar palabras clave que permiten que el número de pistas se ajuste automáticamente al espacio disponible en el contenedor. Esto es especialmente útil para diseños responsivos.
auto-fill
auto-fill: Rellena el contenedor con tantas pistas como sea posible, incluso si estas quedan vacías. Si el contenedor se ensancha, se agregarán más pistas para llenar el espacio, aunque no haya contenido para ellas.
.container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); /* Crea tantas columnas de al menos 150px como quepan */
}auto-fit
auto-fit: Funciona de manera similar a auto-fill, pero con una diferencia clave: si después de distribuir los elementos del grid quedan pistas vacías, estas se colapsan a cero. Esto hace que los elementos existentes se estiren para ocupar el espacio disponible. Es ideal cuando quieres que tus elementos se expandan para llenar el contenedor.
.container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); /* Las columnas se estirarán para ocupar el espacio sobrante */
}En resumen, la función repeat() te ofrece una forma concisa y potente de definir la estructura de tu rejilla, ya sea con un número fijo de pistas o con un sistema dinámico que se adapta al tamaño del contenedor.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ejemplo de auto-fill vs. auto-fit</title>
<link rel="stylesheet" href="2.repeat.css">
</head>
<body>
<h1>Ejemplo con <code>auto-fill</code></h1>
<p>Con <code>auto-fill</code>, el espacio vacío se reserva para nuevas columnas si el contenedor crece. Observa el
espacio en blanco al final si la ventana es ancha.</p>
<div class="grid-container auto-fill-example">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
<hr>
<h1>Ejemplo con <code>auto-fit</code></h1>
<p>Con <code>auto-fit</code>, las columnas existentes se estiran para ocupar el espacio disponible. No deja huecos.
</p>
<div class="grid-container auto-fit-example">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
<h1>Ejemplo con <code>flex y flex grow</code></h1>
<div class="flex-container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
</body>
</html>minmax
La función minmax() es una de las herramientas más potentes y útiles de CSS Grid para crear diseños flexibles y responsivos.
En pocas palabras, minmax(min, max) te permite definir un rango de tamaño para una fila o columna. Estableces un tamaño mínimo que nunca se debe violar y un tamaño máximo que no se debe superar.
La función siempre recibe dos argumentos:
- tamaño mínimo: El límite inferior. La columna o fila no puede ser más pequeña que este valor.
- tamaño máximo: El límite superior. La columna o fila puede crecer hasta este valor, pero no más.
¿Para qué sirve?
Su principal utilidad es crear componentes que son flexibles pero que al mismo tiempo tienen límites lógicos. Evita que tus elementos se encojan hasta ser ilegibles en pantallas pequeñas o que se estiren desproporcionadamente en pantallas muy grandes.
Los valores que puedes usar dentro de minmax() son los que ya conoces: px, %, fr, auto, etc.
Veamos un caso de uso clásico. Quieres un sidebar que sea flexible, pero que nunca se haga demasiado estrecho.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Layout Flexible con Grid y minmax()</title>
<link rel="stylesheet" href="1.minmax.css">
</head>
<body>
<div class="layout-container">
<aside class="sidebar">
<h2>Navegación</h2>
<ul>
<li>Inicio</li>
<li>Perfil</li>
<li>Mensajes</li>
<li>Estadísticas</li>
<li>Ajustes</li>
</ul>
</aside>
<main class="main-content">
<h1>Contenido Principal</h1>
<p>Este área de contenido principal se adapta al espacio sobrante. El sidebar a la izquierda es flexible,
pero nunca se encogerá más allá de los 200px gracias a la función <code>minmax()</code> de CSS Grid.</p>
<p>Prueba a redimensionar la ventana de tu navegador para ver el efecto. Notarás que el sidebar se encoge
hasta llegar a su límite, momento en el cual el navegador activará una barra de scroll horizontal si el
espacio total es menor, protegiendo así el diseño.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat.</p>
</main>
</div>
</body>
</html>¿Qué sucede aquí?
- sidebar (como mínimo 200px): La columna del sidebar nunca será más estrecha que 200px, protegiendo su contenido de ser aplastado en pantallas pequeñas.
- sidebar (como máximo (25%)): La columna del sidebar crecerá con el tamaño de la ventana, pero ocupará como máximo el 25% del ancho total del contenedor, evitando que sea demasiado ancha en pantallas grandes.
- contenido principal, segunda columna (1fr): Cuando el espacio que le correspondería a 1fr sea menor de 250px, la columna dejará de encogerse y se quedará fija en 250px, protegiendo su contenido.
Otro de los ejemplos clave y potente de la función minmax() es cuando creamos galerías responsive. Combinado con repeat() y auto-fit (o auto-fill), te permite crear una lista de elementos que se ajusta automáticamente.
.gallery {
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}¿Qué hace?
- repeat(auto-fit, ...): "Quiero que crees tantas columnas como quepan en el espacio disponible." Con autofit, si el espacio se reduce, las columnas que no quepan pasarán a la siguiente fila.
- minmax(300px, 1fr): "Cada una de estas columnas debe tener un tamaño mínimo de 300px. Si después de colocar todas las columnas de 300px te sobra espacio, repártelo equitativamente (1fr) entre todas las columnas para que ocupen todo el ancho."
El resultado es un diseño perfectamente fluido:
- En una pantalla ancha, podrías tener 4 o 5 columnas.
- A medida que la pantalla se hace más pequeña, el número de columnas disminuirá automáticamente a 3, luego a 2 y finalmente a 1, sin necesidad de usar media queries.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Galería con Grid y minmax()</title>
<link rel="stylesheet" href="minmax.css">
</head>
<body>
<div class="container">
<h1>Galería de Paisajes Urbanos</h1>
<div class="gallery">
<div class="gallery-item">
<img src="https://images.pexels.com/photos/21014/pexels-photo.jpg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
alt="Ciudad 1">
</div>
<div class="gallery-item">
<img src="https://images.unsplash.com/photo-1519892300165-cb5542fb47c7?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzNjUyOXwwfDF8c2VhcmNofDEyfHxjaXR5fGVufDB8fHx8MTYxNjU4NDk4Mw&ixlib=rb-1.2.1&q=80&w=400"
alt="Ciudad 2">
</div>
<div class="gallery-item">
<img src="https://images.unsplash.com/photo-1477959858617-67f85cf4f1df?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzNjUyOXwwfDF8c2VhcmNofDN8fHxjaXR5fGVufDB8fHx8MTYxNjU4NDk4Mw&ixlib=rb-1.2.1&q=80&w=400"
alt="Ciudad 3">
</div>
<div class="gallery-item">
<img src="https://images.unsplash.com/photo-1505761671935-60b3a7427bad?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzNjUyOXwwfDF8c2VhcmNofDV8fHx0cmF2ZWx8ZW58MHx8fHwxNjE2NTg1MDQ0&ixlib=rb-1.2.1&q=80&w=400"
alt="Ciudad 4">
</div>
<div class="gallery-item">
<img src="https://images.unsplash.com/photo-1480714378408-67cf0d13bc1b?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzNjUyOXwwfDF8c2VhcmNofDF8fHxjaXR5fGVufDB8fHx8MTYxNjU4NDk4Mw&ixlib=rb-1.2.1&q=80&w=400"
alt="Ciudad 5">
</div>
<div class="gallery-item">
<img src="https://images.unsplash.com/photo-1513407030348-c983a97b98d8?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzNjUyOXwwfDF8c2VhcmNofDEwfHxjaXR5fGVufDB8fHx8MTYxNjU4NDk4Mw&ixlib=rb-1.2.1&q=80&w=400"
alt="Ciudad 6">
</div>
<div class="gallery-item">
<img src="https://images.unsplash.com/photo-1444723121867-7a241cacace9?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzNjUyOXwwfDF8c2VhcmNofDEzfHxjaXR5fGVufDB8fHx8MTYxNjU4NDk4Mw&ixlib=rb-1.2.1&q=80&w=400"
alt="Ciudad 7">
</div>
<div class="gallery-item">
<img src="https://images.unsplash.com/photo-1449824913935-59a10b8d2000?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzNjUyOXwwfDF8c2VhcmNofDE1fHxjaXR5fGVufDB8fHx8MTYxNjU4NDk4Mw&ixlib=rb-1.2.1&q=80&w=400"
alt="Ciudad 8">
</div>
</div>
</div>
</body>
</html>