Hacer que el contenedor de cuadrícula llene columnas, no filas

Resuelto Glen Pierce asked hace 7 años • 0 respuestas

Quiero que mi cuadrícula se complete verticalmente así:

1 4 7 
2 5 8
3 6 9
... arbitrary number of additional rows.

En cambio, se completa horizontalmente así:

1 2 3
4 5 6
7 8 9

Quiero especificar el número de columnas de mi cuadrícula, no el número de filas.

Así es como se ve mi div con estilo CSS en línea:

<div style="display:grid; grid-template-columns:1fr 1fr 1fr;">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
</div>
Expandir fragmento

Es importante que mi cuadrícula tenga 3 columnas de ancho, pero quiero que los elementos se completen por columna, no por fila. ¿Es esto posible en CSS Grid? Leí esto https://css-tricks.com/snippets/css/complete-guide-grid/ pero no vi nada sobre el orden.

CSS Flexbox tiene flex-direction, ¿no existe un atributo como ese para CSS Grid?

Glen Pierce avatar May 21 '17 09:05 Glen Pierce
Aceptado

Para una cuadrícula que fluye verticalmente y que crea nuevas columnas según sea necesario, y las filas no están definidas, considere usar el diseño de varias columnas CSS ( ejemplo ). CSS Grid Layout (al menos la implementación actual - Nivel 1 ) no puede realizar esta tarea. Aquí está el problema:

En CSS Grid Layout, existe una relación inversa entre las propiedades grid-auto-flowy grid-template-rows/ grid-template-columns.

Más específicamente, con grid-auto-flow: row(la configuración predeterminada) y grid-template-columnsambos definidos, los elementos de la cuadrícula fluyen bien en dirección horizontal, creando automáticamente nuevas filas según sea necesario. Este concepto se ilustra en el código de la pregunta.

#container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-auto-flow: row;
}
<div id="container">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
</div>
Expandir fragmento

Sin embargo, al cambiar a grid-template-rows, los elementos de la cuadrícula se apilan en una sola columna.

Mostrar fragmento de código

No hay creación automática de columnas con grid-auto-flow: rowy grid-template-rows. grid-template-columnsdebe definirse (de ahí la relación inversa con grid-auto-flow).

Mostrar fragmento de código

El mismo comportamiento es cierto en el escenario inverso.

Con grid-auto-flow: columny grid-template-rowsambos definidos, los elementos de la cuadrícula fluyen bien en dirección vertical, creando automáticamente nuevas columnas según sea necesario.

#container {
  display: grid;
  grid-template-rows: 1fr 1fr 1fr;
  grid-auto-flow: column;
}
<div id="container">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
</div>
Expandir fragmento

Sin embargo, al cambiar a grid-template-columns, los elementos de la cuadrícula se apilan en una sola fila. (Este es el problema sobre el que pregunta la mayoría de la gente, incluso en esta pregunta).

Mostrar fragmento de código

No hay creación automática de filas. Eso requiere grid-template-rowsser definido. (Esta es la solución que se proporciona con mayor frecuencia, pero generalmente se rechaza porque los diseños tienen un número variable de filas).

Mostrar fragmento de código

Por lo tanto, considere una solución de diseño de varias columnas , como se sugirió anteriormente.

Referencia de especificaciones: 7.7. Colocación automática: la grid-auto-flowpropiedad

Michael Benjamin avatar May 21 '2017 02:05 Michael Benjamin

Otra opción es eliminar CSS Grid y usar CSS Columns, que hace exactamente lo que usted pide y también tiene un soporte de navegador mucho mejor.

.csscolumn {
  -webkit-column-count: 3;  /* Chrome, Safari, Opera */
  -moz-column-count: 3;     /* Firefox */
  column-count: 3;
}

/* styling for this demo */
.csscolumn {
  width: 50%;
}
.csscolumn + .csscolumn {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid;
}
<div class="csscolumn">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
</div>

