CSS Grid: escribiendo un diseño de revista de 20 líneas receptivo


Recientemente, trabajé en una implementación moderna de un blog roll (una lista de blogs externos útiles / interesantes). La idea era proporcionar a los lectores una selección de las últimas publicaciones en estos blogs, empaquetados en el diseño de una revista, en lugar de una lista seca de enlaces en la barra lateral.

La parte más fácil de la tarea es obtener una lista de publicaciones y sus extractos (extracto - texto introductorio antes del kat) de nuestros canales RSS favoritos. Para hacer esto, utilizamos el complemento WordPress de Feedzy lite , que puede agregar varias fuentes en una lista, ordenadas por tiempo, la solución ideal en nuestro caso. La parte difícil es hacer que todo sea hermoso.

La interfaz de lista estándar del complemento probablemente no tenga sabor, por lo que quería diseñarla como el sitio web de un periódico o revista con una mezcla de bloques "seleccionados" grandes y pequeños.

¡Parece la ocasión perfecta para usar CSS Grid! Cree un diseño de cuadrícula para diferentes diseños, por ejemplo, uno de cinco columnas y uno de tres columnas, y luego cambie entre ellos utilizando consultas de medios en diferentes tamaños de pantalla. ¿Derecha? Pero, ¿realmente necesitamos estas consultas de medios y todos estos problemas para definir los puntos de control, si solo puede usar el parámetro Grid auto-fit, que será la cuadrícula adaptativa para nosotros?

Esta idea me pareció tentadora, pero cuando comencé a agregar elementos que abarcaban varias columnas de la cuadrícula (se extiende), la cuadrícula comenzó a arrastrarse fuera de la página en pantallas estrechas. Las consultas de los medios parecían la única solución. ¡Pero encontré algo mejor!

Después de estudiar varios artículos sobre CSS Grid, descubrí que se dividen principalmente en dos tipos:

  1. Cómo crear un diseño interesante con tramos, pero con un número determinado de columnas.
  2. Cómo crear un diseño adaptativo en una cuadrícula, pero con columnas del mismo ancho (es decir, sin tramos).

Quiero que la cuadrícula implemente tanto esto como aquello: un diseño totalmente adaptable que utiliza elementos de columnas múltiples de tamaño adaptativo.

Lo bueno es que tan pronto como comienzas a comprender las limitaciones de las cuadrículas adaptativas y por qué y cuándo los tramos rompen la adaptabilidad, es fácil crear un diseño de revista con docenas de líneas de código y una consulta de medios (o incluso sin ellas si quieres limitar la variedad de tramos).

Aquí hay una comparación clara del complemento RSS del cuadro y el resultado de nuestro trabajo (clicable):


Este es un diseño de revista totalmente adaptable con bloques de colores "seleccionados" que se adaptan dinámicamente al diseño en función del número de columnas. La página muestra aproximadamente 50 publicaciones, pero el código de diseño no depende de la cantidad de elementos. Puede aumentar fácilmente el número de publicaciones a 100 en la configuración del complemento, y el diseño seguirá siendo interesante hasta el final.

Todo esto se logra exclusivamente a través de CSS y utilizando solo una consulta de medios para mostrar contenido en una columna en las pantallas más estrechas (menos de 460 píxeles).

Lo que es más increíble, todo el diseño tomó solo 21 líneas de CSS (sin contar los estilos generales del sitio). Sin embargo, para lograr tal flexibilidad con tan poco código, tuve que sumergirme en las profundidades más oscuras de la cuadrícula CSS y aprender a sortear algunas de sus limitaciones.

El código en el que descansa todo el diseño es increíblemente corto, y todo gracias al esplendor de CSS Grid:

.archive {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  grid-gap: 32px;
  grid-auto-flow: dense;
}

/*    */
.article:nth-child(31n + 1) {
  grid-column: 1 / -1;
}
.article:nth-child(16n + 2) {
  grid-column: -3 / -1;
}
.article:nth-child(16n + 10) {
  grid-column: 1 / -2;
}

/*     */
@media (max-width: 459px) {
  .archive {
    display: flex;
    flex-direction: column;
  }
}

La técnica descrita en este artículo se puede usar de forma segura para estilizar cualquier contenido generado dinámicamente, ya sea el resultado del widget de publicaciones recientes, páginas de archivo o resultados de búsqueda.

Crear malla adaptativa


Creé 17 elementos para mostrar la diversidad del contenido futuro: titulares, imágenes y extractos, y lo envolví en <div></div>

<div class="archive">
  <article class="article">
    <!--  -->
  </article>

  <!--  16  -->

