Hexágonos y más: patrones de cuadrícula flexibles y receptivos, consultas sin medios

Hace un tiempo, Chris compartió esta bonita cuadrícula hexagonal. Y fiel a su nombre, está usando (espérelo) CSS Grid para formar ese diseño. ¡Es un buen truco! La combinación de columnas de cuadrícula, espacios de cuadrícula y recortes creativos produce el resultado final.
También se podría lograr algo similar con flexbox. Pero estoy aquí para resucitar a nuestro viejo amigo float
para crear el mismo tipo de diseño complejo y responsivo, pero con menos complejidad y sin una sola consulta de medios.
Lo sé, es difícil de creer. Entonces, comenzamos con una demostración funcional:
Esta es una cuadrícula hexagonal totalmente responsiva creada sin consultas de medios, JavaScript o una tonelada de CSS hacky. Cambie el tamaño de la pantalla de demostración y vea la magia. Además de responder, la cuadrícula también se escala. Por ejemplo, podemos incluir más hexágonos agregando más divs y controlar tanto el tamaño como el espaciado usando variables CSS.
¿Guay, verdad? Y este es sólo un ejemplo entre muchas redes que construiremos de la misma manera.
Hacer una cuadrícula de hexágonos
Primero, creamos nuestra forma hexagonal. Esta tarea es bastante fácil de usar clip-path
. Consideraremos una variable S
que definirá la dimensión de nuestro elemento. Clippy de Bennett Feely es un excelente generador en línea de rutas de clips.
Cada hexágono es un inline-block
elemento. El marcado puede ser algo como esto:
div div div/div div/div div/div !--etc. -- /div/div
…y el CSS:
.main { display: flex; /* we will talk about this later ... */ --s: 100px; /* size */ --m: 4px; /* margin */}.container { font-size: 0; /* disable white space between inline block element */}.container div { width: var(--s); margin: var(--m); height: calc(var(--s) * 1.1547); display: inline-block; font-size: initial; /* we reset the font-size if we want to add some content */ clip-path: polygon(0% 25%, 0% 75%, 50% 100%, 100% 75%, 100% 25%, 50% 0%);}
Nada complejo hasta el momento. Tenemos un elemento principal que contiene un contenedor que a su vez contiene los hexágonos. Dado que estamos tratando con inline-block
, necesitamos combatir el problema del espacio en blanco común (usando el font-size
truco) y consideramos algún margen (definido con la variable M
) para controlar el espacio.
Aquí está el resultado hasta el momento:
Cada dos filas necesita un desplazamiento negativo para que las filas se superpongan en lugar de apilarse directamente una encima de la otra. Ese desplazamiento será igual a 25%
la altura del elemento (ver Figura 1). Aplicamos esa compensación para margin-bottom
obtener lo siguiente:
.container div { width: var(--s); margin: var(--m); height: calc(var(--s) * 1.1547); display: inline-block; font-size: initial; clip-path: polygon(0% 25%, 0% 75%, 50% 100%, 100% 75%, 100% 25%, 50% 0%); margin-bottom: calc(var(--m) - var(--s) * 0.2886); /* some negative margin to create overlap */}
…y el resultado es:
Ahora el verdadero truco es cómo podemos desplazar la segunda fila para obtener una cuadrícula hexagonal perfecta. Ya hemos arrugado las cosas hasta el punto en que las filas se superponen verticalmente, pero lo que necesitamos es empujar cada dos filas hacia la derecha para que los hexágonos se tambaleen en lugar de superponerse. Aquí es donde entra en juego float
y.shape-outside
¿Te preguntaste por qué tenemos un .main
elemento que envuelve nuestro contenedor y tiene display: flex
? Ese div también es parte del truco. En un artículo anterior, usé float
y necesitaba ese contenedor flexbox para poder usar height: 100%
. Yo haré lo mismo aquí.
.container::before { content: ""; width: calc(var(--s)/2 + var(--m)); float: left; height: 100%;}
Estoy usando el container::before
pseudoelemento para crear un elemento flotante que ocupa toda la altura a la izquierda de la cuadrícula y que tiene un ancho igual a medio hexágono (más su margen). Obtenemos el siguiente resultado:
Ahora podemos alcanzar shape-outside
. Hagamos un repaso rápido de lo que hace. Robin lo define muy bien en CSS-Tricks Almanac. MDN también lo describe muy bien:
La
shape-outside
propiedad CSS define una forma (que puede no ser rectangular) alrededor de la cual debe envolverse el contenido en línea adyacente. De forma predeterminada, el contenido en línea se ajusta alrededor de su cuadro de margen;shape-outside
proporciona una forma de personalizar este ajuste, lo que permite ajustar el texto alrededor de objetos complejos en lugar de simples cuadros.El énfasis es mío.
Observe el "contenido en línea" en la definición. Esto explica exactamente por qué los hexágonos necesitan ser inline-block
elementos. Pero para entender qué tipo de forma necesitamos, acerquémonos al patrón.
Lo bueno shape-outside
es que en realidad funciona con degradados. Pero ¿qué tipo de gradiente se adapta a nuestra situación?
Si, por ejemplo, tenemos 10 filas de hexágonos, solo necesitamos cambiar las medias en cada fila par. Visto de otra manera, necesitamos cambiar cada segunda fila, por lo que necesitamos una especie de repetición, ¡perfecta para un degradado repetido!
Crearemos un degradado con dos colores:
- Uno transparente para crear el "espacio libre" y al mismo tiempo permitir que la primera fila permanezca en su lugar (ilustrado por la flecha azul arriba).
- Un color opaco para desplazar la segunda fila hacia la derecha de modo que los hexágonos no queden directamente apilados uno encima del otro (ilustrado con la flecha verde).
Nuestro shape-outside
valor se verá así:
shape-outside: repeating-linear-gradient(#0000 0 A, #000 0 B); /* #0000 = transparent */
Ahora, encontremos el valor de A
y B
. B
simplemente será igual a la altura de dos filas ya que nuestra lógica necesita repetir cada dos filas.
La altura de dos filas es igual a la altura de dos hexágonos (incluidos sus márgenes), menos el doble de la superposición ( 2*Height + 4*M - 2*Height*25% = 1.5*Height + 4*M
). O, expresado en CSS con calc()
:
calc(1.732 * var(--s) + 4 * var(--m))
¡Eso es mucho! Entonces, mantengamos todo esto en una propiedad personalizada de CSS, F
.
El valor de A
(definido por la flecha azul en la figura anterior) debe ser al menos igual al tamaño de un hexágono, pero también puede ser mayor. Para empujar la segunda fila hacia la derecha, necesitamos algunos píxeles de color opaco, por lo que A
simplemente puede ser igual a B - Xpx
, donde X
es un valor pequeño.
Terminamos con algo como esto:
shape-outside: repeating-linear-gradient(#0000 0 calc(var(--f) - 3px),#000 0 var(--f));
Y el siguiente resultado:
¿Mira eso? La forma de nuestro degradado lineal repetitivo empuja cada dos filas hacia la derecha la mitad del ancho de un hexágono para compensar el patrón.
Juntemos todo eso:
.main { display:flex; --s: 100px; /* size */ --m: 4px; /* margin */ --f: calc(var(--s) * 1.732 + 4 * var(--m) - 1px); }.container { font-size: 0; /* disable white space between inline block element */}.container div { width: var(--s); margin: var(--m); height: calc(var(--s) * 1.1547); display: inline-block; font-size:initial; clip-path: polygon(0% 25%, 0% 75%, 50% 100%, 100% 75%, 100% 25%, 50% 0%); margin-bottom: calc(var(--m) - var(--s) * 0.2885);}.container::before { content: ""; width: calc(var(--s) / 2 + var(--m)); float: left; height: 120%; shape-outside: repeating-linear-gradient(#0000 0 calc(var(--f) - 3px), #000 0 var(--f));}
¡Eso es todo! Con no más de 15 declaraciones CSS, tenemos una cuadrícula responsiva que se adapta perfectamente a todos los tamaños de pantalla y podemos ajustar las cosas fácilmente simplemente controlando dos variables.
Quizás hayas notado que estoy agregando -1px
a la variable F
. Dado que estamos ante cálculos que involucran decimales, el redondeo puede darnos malos resultados. Para evitar esto agregamos o eliminamos algunos píxeles. También estoy usando 120%
en lugar de 100%
para la altura del elemento flotante por razones similares. No existe una lógica particular con estos valores; simplemente los ajustamos para asegurarnos de cubrir la mayoría de los casos sin desalinear nuestras formas.
¿Quieres más formas?
¡Podemos hacer más que hexágonos con este enfoque! En su lugar, creemos una cuadrícula de "rombos". Nuevamente, comenzamos con nuestro clip-path
para crear la forma:
El código es básicamente el mismo. Lo que cambia son los cálculos y los valores. Encuentre a continuación una tabla que ilustrará los cambios.
Rejilla hexagonal | Rejilla de rombos | |
---|---|---|
height |
calc(var(--s)*1.1547) |
var(--s) |
clip-path |
polygon(0% 25%, 0% 75%, 50% 100%, 100% 75%, 100% 25%, 50% 0%) |
polygon(50% 0, 100% 50%, 50% 100%, 0 50%) |
margin-bottom |
calc(var(--m) - var(--s)*0.2885) |
calc(var(--m) - var(--s)*0.5) |
--f |
calc(var(--s)*1.7324 + 4*var(--m)) |
calc(var(--s) + 4*var(--m)) |
¡Y hemos terminado! Con solo cuatro cambios en nuestro código obtenemos una cuadrícula completamente nueva pero con una forma diferente.
¿Qué tan flexible es esto?
Vimos cómo podíamos hacer las cuadrículas de hexágonos y rombos usando exactamente la misma estructura de código, pero con diferentes variables. Déjame sorprenderte con otra idea: ¿Qué tal si convertimos ese cálculo en una variable para que podamos cambiar fácilmente entre diferentes cuadrículas sin cambiar el código? ¡Ciertamente podemos hacer eso!
Usaremos una forma octogonal porque es más una forma genérica que podemos usar para crear otras formas (un hexágono, un rombo, un rectángulo, etc.) simplemente cambiando algunos valores.
Nuestro octágono se define con cuatro variables:
S
: la anchura.R
: la relación que nos ayudará a definir el alto en función del ancho.hc
yvc
: ambos controlarán nuestrosclip-path
valores y la forma que queremos conseguir.hc
se basará en el ancho mientras quevc
en la altura
Sé que parece considerable, pero clip-path
se define usando ocho puntos (como se muestra en la figura). Agregando algunas variables CSS, obtenemos esto:
clip-path: polygon( var(--hc) 0, calc(100% - var(--hc)) 0, /* 2 points at the top */ 100% var(--vc),100% calc(100% - var(--vc)), /* 2 points at the right */ calc(100% - var(--hc)) 100%, var(--hc) 100%, /* 2 points at the bottom */ 0 calc(100% - var(--vc)),0 var(--vc) /* 2 points at the left */);
Esto es lo que pretendemos:
Acerquémonos para identificar los diferentes valores:
La superposición entre cada fila (ilustrada por la flecha roja) se puede expresar usando la vc
variable que nos da un margin-bottom
igual a M - vc
(dónde M
está nuestro margen).
Además del margen que aplicamos entre nuestro elemento, también necesitamos un margen horizontal adicional (ilustrado por la flecha amarilla) igual a S - 2*hc
. Definamos otra variable para el margen horizontal ( MH
) que sea igual a M + (S - 2*hc)/2
.
La altura de dos filas es igual al doble del tamaño de una forma (más el margen), menos el doble de la superposición, o 2*(S + 2*M) - 2*vc
.
Actualicemos nuestra tabla de valores para ver cómo calculamos las cosas entre las diferentes cuadrículas:
Rejilla hexagonal | Rejilla de rombos | Cuadrícula octágono | |
---|---|---|---|
height |
calc(var(--s)*1.1547) |
var(--s) |
calc(var(--s)*var(--r))) |
clip-path |
polygon(0% 25%, 0% 75%, 50% 100%, 100% 75%, 100% 25%, 50% 0%) |
polygon(50% 0, 100% 50%, 50% 100%, 0 50%) |
polygon(var(--hc) 0, calc(100% - var(--hc)) 0,100% var(--vc),100% calc(100% - var(--vc)), calc(100% - var(--hc)) 100%,var(--hc) 100%,0 calc(100% - var(--vc)),0 var(--vc)) |
--mh |
– | – | calc(var(--m) + (var(--s) - 2*var(--hc))/2) |
margin |
var(--m) |
var(--m) |
var(--m) var(--mh) |
margin-bottom |
calc(var(--m) - var(--s)*0.2885) |
calc(var(--m) - var(--s)*0.5) |
calc(var(--m) - var(--vc)) |
--f |
calc(var(--s)*1.7324 + 4*var(--m)) |
calc(var(--s) + 4*var(--m)) |
calc(2*var(--s) + 4*var(--m) - 2*var(--vc)) |
Muy bien, actualicemos nuestro CSS con esos ajustes:
.main { display: flex; --s: 100px; /* size */ --r: 1; /* ratio */ /* clip-path parameter */ --hc: 20px; --vc: 30px; --m: 4px; /* vertical margin */ --mh: calc(var(--m) + (var(--s) - 2*var(--hc))/2); /* horizontal margin */ --f: calc(2*var(--s) + 4*var(--m) - 2*var(--vc) - 2px);}.container { font-size: 0; /* disable white space between inline block element */}.container div { width: var(--s); margin: var(--m) var(--mh); height: calc(var(--s)*var(--r)); display: inline-block; font-size: initial; clip-path: polygon( ... ); margin-bottom: calc(var(--m) - var(--vc));}.container::before { content: ""; width: calc(var(--s)/2 + var(--mh)); float: left; height: 120%; shape-outside: repeating-linear-gradient(#0000 0 calc(var(--f) - 3px),#000 0 var(--f));}
Como podemos ver, la estructura del código es la misma. Simplemente agregamos más variables para controlar la forma y ampliar la margin
propiedad.
Y debajo un ejemplo práctico. Ajuste las diferentes variables para controlar la forma mientras tiene una cuadrícula totalmente responsiva:
¿Una demostración interactiva, dices? ¡Puedes apostar!
Para facilitar las cosas, estoy expresando el vc
y hc
como porcentaje del ancho y alto para que podamos escalar fácilmente nuestros elementos sin romper elclip-path
De lo anterior podemos obtener fácilmente la cuadrícula hexagonal inicial:
La cuadrícula de rombos:
Y otra cuadrícula hexagonal más:
Una rejilla similar a la mampostería:
Y un tablero de ajedrez ya que estamos en eso:
¡Muchas posibilidades para crear una cuadrícula responsiva con cualquier tipo de forma! Todo lo que tenemos que hacer es ajustar algunas variables.
Arreglando la alineación
Intentemos controlar la alineación de nuestras formas. Dado que estamos tratando con inline-block
elementos, estamos tratando con la alineación izquierda predeterminada y un espacio vacío al final, dependiendo del ancho de la ventana gráfica.
Observe que alternamos entre dos tipos de cuadrículas según el ancho de la pantalla:
Sería bueno tener siempre uno de la cuadrícula (ya sea el número 1 o el número 2) y centrarlo todo para que el espacio libre se divida equitativamente en ambos lados.
Para obtener la primera cuadrícula en la figura anterior, el ancho del contenedor debe ser un multiplicador del tamaño de una forma, más su margen, o N*(S + 2*MH)
, donde N
es un valor entero.
Esto puede parecer imposible con CSS, pero de hecho es posible. Lo hice usando una cuadrícula CSS:
.main { display: grid; grid-template-columns: repeat(auto-fit, calc(var(--s) + 2*var(--mh))); justify-content: center;}.container { grid-column: 1/-1;}
.main
ahora es un contenedor de cuadrícula. Usando grid-template-columns
, defino el ancho de la columna (como se explicó anteriormente) y uso el auto-fit
valor para colocar tantas columnas como sea posible en el espacio disponible. Luego, .container
abarca todas las columnas de la cuadrícula 1/-1
, lo que significa que el ancho de nuestro contenedor será un multiplicador de un tamaño de columna.
Todo lo que se necesita para centrar las cosas es justify-content: center
.
¡Sí, CSS es mágico!
Cambie el tamaño de la demostración y observe que no solo tenemos la primera cuadrícula de la figura, sino que también todo está perfectamente centrado.
Pero espera, lo quitamos display: flex
e intercambiamos display: grid
... entonces, ¿cómo sigue funcionando la altura del flotador basada en porcentaje? Dije que usar un contenedor flexible era la clave para eso, ¿no?
Bueno, resulta que los deportes de cuadrícula CSS también cuentan con esa característica. De la especificación:
Una vez establecido el tamaño de cada área de la cuadrícula, los elementos de la cuadrícula se disponen en sus respectivos bloques contenedores. El ancho y el alto del área de la cuadrícula se consideran definitivos para este propósito.
Nota: Dado que las fórmulas calculadas utilizando sólo tamaños definidos, como la fórmula de ajuste elástico, también son definitivas, el tamaño de un elemento de la cuadrícula que se estira también se considera definido.
Un elemento de cuadrícula tiene una stretch
alineación por defecto, por lo que su altura es definida, lo que significa que usar un porcentaje como altura dentro de él es perfectamente válido.
Digamos que queremos la segunda cuadrícula en la figura; simplemente agregamos una columna adicional con un ancho igual a la mitad del ancho de las otras columnas:
.main { display: grid; grid-template-columns: repeat(auto-fit,calc(var(--s) + 2*var(--mh))) calc(var(--s)/2 + var(--mh)); justify-content :center;}
Ahora, además de una cuadrícula totalmente responsiva y lo suficientemente flexible como para adoptar formas personalizadas, ¡todo está perfectamente centrado!
Luchando contra el desbordamiento
El uso de negativo margin-bottom
en los últimos elementos y el elemento flotante que empuja nuestros elementos creará un desbordamiento no deseado que puede afectar el contenido colocado después de nuestra cuadrícula.
Si cambia el tamaño de la demostración, notará un desbordamiento igual al desplazamiento negativo y, a veces, es más grande. La solución es agregar algunos padding-bottom
a nuestro contenedor. Haré que el relleno sea igual a la altura de una forma:
Debo admitir que no existe una solución perfecta para combatir ese desbordamiento y controlar el espacio debajo de nuestra red. Ese espacio depende de muchos factores y es posible que tengamos que utilizar un valor de relleno diferente para cada caso. La solución más segura es considerar un valor grande que cubra la mayoría de los casos.
Espera, uno más: una cuadrícula piramidal.
Tomemos todo lo que hemos aprendido y construyamos otra grilla asombrosa. Esta vez transformaremos la cuadrícula que acabamos de hacer en una piramidal.
Considere que, a diferencia de la grilla que hemos hecho hasta ahora, la cantidad de elementos es importante especialmente para la parte responsiva. Es necesario conocer el número de elementos y más precisamente el número de filas.
No significa que necesitemos un montón de valores codificados; más bien usamos una variable adicional para ajustar las cosas según el número de filas.
La lógica se basa en el número de filas porque diferentes números de elementos pueden darnos el mismo número de filas. Por ejemplo, hay cinco filas cuando tenemos entre 11 y 15 elementos, incluso si la última fila no está completamente ocupada. Tener entre 16 y 21 elementos nos da seis filas, y así sucesivamente. El número de filas es nuestra nueva variable.
Antes de profundizar en la geometría y las matemáticas, aquí hay una demostración funcional:
Observe que la mayor parte del código es el mismo que hemos hecho en los ejemplos anteriores. Así que centrémonos en las nuevas propiedades que hemos agregado:
.main { --nr: 5; /* number of rows */}.container { max-width: calc(var(--nr)*(var(--s) + 2*var(--mh))); margin: 0 auto;}.container::before ,.container i { content: ""; width: calc(50% - var(--mh) - var(--s)/2); float: left; height: calc(var(--f)*(var(--nr) - 1)/2); shape-outside: linear-gradient(to bottom right, #000 50%, #0000 0);}.container i { float:right; shape-outside: linear-gradient(to bottom left, #000 50%, #0000 0);}
NR
es nuestra variable para el número de filas. El ancho del contenedor debe ser igual al de la última fila de la pirámide para asegurarse de que contenga todos los elementos. Si revisas la figura anterior, verás que el número de elementos contenidos en la última fila es simplemente igual al número de filas, lo que significa que la fórmula es: NR* (S + 2*MH)
.
También habrás notado que también agregamos un i
elemento allí. Lo hicimos porque necesitamos dos elementos flotantes donde aplicaremos shape-outside
.
Para entender por qué necesitamos dos elementos flotantes, veamos qué se hace detrás de escena:
Los elementos azules son nuestros elementos flotantes. Cada uno tiene un ancho igual a la mitad del tamaño del contenedor, menos la mitad del tamaño de la forma, más el margen. La altura es igual a cuatro filas en nuestro caso, y NR - 1
en un caso más genérico. Anteriormente, definimos la altura de dos filas, F
por lo que la altura de una fila es F/2
. Así llegamos a height: calc(var(--f)*(var(--nr) - 1)/2
.
Ahora que tenemos el tamaño de nuestros elementos, necesitamos aplicar un degradado a nuestro shape-outside
.
El color morado en la figura de arriba es el área restringida para nuestros elementos (debe ser un color opaco). El área restante es el espacio libre donde pueden fluir los elementos (debe ser de un color transparente). Esto se puede hacer usando un degradado diagonal:
shape-outside: linear-gradient(to bottom right, #000 50%, #0000 0);
Simplemente cambiamos right
con left
por el otro elemento flotante. Probablemente hayas notado que esto no responde. De hecho, continúe y ajuste el ancho de la ventana gráfica de la demostración y vea cuán poco responde.
Tenemos un par de opciones para responder:
- Podemos volver a la primera cuadrícula cuando el ancho del contenedor es menor que el ancho de la ventana gráfica. Es un poco complicado de codificar, pero nos permite conservar el mismo tamaño para nuestros elementos.
- Podemos reducir el tamaño de nuestros elementos para mantener la cuadrícula piramidal. Esto es más fácil de codificar usando el truco del valor basado en porcentaje, pero eso podría resultar en elementos muy pequeños en tamaños de pantalla más pequeños.
Vayamos con la primera solución. Nos gustan los buenos desafíos, ¿verdad?
Para obtener la cuadrícula piramidal, necesitábamos dos elementos flotantes. La cuadrícula inicial necesitaba sólo un elemento flotante. Por suerte, nuestra estructura nos permite tener tres elementos flotantes sin necesidad de añadir más elementos al marcado, gracias a los pseudoelementos. Usaremos container::before
, i::before
, i::after
:
/* Same as before... *//* The initial grid */.container::before { content: ""; width: calc(var(--s)/2 + var(--mh)); float: left; height: 120%; shape-outside: repeating-linear-gradient(#0000 0 calc(var(--f) - 3px),#000 0 var(--f));}/* The pyramidal grid */.container i::before ,.container i::after { content: ""; width: calc(50% - var(--mh) - var(--s)/2); float: left; height: calc(var(--f)*(var(--nr) - 1)/2); shape-outside: linear-gradient(to bottom right,#000 50%,#0000 0);}.container i::after { float:right; shape-outside: linear-gradient(to bottom left,#000 50%,#0000 0);}
Ahora necesitamos un truco que nos permita usar el primer elemento flotante o los otros dos, pero no todos al mismo tiempo. Esta condición debe estar basada en el ancho de nuestro contenedor:
- Si el ancho del contenedor es mayor que el ancho de la última fila, podemos tener nuestra pirámide y usar los elementos flotantes dentro
i
. - Si el ancho del contenedor es menor que el ancho de la última fila, cambiamos a la otra cuadrícula y usamos el primer elemento flotante.
¡Podemos usarlo clamp()
para esto! Es algo así como una función condicional que establece un rango mínimo y máximo y, dentro de ese rango, le proporcionamos un valor "ideal" para usar entre esos puntos. De esta manera, podemos "cambiar" entre cuadrículas usando nuestras fórmulas como valores fijados y aún evitar el uso de consultas de medios.
Nuestro código se verá así:
.main { /* the other variables won't change*/ --lw: calc(var(--nr)*(var(--s) + 2*var(--mh))); /* width of last row */}.container { max-width: var(--lw);}/* The initial grid */.container::before { width: clamp(0px, (var(--lw) - 100%)*1000, calc(var(--s)/2 + var(--mh)));}/* The pyramidal grid */.container i::before,.container i::after { width: clamp(0px, (100% - var(--lw) + 1px)*1000, calc(50% - var(--mh) - var(--s)/2));}
En pantallas más grandes, el ancho del contenedor ( LW
) ahora es igual a su max-width
, por lo que 100% == LW
. Eso significa que el ancho de .container::before
es igual a 0px
(y da como resultado que este elemento flotante se deshabilite).
Para los demás elementos flotantes, fijamos el ancho:
width: clamp(0px, (100% - var(--lw) + 1px)*1000, calc(50% - var(--mh) - var(--s)/2));
…donde el valor medio ( (100% - LW + 1px)*1000
) es igual a (0 + 1px)*1000 = 1000px
(un valor intencionalmente grande, pero arbitrario). Se sujeta a calc(50% - var(--mh) - var(--s)/2)
. En otras palabras, estos elementos flotantes se habilitan con el ancho correcto (el que definimos anteriormente)
¡Voilá! Tenemos una forma piramidal en pantalla grande.
Ahora, cuando el ancho del contenedor se haga más pequeño, LW
será mayor que 100%
. Entonces, (LW - 100%)
será positivo. Multiplicado por un valor grande, se fija en calc(var(--s)/2 + var(--mh))
, lo que habilita el primer elemento flotante. Para los demás elementos flotantes, (100% - LW + 1px)
se resuelve en un valor negativo y se fija en 0px
, lo que desactiva los elementos flotantes.
Cambie el tamaño de la siguiente demostración y vea cómo cambiamos entre ambas cuadrículas.
Intentemos agregar más elementos:
¿Mira eso? Las cosas están escalando perfectamente. Agreguemos más elementos solo por diversión:
Sigue siendo genial. Observe que la última fila ni siquiera está llena. Simplemente muestra que este enfoque cubre varios casos. También podemos combinar esto con el truco de alineación de cuadrícula CSS que usamos anteriormente:
¿Crees que "flotar" es algo tan malo ahora?
¿Quieres invertir la pirámide?
Como se ilustra en la figura anterior, dos cambios en el código anterior pueden invertir nuestra pirámide:
- Cambio la dirección del gradiente de
to bottom left|right
ato top left|right
, - Agrego un
margin-top
igual a la altura de una fila.
Y oye, podemos intercambiar entre ambas pirámides fácilmente:
¿No es esto hermoso? Tenemos una cuadrícula piramidal responsiva con formas personalizadas que podemos invertir fácilmente y que recurre a otra cuadrícula responsiva en una pantalla pequeña mientras todo está perfectamente centrado. Todo esto sin una sola consulta de medios o JavaScript, sino utilizando la float
propiedad que a menudo se pasa por alto.
Probablemente notarás cierta desalineación en algunos casos particulares. Sí, nuevamente se trata de un problema de redondeo relacionado con el cálculo que estamos haciendo y el hecho de que estamos tratando de hacerlo genérico con las demostraciones interactivas. Para rectificar esto, simplemente ajustamos algunos valores manualmente (especialmente el porcentaje del gradiente) hasta que volvamos a obtener una alineación perfecta.
¡Eso es una envoltura flotante !
Ahí lo tenemos: combinarlo float
puede shape-outside
ayudarnos a crear diseños complejos, flexibles y receptivos: ¡larga vida float
!
El artículo termina aquí pero esto es sólo el comienzo. Te proporcioné el diseño y ahora puedes colocar fácilmente cualquier contenido dentro de los divs, aplicar un fondo, sombras, animaciones, etc.
Deja un comentario