
Si trabaja en aplicaciones web que admiten navegadores más antiguos y ha deseado CSS Grid desde el margen como yo, tengo buenas noticias: ¡he descubierto una forma inteligente solo CSS de usar la ubicación automática de cuadrícula en IE10 +!
Ahora, en realidad no es CSS Grid, pero sin mirar el código en sí, no podría saberlo. La estructura HTML se parece a CSS Grid. Tiene un conjunto definido de columnas con una cantidad indefinida de filas y tiene medianeras que admiten bordes y sombras en las celdas sin cortes. Pero lo que realmente está sucediendo detrás de escena es una combinación de flexbox y márgenes.
En este artículo, explicaré el enfoque. Aquí hay una demostración de lo que estamos viendo:
ver la pluma
Diseño de columna similar a CSS-Grid compatible con IE10 por Brian Holt (@bholtbholt)
en CodePen.
Filas de flujo automático con envoltura flexbox
Cuadrícula de ubicación automática creada por Flexbox
Obtener la configuración básica de la red es muy simple. Si está familiarizado con flexbox, estoy seguro de que ya lo ha adivinado flex-wrap: wrap
es el truco aquí. Y tendrías razón.
Pongamos el marcado HTML en su lugar antes de escribir cualquier CSS. Queremos que se asemeje a la misma estructura que si estuviéramos usando la colocación automática: una .grid
contenedor y un número indefinido de .grid__cell
s.
<div class="grid">
<div class="grid__cell">...</div>
...
</div>
Establecemos tres puntos de interrupción de la cuadrícula. Un diseño de una columna, dos columnas y tres columnas para dispositivos móviles, pantallas pequeñas y pantallas medianas, respectivamente. Estoy usando los puntos de interrupción utilizados en Bootstrap para este artículo, aunque nos gustaría definirlos en puntos reales donde el diseño se rompe si estuviéramos trabajando con contenido real.
$screen-sm-min: 768px;
$screen-sm-max: 991px;
$screen-md-min: 992px;
La cuadrícula móvil primero se colapsa en una sola columna
Un enfoque móvil primero significa que nuestro diseño de una sola columna ya está completo, ya que cada .grid__cell
ya es un bloque. Establecimos .grid
para convertirse en un contenedor de caja flexible después del primer punto de interrupción y envolver las celdas.
@media (min-width: $screen-sm-min) {
.grid {
display: flex;
flex-wrap: wrap;
}
}
Nuestros diseños de dos y tres columnas necesitan anchos explícitos y propiedades flexibles; de lo contrario, se amontonarán en una sola línea. Mientras probaba IE10, experimenté un comportamiento inesperado con el flex-basis
propiedad, y encontró establecer un ancho explícito con flex-basis: auto
era más consistente. Sin embargo, esto no parecía ser un problema con IE11.
.grid__cell {
min-width: 0;
flex: 1 1 auto;
}
// Two-column grid
@media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
$width: 50%;
.grid__cell {
width: $width;
}
}
// Three-column grid
@media (min-width: $screen-md-min) {
$width: 33.33%;
.grid__cell {
width: $width;
}
}
No necesitamos envolver .grid__cell
en una consulta de medios, ya que sus propiedades flexibles no tendrán efecto cuando el padre no sea un contenedor de caja flexible. También definimos un límite superior para la consulta de medios de dos columnas para que no afecte la cuadrícula de tres columnas.
¡Y eso es! Ahora tenemos una cuadrícula flexbox receptiva, fluida y envolvente. La parte fácil está hecha… bueno, siempre y cuando solo tengamos elementos que sean múltiplos de dos y tres. Con flex: 1 1 auto
, el último elemento siempre ocupará el espacio restante en la última fila.
Cuadrícula de dos columnas en pantallas más pequeñas
Grilla de tres columnas en pantallas grandes
Alineación de celdas en la última fila
La última fila elusiva es por qué estamos aquí, ¿verdad? De forma predeterminada, cada celda se extenderá hasta el final de la fila en un diseño flexible, pero la cuadrícula deja un espacio en blanco. ¿Cómo hacemos eso en flexbox? ¡Con pseudo-elementos!
El truco es agregar un pseudo-elemento al .grid
contenedor y configúrelo como una celda. Definimos el :after
celda de pseudo-elemento en cada uno de nuestros puntos de ruptura con el mismo ancho que una celda real.
@media (min-width: $screen-sm-min) {
.grid {
...
&:after {
content: '';
display: block;
flex: 1 1 auto;
}
}
}
@media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
$width: 50%;
.grid:after {
width: $width;
}
}
@media (min-width: $screen-md-min) {
$width: 33.33%;
.grid:after {
width: $width;
}
}
Esto crea una celda falsa que empujará contra nuestras celdas reales y alineará nuestra cuadrícula de dos columnas cuando las celdas sean impares. Dejar su altura indefinida le permite colapsar a la nada cuando las celdas son uniformes.
Cuadrícula de dos columnas con celdas impares, encajando en su lugar
Nuestra cuadrícula de tres columnas es un poco más compleja porque necesitamos manejar múltiples estados, como cuando hay una celda vacía y cuando hay dos celdas vacías.
Cuadrícula de tres columnas con una celda vacía
Nuestro estado de una celda vacía ya está manejado porque en realidad no es diferente de una celda vacía en dos columnas. El :after
celda tiene su ancho establecido y completa la fila. Sin embargo, la historia cambia cuando hay dos celdas vacías porque flex: 1 1 auto
asoma la cabeza de nuevo: la última celda ahora se extiende a lo largo del 50% del ancho cuando se empuja contra el pseudo-elemento.
Cuadrícula de tres columnas con dos celdas vacías
Usando CSS :nth-of-type
selectores, podemos apuntar a la primera columna de cada fila. Dado que nuestras filas son múltiplos de tres, las apuntamos con 3n
luego cuenta hacia atrás por 2
para obtener el primer elemento de cada fila.
@media (min-width: $screen-md-min) {
.grid__cell {
...
&:nth-of-type(3n-2) {
background-color: red;
}
}
}
Orientación a la primera celda de cada fila de tres columnas
En términos generales, nos dirigimos a todas las celdas de la primera columna, pero debemos limitar la selección solo a la última fila. En realidad, debemos limitarlo a cuando es la última celda en la primera columna de la última fila. Afortunadamente, hay un práctico pseudo-selector para apuntar al último elemento de este tipo. encadenamos :last-of-type
para crear la declaración lógica.
@media (min-width: $screen-md-min) {
.grid__cell {
...
&:nth-of-type(3n-2):last-of-type {
background-color: red;
}
}
}
Ahora que tenemos seleccionada la última celda en la primera columna de la última fila, usamos un margen para empujar el :after
celda hasta la última columna y llene la celda del medio.
@media (min-width: $screen-md-min) {
.grid__cell {
...
&:nth-of-type(3n-2):last-of-type {
margin-right: $width;
}
}
}
Aquí está nuestro flexbox-defined-auto-placement-grid-imitator en su totalidad. Mira sus filas bellamente alineadas. ¡Apuesto a que ni siquiera puedes decir que no es CSS Grid!
Nuestra grilla completa de tres columnas.
Adición de medianeras con márgenes
La especificación de CSS Grid tiene un espacio entre columnas y filas para proporcionar espacio entre cada celda. Crear canales en flexbox es mucho más desafiante. Parece que llegará a flexbox, pero aún no hemos llegado… e IE nunca lo estará.
En Daniel Tonónguía de CSS Grid en IE, usó un div de celda interna con márgenes negativos, bordes, un poco de relleno y overflow: hidden
. Aunque tal vez un poco raro, el efecto funciona, pero rompe nuestro deseo de mantener una estructura HTML similar a CSS Grid. El enfoque que prefiero puede parecer un poco tosco, pero también me pareció el más fácil de leer y entender. Además, continúa usando :nth-of-type
pseudo-selectores que hacen que el enfoque general se sienta consistente.
Queremos espacios entre las celdas, pero no alrededor del exterior. También queremos que nuestras celdas queden al ras del contenedor.
Espacios entre las celdas, no en el exterior.
Nuestra cuadrícula móvil o de una sola columna solo necesita un margen inferior en las celdas. Agregamos eso y anulamos la última celda con margin-bottom: 0
para que la celda encaje al ras contra el contenedor. Normalmente usaría initial
, pero no hay soporte en IE.
$col-gap: 16px;
.grid__cell {
...
margin-bottom: $col-gap;
&:last-of-type {
margin-bottom: 0;
}
}
Cuadrícula de una sola columna con espacios entre cada fila
Nuestras cuadrículas de dos y tres columnas necesitan márgenes a la derecha de las celdas, sin márgenes derechos en la última columna y sin márgenes inferiores en ninguna de las celdas de la última fila. Debido a los márgenes, también necesitaremos recalcular nuestros anchos ya que las celdas se envolverán si no encajan.
En un diseño de dos columnas, obtener la columna correcta (o la segunda) es bastante fácil con :nth-of-type(2n)
o :nth-of-type(even)
. Prefiero un multiplicador n por coherencia con nuestra cuadrícula de tres columnas y para calcular la última fila.
Nuestra última fila es un poco más complicada. Cuando tenemos celdas impares, nuestro CSS móvil primero se encarga de eliminar los márgenes inferiores ya que la celda es la :last-of-type
y nuestro :after
la celda no tiene márgenes aplicados.
Dos columnas con celdas pares
Cuando tenemos celdas pares, debemos apuntar a la penúltima celda, pero solo cuando está en la posición de la primera columna. Si no lo calificamos, la penúltima celda crecerá verticalmente para coincidir con la altura de la penúltima fila. Podemos orientarlo con :nth-of-type(2n-1):nth-last-of-type(2)
.
@media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
$width: calc(50% - #{$col-gap});
.grid__cell {
...
margin-right: $col-gap;
// Remove margin in last column
&:nth-of-type(2n) {
margin-right: 0;
}
// For when the last row is complete
// . .
// * .
&:nth-of-type(2n-1):nth-last-of-type(2) {
margin-bottom: 0;
}
}
}
Dos columnas con celdas uniformes que se asientan al ras contra el contenedor
Nuestros canalones de tres columnas adoptan el mismo enfoque. Añadimos margin-right
a todos ellos, elimínelo de la tercera columna y elimine los márgenes inferiores de la última fila. Nuevamente, nuestra última celda es manejada por nuestro enfoque móvil primero, pero ahora debemos cubrir cuándo hay dos celdas en la última fila y cuándo hay tres celdas. Podemos calificar a nuestros selectores con nth-of-type
y nth-last-of-type
.
@media (min-width: $screen-md-min) {
$width: calc(33% - #{$col-gap});
.grid__cell {
...
margin-right: $col-gap;
// Remove margin in last column
&:nth-of-type(3n) {
margin-right: 0;
}
// For when there two items in the last row
// . . .
// * .
&:nth-of-type(3n-2):nth-last-of-type(2) {
margin-bottom: 0;
}
// For when the last row is complete
// . . .
// * * .
&:nth-of-type(3n-1):nth-last-of-type(2),
&:nth-of-type(3n-2):nth-last-of-type(3) {
margin-bottom: 0;
}
}
}
Cuadrícula de tres columnas con canales y una celda vacía
Necesitamos ajustar el margen de la última celda en la última fila cuando está sola debido a las columnas. Utilizamos el 33% más un canalón a cada lado.
@media (min-width: $screen-md-min) {
$width: calc(33% - #{$col-gap});
.grid__cell {
...
// When there is only one item in the last rpw
// Fill the margin so it's like the last item is
// double the width
// . . .
// *->
&:nth-of-type(3n-2):last-of-type {
margin-right: calc(33% + #{$col-gap * 2});
}
}
}
¡Ahora nuestras canaletas están instaladas y la rejilla está completa! Llénalos de bordes, sombras o lo que tu corazón desee.
Grilla completa de tres columnas con canaletas usando flexbox.
Terminando
Aquí está el resultado final una vez más:
ver la pluma
Diseño de columna similar a CSS-Grid compatible con IE10 por Brian Holt (@bholtbholt)
en CodePen.
Creo que esta técnica también podría admitir IE9 con ajustes menores, como usar bloques en línea en lugar de flexbox. También podríamos expandirnos a una cuadrícula de cuatro columnas agregando otro punto de interrupción y usando el mismo enfoque que la cuadrícula de tres columnas. ¡Siéntase libre de usar este enfoque y espero que ayude!