<div class="csscolumn">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
</div>

<div class="csscolumn">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
  <div>10</div>
</div>
Expandir fragmento

Asons avatar May 21 '2017 17:05 Asons

El método más simple que he visto es el siguiente:

.grid {
	display: grid;
	grid-auto-flow: column;
	grid-gap: 1px;
	grid-template-columns: repeat(3, 1fr); 
	grid-template-rows: repeat(5, auto);    
}
<div class="grid">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
<div>9</div>
<div>10</div>
<div>11</div>
<div>12</div>
<div>13</div>
</div>
Expandir fragmento

RayYates avatar Jan 09 '2019 20:01 RayYates

Más como ejercicio técnico que como solución práctica, puedes conseguir de alguna manera tu resultado utilizando estilos específicos dependiendo del número de elementos.

Vamos a ver cómo funciona:

.item:first-child:nth-last-child(n+4):nth-last-child(-n + 6) ~ .item:nth-child(n+3)

el primer seleccionador

.item:first-child:nth-last-child(n+4):nth-last-child(-n + 6)

está activo si nuestra lista tiene entre 4 y 6 elementos. En este caso, algún artículo estará tanto en la primera condición como en la segunda.

En este caso, queremos que haya 2 elementos en la primera columna. apunte a los elementos restantes (desde el tercero en adelante) con

~ .item:nth-child(n+3)

y colóquelos en la segunda columna. Una regla similar, ahora para el día 5 en adelante.

~ .item:nth-child(n+5)

coloca los demás elementos en la tercera columna. Estas 2 reglas tienen la misma prioridad y apuntan a los últimos elementos, por lo que es fundamental que aparezcan en este orden.

Necesitamos repetir reglas similares hasta la cantidad máxima de elementos que puedan estar presentes (probablemente un trabajo para un preprocesador)

var elements = 5;

function add () {
    var ctn = document.getElementById("container");
    var ele = document.createElement("div");
    elements ++;
    ele.innerHTML = elements;
    ele.className = "item";
    ctn.appendChild (ele);
}
#container {
  width: 90%;
  border: solid 1px red;
  display: grid;
  grid-template-rows: 33% 33% 33%;
  grid-auto-flow: column dense;
}

.item {
  width: 90%;
  height: 80px;
  background-color: lightgreen;
  margin: 10px;
  grid-column: 1;
}

.item:first-child:nth-last-child(n+4):nth-last-child(-n + 6) ~ .item:nth-child(n+3) {
  background-color: yellow;
  grid-column: 2;
}

.item:first-child:nth-last-child(n+4):nth-last-child(-n + 6) ~ .item:nth-child(n+5) {
  background-color: tomato;
  grid-column: 3;
}

.item:first-child:nth-last-child(n+7):nth-last-child(-n + 9) ~ .item:nth-child(n+4) {
  background-color: burlywood;
  grid-column: 2;
}

.item:first-child:nth-last-child(n+7):nth-last-child(-n + 9) ~ .item:nth-child(n+7) {
  background-color: blueviolet;
  grid-column: 3;
}

.item:first-child:nth-last-child(n+10):nth-last-child(-n + 12) ~ .item:nth-child(n+5) {
  background-color: darkcyan;
  grid-column: 2;
}

.item:first-child:nth-last-child(n+10):nth-last-child(-n + 12) ~ .item:nth-child(n+9) {
  background-color: chartreuse;
  grid-column: 3;
}

.item:first-child:nth-last-child(n+13):nth-last-child(-n + 15) ~ .item:nth-child(n+6) {
  background-color: yellow;
  grid-column: 2;
}

.item:first-child:nth-last-child(n+13):nth-last-child(-n + 15) ~ .item:nth-child(n+11) {
  background-color: tomato;
  grid-column: 3;
}
<button onclick="add()">Add</button>
<div id="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>
Expandir fragmento

vals avatar May 21 '2017 06:05 vals