</div>

El código para convertir estos elementos en una cuadrícula adaptativa es especialmente compacto:

.archive {
  /*     - */
  display: grid;
  /*        ,       180 . */
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  /*     */
  grid-gap: 1em;
}

→ Demostración en CodePen

Observe cómo la altura de la línea se ajusta automáticamente al bloque de contenido más alto de la línea. Si cambia el ancho en la demostración desde el enlace de arriba, verá que los elementos aumentan y disminuyen automáticamente y el número de columnas cambia de 1 a 5, respectivamente.

Aquí en acción, vemos la magia de CSS Grid llamadaauto-fit. Esta palabra clave funciona junto con la funciónminmax()aplicada agrid-template-columns.

Cómo funciona


El diseño de cinco columnas en sí se puede obtener así:

.archive {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
}

Sin embargo, esto crea un diseño de cinco columnas que se estira y contrae en diferentes anchos de pantalla, pero siempre permanece en cinco columnas, lo que conduce a columnas terriblemente estrechas en pantallas pequeñas. Lo primero que viene a la mente es escribir un montón de consultas de medios y redefinir una cuadrícula con un número diferente de columnas. Eso funcionaría, pero la palabra clave lo auto-fithace todo automáticamente.

Para auto-fitusar la función como la necesitamos minmax(). Por lo tanto, le decimos al navegador cuánto puede comprimir las columnas y cuánto estirar. Cuando se alcanza uno de los límites, el número de columnas aumenta o disminuye, respectivamente.

.archive {
  grid-template-columns: repeat (auto-fit, minmax(180px, 1fr));
}

En este ejemplo, el navegador intentará acomodar tantas columnas de hasta 180 píxeles de ancho. Si hay espacio en exceso, todas las columnas se expandirán, dividiéndolas entre ellas por igual. Esto es lo que dicta el significado 1fr: hacer que los tamaños de columna sean fracciones iguales ( acciones fr ) del ancho disponible.

Si estira la ventana del navegador, todas las columnas crecerán igualmente con el aumento de espacio libre. Tan pronto como el nuevo espacio alcance los 180 píxeles, aparecerá una nueva columna en su lugar. Y si reduce la ventana del navegador, todo sucede al revés, ajustando perfectamente la cuadrícula hasta que se convierta en un diseño de una sola columna. ¡Magia!

→ Video de demostración

Y toda esta adaptabilidad gracias a una línea de código. Bien genial?

Creación de tramos con "autoflow: denso"


Entonces, en este momento ya tenemos una cuadrícula adaptativa, eso es solo todos sus elementos: el mismo ancho. El diseño de un periódico o revista implica la presencia de bloques seleccionados, en este contexto, aquellos que cubrirían dos, tres o incluso todas las columnas disponibles.

Para crear tramos de varias columnas, podemos usar la propiedad grid-column: spanen aquellos elementos que deberían ocupar más espacio. Supongamos que queremos que el tercer elemento de la lista tenga dos columnas de ancho:

.article:nth-child(3) {
  grid-column: span 2;
}

Sin embargo, después de agregar tramos, pueden aparecer muchos problemas. En primer lugar, pueden formarse agujeros en la cuadrícula en aquellos casos en que el elemento ancho no cabe en su línea y lo auto-fittransfiere a lo siguiente:


Esto se soluciona fácilmente agregando una propiedad grid-auto-flow: densea la cuadrícula. Debido a esta propiedad, el navegador comprende que los agujeros deben rellenarse con otros elementos. Esto crea un flujo alrededor de los elementos más anchos más estrechos:


Tenga en cuenta: el orden de los elementos está roto, ahora el cuarto elemento está delante del tercero. Hasta donde yo sé, esto no puede pasarse por alto, esta es una de las limitaciones de CSS Grid que debe aceptarse.

Formas de identificar tramos


Hay varias formas de especificar el número de columnas que debe ocupar un elemento. Es más fácil aplicarlo grid-columns: span [n]a uno de los elementos, donde nes el número de columnas que ocupará el elemento. El tercer elemento en nuestro diseño tiene una propiedad registrada grid-column: span 2, lo que explica por qué su ancho es dos veces mayor que otros elementos.

Para usar otros métodos, debe especificar las líneas de la cuadrícula . Las líneas de la cuadrícula se numeran de la siguiente manera:


Las líneas de cuadrícula se pueden indicar de izquierda a derecha con números positivos (por ejemplo, 1, 2, 3), o de derecha a izquierda con números negativos (-1, -2, -3). Se pueden usar para colocar elementos en la cuadrícula utilizando una propiedad grid-column, como esta:

