Descubrí CSS hace aproximadamente una década mientras intentaba modificar el aspecto de un blog que había creado. Muy pronto, pude codificar cosas interesantes con características más matemáticas y, por lo tanto, más fáciles de entender, como las transformaciones. Sin embargo, otras áreas de CSS, como el diseño, siguen siendo una fuente constante de problemas.
Esta publicación trata sobre un problema que encontré hace aproximadamente una década y, hasta hace poco, no sabía cómo resolverlo de manera inteligente. Específicamente, se trata de cómo encontré una solución a un problema de larga duración utilizando una técnica moderna de cuadrícula CSS que, en el proceso, me dio resultados aún más geniales de lo que imaginé originalmente.
Tenga en cuenta que este no es un tutorial sobre cómo utilizar mejor la cuadrícula CSS, sino más bien un recorrido por mi propio proceso de aprendizaje.
El problema
Una de las primeras cosas que solía publicar en ese blog eran fotos aleatorias de la ciudad, así que tuve la idea de tener una cuadrícula de miniaturas con un tamaño fijo. Para una apariencia más agradable, quería que esta cuadrícula estuviera alineada en el medio con respecto a los párrafos arriba y abajo, pero, al mismo tiempo, quería que las miniaturas de la última fila estuvieran alineadas a la izquierda con respecto a la cuadrícula. Mientras tanto, el ancho de la publicación (y el ancho de la cuadrícula dentro de él) dependería de la ventana gráfica.
El HTML se parece a esto:
<section class="post__content">
<p><!-- some text --></p>
<div class="grid--thumbs">
<a href="https://css-tricks.com/cool-little-css-grid-tricks-for-your-blog/full-size-image.jpg">
<img src="https://css-tricks.com/cool-little-css-grid-tricks-for-your-blog/thumb-image.jpg" alt="image description"/>
</a>
<!-- more such thumbnails -->
</div>
<p><!-- some more text --></p>
</section>
Puede parecer simple, pero resultó ser uno de los problemas de CSS más difíciles que he encontrado.
Soluciones menos que ideales
Estas son cosas que he probado o visto sugeridas a lo largo de los años, pero que en realidad nunca me llevaron a ninguna parte.
Imposibilidad flotante
Los flotadores resultaron ser un callejón sin salida porque no pude averiguar cómo hacer que la cuadrícula se alineara en el medio de esta manera.
.grid--thumbs { overflow: hidden; }
.grid--thumbs a { float: left; }
La siguiente demostración muestra el intento de flotación. Cambie el tamaño de la inserción para ver cómo se comporta en diferentes anchos de ventana gráfica.
inline-block
Locura
Al principio, esto parecía una mejor idea:
.grid--thumbs { text-align: center }
.grid--thumbs a { display: inline-block }
Excepto que resultó que no lo era:
En este caso, la última fila no se alinea a la izquierda.
En cierto momento, gracias a un autocompletado accidental de CSS en CodePen, descubrí una propiedad llamada text-align-last
, que determina cómo se alinea la última línea de un bloque.
Desafortunadamente, estableciendo text-align-last: left
en la cuadrícula tampoco era la solución que estaba buscando:
En este punto, consideré descartar la idea de una cuadrícula alineada en el medio. ¿Podría una combinación de text-align: justified
y text-align-last: left
en la cuadrícula producen un mejor resultado?
Bueno, resulta que no es así. Es decir, a menos que solo haya una miniatura en la última fila y los espacios entre las columnas no sean demasiado grandes. Cambie el tamaño de la inserción a continuación para ver a qué me refiero.
Esto es más o menos donde estaba hace dos años, después de nueve años de intentar y no encontrar una solución a este problema.
Hacks sucios de flexbox
Una solución de flexbox que parecía que funcionaría al principio era agregar un ::after
pseudo-elemento en la cuadrícula y establecer flex: 1
tanto en las miniaturas como en este pseudo-elemento:
.grid--thumbs {
display: flex;
flex-wrap: wrap;
a, &::after { flex: 1; }
img { margin: auto; }
&:after { content: 'AFTER'; }
}
La siguiente demostración muestra cómo funciona este método. Le he dado las miniaturas y el ::after
contornos de pseudoelemento púrpura para que sea más fácil ver lo que está sucediendo.
Esto no es exactamente lo que quería porque la cuadrícula de miniaturas no está alineada en el medio. Dicho esto, no se ve tan mal … siempre que la última fila tenga exactamente un elemento menos imagen que los demás. Sin embargo, tan pronto como eso cambie, el diseño se romperá si faltan más elementos o ninguno.
Porqué el ::after
hack no es confiable.
Esa fue una idea loca. Otra es no usar un pseudoelemento, sino agregar tantos divs vacíos después de las miniaturas como columnas que esperamos tener.
El número esperado de columnas es algo que deberíamos poder aproximar, ya que el tamaño de las miniaturas es fijo y probablemente queramos establecer un ancho máximo para la publicación, ya que el texto que se extiende a lo ancho de una pantalla completa puede ser visualmente agotador para los ojos. leer. Dividir el ancho máximo por el ancho fijo de la miniatura debería darnos el número máximo de columnas en este caso.
Los primeros elementos vacíos ocuparán todo el ancho de la fila que no está completamente llena de miniaturas, mientras que el resto se extenderá a otras filas. Pero dado que su height
es cero, no importará visualmente.
Esto hace el truco, pero, de nuevo, es hacky y todavía no produce el resultado exacto que quiero, ya que a veces termina con grandes y feos espacios entre las columnas.
¿Una solución de rejilla?
El diseño de la cuadrícula siempre ha sonado como la respuesta, dado su nombre. El problema era que todos los ejemplos que había visto para ese entonces usaban un número predefinido de columnas y eso no funciona para este patrón en particular donde el número de columnas está determinado por el ancho de la ventana gráfica.
El año pasado, mientras codificaba una colección de un elemento, patrones de fondo CSS puros, tuve la idea de generar un montón de consultas de medios que modificarían una variable CSS, --n
, correspondiente al número de columnas utilizadas para establecer grid-template-columns
.
$w: 13em;
$h: 19em;
$f: $h/$w;
$n: 7;
$g: 1em;
--h: #{$f*$w};
display: grid;
grid-template-columns: repeat(var(--n, #{$n}), var(--w, #{$w}));
grid-gap: $g;
place-content: center;
@for $i from 1 to $n {
@media (max-width: ($n - $i + 1)*$w + ($n - $i + 2)*$g) {
--n: #{$n - $i}
}
}
En realidad, estaba muy orgulloso de esta idea en ese momento, aunque ahora me estremezco al mirar hacia atrás. Una consulta de medios para cada número de columnas posibles no es exactamente ideal, sin mencionar que no funciona tan bien cuando el ancho de la cuadrícula no es igual al ancho de la ventana gráfica, pero sigue siendo algo flexible y también depende del ancho de sus hermanos. .
Una solucion magica
Finalmente encontré una mejor solución mientras trabajaba con la cuadrícula CSS y no entendía por qué el repeat()
la función no estaba funcionando en una situación particular. Fue muy frustrante y me impulsó a ir a MDN, donde me di cuenta de la auto-fit
palabra clave y, aunque no entendía la explicación, tenía el presentimiento de que podría ayudar con este otro problema, así que dejé todo lo que estaba haciendo y lo intenté.
Esto es lo que tengo:
.grid--thumbs {
display: grid;
justify-content: center;
grid-gap: .25em;
grid-template-columns: repeat(auto-fit, 8em);
}
También descubrí el minmax()
función, que se puede utilizar en lugar de tamaños fijos en elementos de la cuadrícula. Todavía no he podido entender exactamente cómo minmax()
funciona, y cuanto más juego con él, menos lo entiendo, pero lo que parece que hace en esta situación es crear la cuadrícula y luego estirar sus columnas por igual hasta que llenen todo el espacio disponible:
grid-template-columns: repeat(auto-fit, minmax(8em, 1fr));
Otra cosa interesante que podemos hacer aquí es evitar que la imagen se desborde cuando es más ancha que el elemento de la cuadrícula. Podemos hacer esto reemplazando el mínimo 8em
con min(8em, 100%)
Eso esencialmente asegura que las imágenes nunca excedan el 100%, pero nunca por debajo de los 8em. ¡Gracias a Chris por esta sugerencia!
Tenga en cuenta que el min()
¡La función no funciona en versiones anteriores a Chromium Edge!
Tenga en cuenta que esto solo produce un buen resultado si todas las imágenes tienen la misma relación de aspecto, como las imágenes cuadradas que he usado aquí. Para mi blog, esto no fue un problema, ya que todas las fotos se tomaron con mi teléfono Sony Ericsson W800i y todas tenían la misma relación de aspecto. Pero si soltáramos imágenes con diferentes relaciones de aspecto, la cuadrícula ya no se vería tan bien:
Podemos, por supuesto, configurar la imagen height
a un valor fijo, pero eso distorsiona las imágenes … a menos que establezcamos object-fit
a cover
, que resuelve nuestro problema!
Otra idea sería convertir la primera miniatura en una especie de banner que abarque todas las columnas de la cuadrícula. El único problema es que no sabemos el número de columnas porque eso depende de la ventana gráfica. Pero hay una solución: podemos establecer grid-column-end
a -1
!
.grid--thumbs {
/* same styles as before */
a:first-child {
grid-column: 1/ -1;
img { height: 13em }
}
}
La primera imagen se agranda height
que todos los demás.
Por supuesto, si quisiéramos que la imagen abarcara todas las columnas excepto la última, la configuraríamos en -2
y así sucesivamente … ¡los índices de columna negativos son una cosa!
auto-fill
es otra palabra clave de propiedad de cuadrícula que noté en MDN. Las explicaciones para ambos son largas paredes de texto sin imágenes, por lo que no las encontré particularmente útiles. Peor aún, reemplazando auto-fit
con auto-fill
en cualquiera de las demostraciones de grid anteriores no produce absolutamente ninguna diferencia. Cómo funcionan realmente y en qué se diferencian sigue siendo un misterio, incluso después de consultar artículos o jugar con ejemplos.
Sin embargo, probar diferentes cosas y ver lo que sucede en varios escenarios en un punto me llevó a la conclusión de que, si estamos usando un minmax()
ancho de columna y no fijo (como 8em
), entonces probablemente sea mejor usar auto-fill
en vez de auto-fit
porque, el resultado se ve mejor si solo tenemos unas pocas imágenes, como se ilustra en la demostración interactiva a continuación:
Creo que lo que más me gusta personalmente es la idea inicial de una cuadrícula de miniaturas que está alineada en el medio y tiene un ancho de columna mayormente fijo (pero aún usa min(100%, 15em)
en lugar de solo 15em
sin embargo). Al final del día, es una cuestión de preferencia personal y lo que se puede ver en la demostración a continuación me parece mejor:
Estoy usando auto-fit
en esta demostración porque produce el mismo resultado que auto-fill
y es un carácter más corto. Sin embargo, lo que no entendí al hacer esto es que ambas palabras clave producen el mismo resultado porque hay más elementos en la galería de los que necesitamos para completar una fila.
Pero una vez que eso cambia, auto-fit
y auto-fill
producir resultados diferentes, como se ilustra a continuación. Puedes cambiar el justify-content
valor y el número de elementos colocados en la cuadrícula:
No estoy seguro de cuál es la mejor opción. Supongo que esto también depende de las preferencias personales. Junto con justify-content: center
, auto-fill
parece ser la opción más lógica, pero, al mismo tiempo, auto-fit
produce un resultado más atractivo.