Estilo de celdas vacías con contenido generado y diseño de cuadrícula CSS
Publicado: 2022-03-10Un problema común de diseño de cuadrícula es cuando un recién llegado al método de diseño se pregunta cómo diseñar una celda de cuadrícula que no contiene ningún contenido. En la especificación de nivel 1 actual, esto no es posible ya que no hay forma de apuntar a una celda de cuadrícula vacía o un área de cuadrícula y aplicar estilo. Esto significa que para aplicar estilo, debe insertar un elemento.
En este artículo, voy a echar un vistazo a cómo usar el contenido generado por CSS para lograr el estilo de las celdas vacías sin agregar elementos vacíos redundantes y mostraré algunos casos de uso donde esta técnica tiene sentido.
Echando un vistazo más de cerca a BFC
Si alguna vez ha hecho un diseño con CSS, probablemente sepa qué es BFC. Comprender por qué funciona y cómo crear uno es útil y puede ayudarlo a comprender cómo funciona el diseño en CSS. Leer un artículo relacionado →
¿Por qué no podemos diseñar áreas vacías ya?
El párrafo inicial de la Especificación de red dice:
“Este módulo CSS define un sistema de diseño bidimensional basado en cuadrículas, optimizado para el diseño de la interfaz de usuario. En el modelo de diseño de cuadrícula, los elementos secundarios de un contenedor de cuadrícula se pueden colocar en ranuras arbitrarias en una cuadrícula de diseño flexible o de tamaño fijo predefinida”.
La frase clave aquí es "hijos de un contenedor de cuadrícula". La especificación define la creación de una cuadrícula en el elemento principal, en la que se pueden colocar los elementos secundarios. No define ningún estilo de esa cuadrícula, ni siquiera va tan lejos como para implementar algo como la propiedad column-rule
que tenemos en Diseño de varias columnas. Diseñamos los elementos secundarios, y no la cuadrícula en sí, lo que nos deja con la necesidad de tener algún tipo de elemento al que aplicar ese estilo.
Uso de elementos redundantes como gancho de estilo
Una forma de insertar algo al estilo es insertar un elemento redundante en el documento, por ejemplo, un lapso o un div. A los desarrolladores suele no gustarles esta idea, a pesar de que han estado agregando "envolturas de fila" redundantes adicionales durante años para lograr diseños de cuadrícula utilizando flotadores. ¡Quizás ese elemento obviamente vacío es más desagradable que la redundancia un tanto escondida del elemento envoltorio!
Los elementos completamente vacíos se convierten en elementos de cuadrícula y se les pueden agregar fondos y bordes al igual que un elemento que contiene contenido, como lo demuestra este ejemplo.
Eric Meyer, en su artículo A List Apart Faux Grid Tracks, aboga por usar el elemento b
como su elemento redundante de elección, ya que no confiere significado semántico, es corto y también bastante obvio en el marcado como gancho.
Es poco probable que insertar algunos elementos div
o b
adicionales sea el mayor crimen contra el buen marcado que jamás haya cometido, por lo que no perdería el sueño si eligiera ese enfoque si fuera necesario. El desarrollo web muy a menudo implica elegir el enfoque menos subóptimo para hacer el trabajo hasta que se idee una mejor solución. Sin embargo, prefiero mantener mi estilo en un solo lugar si es posible, de forma segura en la hoja de estilo. Por lo menos, facilita la reutilización de estilos, sin necesidad de preocuparse por el marcado adicional requerido. Es por esta razón que tiendo a mirar el contenido generado, algo con lo que estoy muy familiarizado por el trabajo que he hecho formateando libros con CSS, donde pasas la mayor parte de tu tiempo trabajando con esta característica.
Uso del contenido generado como gancho de estilo
El contenido generado por CSS utiliza las ::before
y ::after
CSS junto con la propiedad de content
para insertar algún tipo de contenido en el documento. La idea de insertar contenido podría llevarlo a pensar que esto es para insertar texto y, si bien esto es posible, para nuestros propósitos, estamos interesados en insertar un elemento vacío como elemento secundario directo de nuestro Contenedor de cuadrícula. Con un elemento insertado podemos darle estilo.
En el siguiente ejemplo, tengo un elemento contenedor, que se convertirá en mi Grid Container, con otro elemento anidado dentro. Este único hijo directo se convertirá en un elemento de cuadrícula. Definí una cuadrícula de tres columnas y tres filas en el contenedor y luego coloqué el elemento único usando Líneas de cuadrícula, por lo que se encuentra en la Celda de cuadrícula central.
<div class="grid"> <div class="item"></div> </div>
.grid { display: grid; grid-template-columns: 100px 100px 100px; grid-template-rows: 100px 100px 100px; grid-gap: 10px; } .grid > * { border: 2px solid rgb(137,153,175); } .item { grid-column: 2; grid-row: 2; }
Si echamos un vistazo a este ejemplo, usando Firefox Grid Inspector para superponer las líneas de la cuadrícula, podemos ver cómo existen las otras celdas vacías de la cuadrícula; sin embargo, para agregarles un fondo o un borde, necesitaríamos agregar elementos secundarios adicionales. elementos. Que es exactamente lo que permite el contenido generado.
En mi CSS, agrego una cadena vacía, ::before
y ::after
mi contenedor Grid. Estos se convertirán inmediatamente en elementos de cuadrícula y se estirarán para llenar su contenedor. Luego agrego el estilo que necesito para los cuadros, en este caso, agrego un color de fondo, y los coloco como lo haría con cualquier elemento de cuadrícula normal.
.grid::before { content: ""; background-color: rgb(214,232,182); grid-column: 3; grid-row: 1; } .grid::after { content: ""; background-color: rgb(214,232,182); grid-column: 1; grid-row: 3; }
En el documento todavía tenemos solo un elemento secundario, los elementos de estilo redundantes están contenidos en el CSS, lo que parece perfectamente razonable ya que solo están ahí para fines de estilo.
Limitaciones del enfoque de contenido generado
El problema obvio con este enfoque se hará evidente si decide que también le gustaría diseñar las celdas de cuadrícula superior derecha e inferior izquierda. Solo puede aplicar una parte del contenido generado en la parte superior y otra en la parte inferior del contenedor; no se permiten varios pseudoelementos ::before
y ::after
. ¡El método no funcionará si desea crear un tablero de ajedrez CSS Grid! Si encuentra que necesita hacer muchos estilos de celdas vacías, entonces, en el futuro previsible, es probable que el enfoque de "Relleno B" explicado anteriormente sea su mejor opción.
El método de contenido generado también podría confundir a un futuro desarrollador que trabaje en su proyecto. Como estamos apuntando al contenedor, si reutiliza esa clase en otro lugar, traerá el contenido generado, esto es útil si eso es lo que desea. En el siguiente ejemplo, hemos agregado líneas decorativas a cada lado de un encabezado, sería razonable que cada instancia de h1
tuviera esas líneas. ¡Sin embargo, sería muy confuso si no supieras que esto va a suceder! Una línea de comentarios sobre las reglas del contenedor ayudará aquí. Tiendo a trabajar en estos días en una biblioteca de patrones, lo que realmente ayuda a que estos componentes estén ordenados en un solo lugar, lo que hace que sea más obvio lo que sucede cuando se aplica una clase a un elemento.
Encabezados de lujo
Uno de mis trucos favoritos de contenido generado es diseñar encabezados. En el pasado, tenía que hacer retroceder los estilos de encabezado que requerían envolturas adicionales y pistas de posicionamiento absoluto para lograrlo. Cuando el contenido proviene de un CMS, a menudo es imposible agregar esos envoltorios redundantes.
Con Grid y el contenido generado, podemos agregar una línea a cada lado de nuestro encabezado sin agregar ningún marcado adicional. La línea crecerá y se reducirá según el espacio disponible y volverá a caer elegantemente a un encabezado centrado cuando Grid no esté disponible en los navegadores.
Nuestro marcado es un simple h1
.
<h1>My heading</h1>
En las reglas para el h1
, creo una cuadrícula de tres columnas. El valor de grid-template-columns
da una pista de 1fr
, luego una de auto
y una pista final de 1fr
. Las dos pistas 1fr
compartirán el espacio disponible que queda después de que el encabezado haya ocupado el espacio que necesita para colocarse dentro de la pista de tamaño auto
.
Agregué la propiedad text-align
con un valor de center
para que mi encabezado se ingrese en navegadores sin cuadrícula.
h1 { text-align: center; display: grid; grid-template-columns: 1fr auto 1fr; grid-gap: 20px; }
Ahora agregamos nuestro contenido generado, para agregar una línea antes y después del texto del encabezado. Envuelvo estas reglas en una consulta de características, por lo que no obtenemos ningún contenido extraño generado en navegadores sin diseño de cuadrícula.
La línea en sí es un borde en el elemento generado.
@supports (display: grid) { h1:before, h1:after { content: ""; align-self: center; border-top: 1px solid #999; } }
¡Eso es todo lo que necesitas hacer! Puede usar la misma técnica para agregar cualquier estilo, o incluso un ícono en ambos lados de un elemento, encima o debajo del elemento. Al colocar su elemento en una pista separada, sabe que no hay posibilidad de que el elemento termine superponiéndose al texto del encabezado, lo que suele ser el problema cuando se intenta hacer este tipo de cosas con posicionamiento absoluto. También tiene la ventaja de las formas precisas en que los elementos se pueden alinear entre sí en la cuadrícula.
Este es un buen ejemplo de una mejora posible utilizando el diseño de cuadrícula que podría aprovechar incluso si aún no está listo para dirigirse directamente a un rediseño importante utilizando la cuadrícula. Recurre muy bien a un encabezado sencillo, las personas con navegadores compatibles obtienen el toque adicional y todos obtienen el contenido. Eric Meyer adoptó un enfoque similar, utilizando contenido generado para agregar citas fácilmente modificables y posicionables a un elemento de cita en bloque.
Con estas pequeñas funciones, a menudo no empiezo a pensar que voy a utilizar Grid Layout. Cuando empiezo a descubrir cómo implementar mi diseño, me doy cuenta de que es el método de diseño a elegir. Es por esta razón que animo a las personas a no pensar en Grid como un diseño de página sobre componentes, si lo hace, podría perder muchas oportunidades en las que puede ayudar.
Agregar fondos y bordes a áreas de su diseño
También podemos usar contenido generado para apilar elementos; el hecho es que más de un elemento puede ocupar una celda de cuadrícula en particular. Esto puede incluir aquellos elementos insertados con contenido generado.
En el siguiente ejemplo, tengo un diseño con dos secciones de contenido y un elemento de ancho completo. Detrás del contenido hay un fondo que también se ejecuta debajo del elemento de ancho completo.
El marcado tiene un contenedor con las secciones y el elemento de ancho completo como elementos secundarios directos, y estoy usando la ubicación basada en líneas para colocar mis elementos en la cuadrícula.
<article class="grid"> <section class="section1"> <p>…</p> </section> <div class="full-width"> <img src=“placeholder.jpg” alt=“Placeholder”> </div> <section class="section2"> <p>…</p> </section> </article>
.grid { display: grid; grid-template-columns: 1fr 20px 4fr 20px 1fr; grid-template-rows: auto 300px auto; grid-row-gap: 1em; } .section1 { grid-column: 3; grid-row: 1; } .section2 { grid-column: 3; grid-row: 3; } .full-width { grid-column: 1 / -1; grid-row: 2; background-color: rgba(214,232,182,.5); padding: 20px 0; }
Esto me da el diseño con la imagen de ancho completo y dos secciones de contenido colocadas; sin embargo, si agrego el fondo a las secciones, se detendrá sobre el row-gap
entre la section
y la imagen de ancho completo.
.section { background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); }
Si elimináramos el grid-row-gap
y usáramos relleno para hacer el espacio, aún no habilitaría el efecto del fondo que se ejecuta debajo del panel de ancho completo.
Aquí es donde podemos usar el contenido generado. Agrego contenido generado ::before
del contenedor de cuadrícula y le doy un color de fondo. Si no hago nada más, esto colocará el contenido en la primera celda de la cuadrícula.
.grid::before { content: ""; background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); }
Luego puedo colocar el contenido usando el posicionamiento basado en líneas para estirar sobre el área que debería mostrar el color de fondo.
.grid::before { content: ""; background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); grid-column: 2 / 5; grid-row: 1 / 4; }
Puedes ver el ejemplo completo en este CodePen.
Controlando la pila con z-index
En el ejemplo anterior, el contenido generado se inserta con ::before
. Esto significa que los otros elementos vienen después, está en la parte inferior de la pila y, por lo tanto, se mostrará detrás del resto del contenido, que es donde lo quiero. También puede usar z-index
para controlar la pila. Intente cambiar el selector ::before
a ::after
. El fondo del contenido generado ahora se encuentra encima de todo, como puede ver por la forma en que el borde se extiende sobre la imagen. Esto se debe a que ahora se ha convertido en lo último en el contenedor de cuadrícula, se pinta en último lugar y, por lo tanto, aparece "en la parte superior".
Para cambiar esto, debe otorgarle a este elemento una propiedad de z-index
más baja que todo lo demás. Si nada más tiene un valor z-index
, lo más simple que puede hacer es darle a su contenido generado un z-index
de -1
. Esto hará que sea lo primero en la pila, como el elemento con el z-index
más bajo.
.grid::after { z-index: -1; content: ""; background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); grid-column: 2 / 5; grid-row: 1 / 4; }
Agregar fondos de esta manera no necesita limitarse a dejar un fondo completamente detrás de su contenido. Poder resaltar bloques de color detrás de parte de su diseño podría crear algunos efectos interesantes.
¿Es esto algo que la especificación podría resolver en el futuro?
Agregar fondos y bordes se siente como una característica faltante de la especificación de CSS Grid y una que el grupo de trabajo ha discutido junto con muchos miembros de la comunidad (el hilo de discusión está en GitHub).
Si tiene casos de uso que no se resuelven fácilmente con contenido generado, agregue sus pensamientos a ese hilo. Sus comentarios y casos de uso ayudan a demostrar que hay interés de los desarrolladores en la función y también garantizan que cualquier propuesta cubra el tipo de cosas que necesita hacer.
¡Más ejemplos, por favor!
Si este artículo te anima a experimentar con el contenido generado o, si ya tienes un ejemplo, añádelo a los comentarios. Todos son nuevos en el uso de Grid en la producción, por lo que hay muchos, " ¡Nunca pensé en eso! ” Momentos para tener, ya que combinamos Grid con otros métodos de diseño.