.grid-item {
  grid-column: ( ) / ( );
}

Por lo tanto, las líneas de la cuadrícula amplían nuestra capacidad para definir tramos. La flexibilidad se agrega por la capacidad de reemplazar el valor inicial o final con una palabra clave span. Por ejemplo, el bloque azul de tres columnas en el ejemplo anterior se puede crear aplicando cualquiera de estas propiedades al octavo elemento de cuadrícula:

  • grid-column: 3 / 6
  • grid-column: -4 / -1
  • grid-column: 3 / span 3
  • grid-column: -4 / span 3
  • grid-column: span 3 / -1
  • etc.

En una cuadrícula no adaptativa (es decir, con un número fijo de columnas), cada una de estas propiedades da el mismo resultado (como en el ejemplo con el bloque azul anterior). Pero si la cuadrícula es adaptativa y el número de columnas cambia, la diferencia se vuelve muy notable. Algunos tramos rompen el diseño con el ajuste automático activado, lo que hace que parezca que estas dos soluciones son incompatibles. Afortunadamente, algunos trucos nos permitirán combinarlos de manera segura.

Pero primero, necesitamos entender el problema.

Problemas de desplazamiento horizontal


Aquí hay algunos "elementos destacados" creados usando el método de línea de cuadrícula (clicable):


En todo el ancho (cinco columnas), todo se ve bien, pero si reduce la pantalla a un tamaño en el que debería haber dos columnas, el diseño se rompe de esta manera:


Como puede ver, nuestra cuadrícula ha perdido su adaptabilidad y, aunque el contenedor se ha reducido, la cuadrícula está tratando de soportar las cinco columnas. Para hacer esto, continúa probando el mismo ancho de columna y eventualmente va más allá de los límites de su contenedor a la derecha. A partir de esto, aparece el desplazamiento horizontal.

¿Por qué sucede? El problema es que el navegador está tratando de cumplir con nuestras instrucciones exactas para las líneas de la cuadrícula. En este ancho, la auto-fitcuadrícula solo debe mostrar dos columnas, pero nuestro sistema de numeración de líneas de pila contradice esto, refiriéndose específicamente a la quinta línea. Esta contradicción conduce al desorden. Para mostrar correctamente nuestra cuadrícula implícita de dos columnas, solo se pueden usar los números 1, 2, 3 y -3, -2, -1, así:


Pero si uno de los elementos de nuestra cuadrícula contiene instrucciones grid-columnfuera de estos límites, digamos 4, 5 o -6, el navegador recibe instrucciones ambiguas. Por un lado, le pedimos que cree automáticamente columnas flexibles (que deberían, implícitamente, permanecer dos en este ancho de pantalla). Por otro lado, nos referimos explícitamente a las líneas de cuadrícula, que no pueden existir en un formato de dos columnas. Cuando existe una contradicción entre las columnas implícitas (automáticas) y su número explícitamente definido, la cuadrícula siempre prefiere una definición explícita . Así es como aparecen las columnas no deseadas y el desbordamiento horizontal (lo que llaman pérdida de datos CSS) Los tramos, como los números de línea de la cuadrícula, pueden crear definiciones de columna explícitas. grid-column: span 3 (el octavo elemento de la cuadrícula en la demostración) obliga a la cuadrícula a tener explícitamente al menos tres columnas, a pesar de que queremos dos implícitas.

Puede parecer que la única opción es utilizar consultas de medios para cambiar los valores grid-columnen el ancho deseado ... ¡pero no se apresure! Yo también lo pensé al principio. Pero, después de reflexionar un poco y jugar con diferentes configuraciones, descubrí que hay algunas formas de solucionar este problema, gracias a las cuales todavía tenemos una sola solicitud de medios para los dispositivos más estrechos.

Soluciones


Al final resultó que, el truco es determinar los tramos utilizando solo números de línea que están disponibles para la cuadrícula más estrecha de las planificadas para su visualización. En este caso, estamos hablando de una cuadrícula de dos columnas (recuerde, usamos una consulta de medios para la visualización de una sola columna). Por lo tanto, puede usar con seguridad los números 1, 2, 3 y sus pares negativos sin romper la cuadrícula.

Al principio pensé que me limitaría al ancho del tramo en dos columnas usando estas combinaciones de números:

  • grid column: span 2
  • grid-column: 1 /3
  • grid-column: -3 / -1


Que permanecen perfectamente adaptables hasta dos altavoces:


Aunque esto funciona , desde el punto de vista del diseño, esta es una limitación seria, y no demasiado brillante. Quería hacer tramos en el ancho de tres, cuatro o incluso cinco columnas en pantallas anchas. ¿Pero cómo? Lo primero que pensé fue volver a las consultas de los medios nuevamente (Dios mío, es difícil deshacerse de los viejos hábitos), pero aún así traté de evitar este enfoque y mirar el diseño receptivo desde un ángulo diferente.

Al mirar nuevamente la lista de números disponibles, de repente me di cuenta de que los números positivos y negativos en los valores iniciales y finales grid-columnse pueden combinar, por ejemplo 1/-3,2/-2. No parecería nada interesante. Pero ya no parece así cuando comprende la posición de las líneas después de cambiar el tamaño de la cuadrícula: los tramos cambian el ancho de acuerdo con el ancho de la pantalla. Se abre un montón de nuevas oportunidades para tramos adaptativos, en particular, elementos que abarcan un número diferente de columnas con un cambio en el ancho de la pantalla, sin ninguna consulta de medios.

El primer ejemplo que descubrí es grid-column: 1/-1. Esta propiedad convierte el elemento en un banner en todo su ancho, llenando todas las columnas de la primera a la última, ¡incluso cuando solo hay una columna!

Utilizandogrid-column: 1/-2, puede crear un tramo de "ancho casi completo", que llena todas las columnas de izquierda a derecha, excepto la última. En un diseño de dos columnas, dicho intervalo se adapta adaptativamente a un elemento ordinario en una columna. Sorprendentemente, funciona incluso al comprimir el diseño en una columna. (Parece que la razón es que la cuadrícula no reducirá el elemento a ancho cero y, por lo tanto, seguirá siendo el ancho de una columna, como en el caso de grid-column: 1/1). Supuse que grid-column: 2/-1debería funcionar de la misma manera, solo deje una columna intacta a la izquierda y no a la derecha . Resultó ser casi correcto, al comprimir el diseño en una columna, todavía se produce un desbordamiento.

Entonces probé una combinación1/-3. Funcionó bien en pantallas anchas, llenando al menos tres columnas, y en pantallas estrechas, llenando solo una. Pensé que con una cuadrícula de dos columnas resultaría algo extraño, ya que la primera línea de la cuadrícula es la misma que la línea debajo del número -3. Para mi sorpresa, el elemento se muestra correctamente en una columna.

Después de numerosos experimentos, descubrí que hay 11 valores adecuados grid-columnde los disponibles en una cuadrícula de dos columnas. Tres de ellos funcionan incluso en un diseño de una sola columna. Otras siete funcionan correctamente hasta en dos columnas, y para una visualización adecuada en una columna solo necesitarán una consulta de medios.

Aquí está la lista completa:


Demostración de valores adaptativos de columna de cuadrícula en diferentes tamaños de pantalla en una cuadrícula de ajuste automático. ( Demo )

En general, a pesar de un subconjunto bastante limitado de tramos adaptativos, hay muchas oportunidades.

  • 2/-2 - ¡Una combinación interesante, crea un espacio centrado que funciona hasta la cuadrícula de una columna!
  • 3/-1 - Menos útil ya que conduce al desbordamiento incluso en dos columnas.
  • 3/-3 - una sorpresa agradable.

Debido a la variedad de valores grid-columnde esta lista, es posible crear un diseño interesante y totalmente receptivo. Usando una única consulta de medios para la visualización de columna única más estrecha, podemos administrar diez patrones diferentes grid-column.

Esa misma consulta de medios es bastante simple, incluso digamos sencilla. En nuestro ejemplo, él es responsable de cambiar la visualización de la cuadrícula a flexbox:

@media (max-width: 680px) {
  .archive {
    display: flex;
    flex-direction: column;
  }

  .article {
    margin-bottom: 2em;
  }
}

Aquí está la grilla final, que, como habrás notado, es totalmente receptiva: de una a cinco columnas (se puede hacer clic):


Uso: nth-child () para repetir ancho dinámico


Para reducir mi código a dos docenas de líneas, apliqué otro truco. El selector :nth-child(n)me permitió diseñar una gran cantidad de elementos a la vez. Toda mi idea con los tramos debía aplicarse a muchas publicaciones en el feed para que los bloques seleccionados aparecieran en la página regularmente. Primero, escribí una lista de selectores separados por comas con un número de elemento claramente definido:

.article:nth-child(2),
.article:nth-child(18),
.article:nth-child(34),
.article:nth-child(50)  {
  background-color: rgba(128,0,64,0.8);
  grid-column: -3 / -1;
}

En cuanto a la velocidad, me di cuenta de que este es un proceso que lleva mucho tiempo, especialmente cuando tiene que copiar esta lista completa de condiciones para cada elemento secundario que debe cambiarse dentro del artículo: encabezado, enlaces, etc. Durante la creación de prototipos, me vi obligado a cambiar manualmente los números en cada una de estas listas cada vez que quería jugar con la posición de los tramos. Un proceso aburrido y propenso a errores.

Fue entonces cuando me di cuenta de que puede aprovechar la característica genial del pseudo-selector :nth-child: en lugar de un valor entero, ingrese una expresión, por ejemplo :nth-child(2n+ 2), que significa cada segundo elemento secundario.

Así es como solía :nth-child([])crear un bloque azul de ancho completo en mi cuadrícula que aparece en la parte superior de la página y luego a la mitad de la lista:

.article:nth-child(31n + 1) {
  grid-column: 1 / -1;
  background: rgba(11, 111, 222, 0.5);
}

Una pieza de código entre paréntesis ( 31n + 1) es responsable de elegir el 1º, 32º, 63º, etc. elemento hijo El navegador inicia el ciclo que comienza con n = 0 ( 31 * 0 + 1 = 1), luego n=1( 31 * 1 + 1 = 32) y finalmente n=2( 31 * 2 + 1 = 63). En el último caso, el navegador comprende que no hay un elemento secundario 63, ignora la regla, detiene el ciclo y aplica la regla a los elementos primero y 32.

Estoy haciendo algo similar para los bloques morados que aparecen a la izquierda o a la derecha en toda la página:

.article:nth-child(16n + 2) {
  grid-column: -3 / -1;
  background: rgba(128, 0, 64, 0.8);
}

.article:nth-child(16n + 10) {
  grid-column: 1 / -2;
  background: rgba(128, 0, 64, 0.8);
}

El primer selector es para los bloques morados de la izquierda. La expresión 16n + 2es responsable de aplicar estilos a cada elemento de cuadrícula 16, comenzando con el segundo.

El segundo selector es para los bloques morados de la derecha. El intervalo es el mismo ( 16n), pero el cambio es diferente ( 10). Como resultado, estos bloques se encuentran regularmente en el lado derecho de la cuadrícula, en elementos numerados 10, 26, 42, etc.

Para los estilos visuales de estos elementos, utilicé otro truco para evitar la repetición del código. Para estilos comunes de bloques morados ( background-colorpor ejemplo, obvio ), puede usar un selector:

.article:nth-child(8n + 2) {
  background: rgba(128, 0, 64, 0.8);
  /* Other shared syling */
}

Este selector seleccionará los elementos 2, 10, 18, 26, 34, 42, 50 y más. En otras palabras, selecciona los bloques izquierdo y derecho.

Esto funciona porque 8n- esto es exactamente la mitad 16n, y la diferencia de desplazamiento en los dos selectores también es 8.

Palabra final


CSS Grid ahora se puede usar para crear mallas flexibles y receptivas con un código mínimo. Sin embargo, si evita el uso de consultas de medios retrógradas, existen restricciones significativas en el posicionamiento de los elementos en la cuadrícula.

Sería genial poder crear tramos que no condujeran al desplazamiento horizontal y al desbordamiento en pantallas pequeñas. Ahora podemos decirle al navegador: "Haga una cuadrícula adaptativa, por favor", y lo hace muy bien. Pero solo necesita agregar: "Ah, y este elemento de la cuadrícula se estira en cuatro columnas, por favor", y agita el asa hacia pantallas estrechas, dando preferencia a la solicitud de un tramo de cuatro columnas, en lugar de una cuadrícula adaptativa. Sería posible hacer que la cuadrícula haga lo contrario, por ejemplo así:

.article {
  grid-column: span 3, autofit;
}

Otro problema con las cuadrículas receptivas es la última línea. Cambiar el ancho de la pantalla a menudo puede hacer que esté en blanco. Intenté durante mucho tiempo encontrar una manera de estirar el último elemento de la cuadrícula a las columnas restantes (respectivamente, llenar la fila), pero parece ser imposible. Por ahora. Sería bueno tener la oportunidad de establecer la posición inicial del elemento con una palabra clave, como auto, por así decir, "Rellene la línea hasta el final, comenzando desde el borde izquierdo". Algo como esto:

.article {
  grid-column: auto, -1;
}

... eso estiraría el tramo en el borde izquierdo de la cuadrícula hasta el final de la línea.


All Articles