We're looking for a user researcher to understand the needs of developers and designers. Is this you or someone you know? Check out the post: https://mzl.la/2IGzdXS

Relación de Grid Layout con otros métodos de diseño y posicionamiento - CSS

Traducción en curso

CSS Grid Layout ha sido diseñado para trabajar junto con otros elementos de CSS, como parte de un sistema completo para hacer el diseño. En esta guía explicaré cómo se ajusta Grid junto con otras técnicas que ya se estén usando.

Las traducciones posibles a la palabra Grid en este contexto son: Grilla, Rejilla, Cuadrícula, Malla. Para efecto del contenido será Grid.

Grid y flexbox

La diferencia básica entre CSS Grid Layout y CSS Flexbox Layout es que flexbox fue pensado para diseños de una dimensión, en una fila o una columna. CSS Grid Layout se pensó para el diseño bidimensional, en varias filas y columnas al mismo tiempo. Las dos especificaciones comparten algunas características comunes sin embargo, y si ya ha aprendido a cómo utilizar flexbox, verá semejanzas que le ayudarán a entender Grid.

Diseños de Una dimensión vs. dos dimensiones

Un ejemplo simple puede demostrar la diferencia entre el diseño de una y dos dimensiones.

En este primer ejemplo, estoy usando flexbox para diseñar un conjunto de cuadros. Tengo cinco elementos secundarios en mi contenedor y les he dado valores a sus propiedades flex para que puedan aumentar y reducirse desde una base flexible de 200 píxeles.

También he configurado la propiedad wrapflex-wrap , de modo que si el espacio en el contenedor se vuelve demasiado estrecho para mantener la base flexible, los artículos se ajustarán a una nueva fila.

<div class="wrapper">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
  <div>Five</div>
</div>
.wrapper {
  display: flex;
  flex-wrap: wrap;
}
.wrapper > div {
  flex: 1 1 200px;
}

In the image you can see that two items have wrapped onto a new line. These items are sharing the available space and not lining up underneath the items above. This is because when you wrap flex items, each new row (or column when working by column) becomes a new flex container. Space distribution happens across the row.

A common question then is how to make those items line up. This is where you want a two dimensional layout method, you want to control the alignment by row and column. and is where grid comes in.

El mismo diseño con CSS Grid Layout

In this next example I create the same layout using Grid. This time we have three 1fr column tracks. We do not need to set anything on the items themselves, they will lay themselves out one into each cell of the created grid. As you can see they stay in a strict grid, lining up in rows and columns. With five items, we get a gap on the end of row two.

<div class="wrapper">
   <div>One</div>
   <div>Two</div>
   <div>Three</div>
   <div>Four</div>
   <div>Five</div>
</div>
.wrapper {
   display: grid;
   grid-template-columns: repeat(3, 1fr);
}

A very simple question to ask yourself when decided between grid or flexbox is:

  • do I only need to control the layout by row or column – use a flexbox
  • do I need to control the layout by row and column – use a grid

Content out or layout in?

In addition to the one-dimensional versus two-dimensional distinction, there is another way to decide if you should use flexbox or grid for a layout. Flexbox works from the content out. An ideal use case for flexbox is when you have a set of items and want to space them out evenly in a container. You let the size of the content decide how much individual space each item takes up. If the items wrap onto a new line, they will work out their spacing based on their size and the available space in that line.

Grid works from the layout in. When you use CSS Grid Layout you create a layout and then you place items into it, or you allow the auto-placement rules to place the items into the grid cells according to that strict grid. There is the ability to create tracks that respond to the size of the content, however they will also change the entire track.

If you are using flexbox and find yourself disabling some of the flexibility, you probably need to use CSS Grid Layout. An example would be if you are setting a percentage width on a flex item to make it line up with other items in a row above. In that case a grid is likely to be a better choice.

Alineación de la Caja

The feature of flexbox that was most exciting to many of us was that it gave us proper alignment control for the first time. It made it easy to center a box on the page. Flex items can stretch to the height of the flex container meaning that equal height columns were possible. These were things we have wanted to do for a very long time, and have come up with all kinds of hacks to at least create the visual effect of.

The alignment properties from the flexbox specification have been added to a new specification called Box Alignment Level 3. This means that they can be used in other specifications, including Grid Layout. In the future they may well apply to other layout methods as well.

In a later guide in this series I’ll be taking a proper look at Box Alignment and how it works in Grid Layout, here however is a simple example comparing flexbox to grid.

The first example uses flexbox, I have a container with three items inside. The wrapper min-height is set, so it is defining the height of the flex container. I have set align-items on the flex container to flex-end so the items will line up at the end of the flex container. I have also set the align-self property on box1 so it will override the default and stretch to the height of the container and on box2 so it aligns to the start of the flex container.

<div class="wrapper">
   <div class="box1">One</div>
   <div class="box2">Two</div>
   <div class="box3">Three</div>
</div>
.wrapper {
   display: flex;
   align-items: flex-end;
   min-height: 200px; 
}
.box1 {
   align-self: stretch;
}
.box2 {
   align-self: flex-start;
}

Alineación en CSS Grid Layout

This second example uses a grid to create the same layout, this time we are using the box alignment properties as they apply to a grid layout. So we align to start and end rather than flex-start and flex-end. In the case of a grid layout we are aligning the items inside their grid area, in this case that is a single grid cell, but could be an area made up of several grid cells.

<div class="wrapper">
   <div class="box1">One</div>
   <div class="box2">Two</div>
   <div class="box3">Three</div>
</div>
.wrapper {
   display: grid;
   grid-template-columns: repeat(3,1fr);
   align-items: end;
   grid-auto-rows: 200px;
}.box1 {
   align-self: stretch;
}
.box2 {
   align-self: start;
}

La unidad fr y flex-basis

Ya hemos visto que la unidad fr asigna a las pistas del grid (tracks) una proporción del espacio disponible en el grid container. La unidad fr, cuando se combina con la función minmax permite un comportamiento muy similar al de las propiedades flex en flexbox - mientras mantenemos la posibilidad de crear un layout de dos dimensiones.

Si volvemos al ejemplo en el que demostré la diferencia entre layouts de una y de dos dimensiones, puedes ver que hay una diferencia con respecto al funcionamiento responsive en cada una de ellas. En la flex-layout si arrastramos nuestra ventana haciéndola cada vez más pequeña, flex box ajusta el número de ítems en cada fila de acuerdo al espacio disponible. Si tenemos mucho espacio los cinco ítems pueden caber en una fila, pero si tenemos un contenedor muy estrecho podríamos tener espacio solo para uno.

La versión grid, en comparación, siempre tiene tres pistas de columna: son las pistas mismas las que crecen y se encogen, pero siempre hay tres, ya que definimos tres al crear la rejilla.

Auto-filling grid tracks

Podemos crear un efecto similar a flexbox, mientras mantenemos el contenido organizado en filas y columnas concretas mediante la creación de una lista de tracks usando la notación repeat y las propiedades auto-fill y auto-fit.

En el siguiente ejemplo he usado auto-fill en el lugar del número entero de la notación repeat y he establecido la lista de track en 200 píxeles. Esto significa que el grid creará tantas columnas de 200 píxeles como quepan en el container.

<div class="wrapper">
   <div>One</div>
   <div>Two</div>
   <div>Three</div>
</div>
.wrapper {
   display: grid;
   grid-template-columns: repeat(auto-fill, 200px);
}

Una cantidad flexible de tracks

This isn’t quite the same as flexbox, in the flexbox example the items are larger than the 200 pixel basis before wrapping. We can achieve the same in grid by combining auto-fill and the minmax function. In this next example I create auto filled tracks with minmax. I want my tracks to be a minimum of 200 pixels, and I then set the maximum to be 1fr. Once the browser has worked out how many times 200 pixels will fit into the container - also taking account of grid gaps - it will treat the 1fr maximum as an instruction to share out the remaining space between the items.

<div class="wrapper">
   <div>One</div>
   <div>Two</div>
   <div>Three</div>
</div>
.wrapper {
   display: grid;
   grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

We now have the ability to create a grid with a flexible number of flexible tracks, but to see items laid out on the grid aligned by rows and columns at the same time.

El grid y los elementos absolutamente posicionados

La rejilla interactúa con elementos absolutamente posicionados, lo que puede ser útil si quieres colocar un elemento dentro de una rejilla o de un área de la rejilla. La especificación define el comportamiento cuando un grid container es el bloque contenedor donde el grid container es el padre del elemento posicionado absolutamente.

El grid container como bloque contenedor

Para hacer que el grid container sea un bloque contenedor es necesario añadir al container la propiedad position con el valor relative, de la misma manera que harías para cualquier otro bloque contenedor posicionado absolutamente. Una vez hecho esto, si asignas a un grid ítem una position: absolute será tomado como bloque que contiene el grid container o, si el ítem también tiene grid position será del grid en la que está colocado.

En el ejemplo de abajo tengo un wrapper que contiene cuatro ítems hijos, el ítem tres está absolutamente posicionado y también se emplaza en la cuadrícula usando line-based placement. El grid container tiene position: relative y así se convierte en el contexto de posicionamiento de este elemento.

<div class="wrapper">
   <div class="box1">One</div>
   <div class="box2">Two</div>
   <div class="box3">
    This block is absolutely positioned. In this example the grid container is the containing block and so the absolute positioning offset values are calculated in from the outer edges of the area it has been placed into.
   </div>
   <div class="box4">Four</div>
</div>
.wrapper {
   display: grid;
   grid-template-columns: repeat(4,1fr);
   grid-auto-rows: 200px;
   grid-gap: 20px;
   position: relative;
}
.box3 {
   grid-column-start: 2;
   grid-column-end: 4;
   grid-row-start: 1;
   grid-row-end: 3;
   position: absolute;
   top: 40px;
   left: 40px;
}

You can see that the item is taking the area from grid row line 2 to 4, and starting after line 1. Then it is offset in that area using the top and left properties. However, it has been taken out of flow as is usually for absolutely positioned items and so the auto-placement rules now place items into the same space. The item also doesn’t cause the additional row to be created to span to row line 3.

If we remove position: absolute from the rules for .box3 you can see how it would display without the positioning.

A grid container as parent

If the absolutely positioned child has a grid container as a parent but that container does not create a new positioning context, then it is taken out of flow as in the previous example. The positioning context will be whatever element creates a positioning context as is common to other layout methods. In our case if we remove position: relative from the wrapper above, positioning context is from the viewport, as shown in this image.

Image of grid container as parent

Once again the item no longer participates in the grid layout in terms of sizing or when other items are auto-placed.

With a grid area as the parent

If the absolutely positioned item is nested inside a grid area then you can create a positioning context on that area. In the below example we have our grid as before but this time I have nested an item inside .box3 of the grid.

I have given .box3 position relative and then positioned the sub-item with the offset properties. In this case the positioning context is the grid area.

<div class="wrapper">
   <div class="box1">One</div>
   <div class="box2">Two</div>
   <div class="box3">Three
       <div class="abspos">
        This block is absolutely positioned. In this example the grid area is the containing block and so the absolute positioning offset values are calculated in from the outer edges of the grid area.
       </div>
   </div>
   <div class="box4">Four</div>
</div>
.wrapper {
   display: grid;
   grid-template-columns: repeat(4,1fr);
   grid-auto-rows: 200px;
   grid-gap: 20px;
}
.box3 {
   grid-column-start: 2;
   grid-column-end: 4;
   grid-row-start: 1;
   grid-row-end: 3;
   position: relative;
}
.abspos {
   position: absolute;
   top: 40px;
   left: 40px;
   background-color: rgba(255,255,255,.5);
   border: 1px solid rgba(0,0,0,0.5);
   color: #000;
   padding: 10px;
}

Grid and display: contents

A final interaction with another layout specification that is worth noting is the interaction between CSS Grid Layout and display: contents. The contents value of the display property is a new value that is described in the Display specification as follows:

“The element itself does not generate any boxes, but its children and pseudo-elements still generate boxes as normal. For the purposes of box generation and layout, the element must be treated as if it had been replaced with its children and pseudo-elements in the document tree.”

If you set an item to display: contents the box it would normally create disappears, and the boxes of the child elements appear as if they have risen up a level. This means that children of a grid item can become grid items. Sound odd? Here is a simple example. In the following markup I have a grid, the first item on the grid is set to span all three column tracks. It contains three nested items. As these items are not direct children, they don’t become part of the grid layout and so display using regular block layout.

<div class="wrapper">
   <div class="box box1">
       <div class="nested">a</div>
       <div class="nested">b</div>
       <div class="nested">c</div>
   </div>
   <div class="box box2">Two</div>
   <div class="box box3">Three</div>
   <div class="box box4">Four</div>
   <div class="box box5">Five</div>
</div>
.wrapper {
   display: grid;
   grid-template-columns: repeat(3, 1fr);
   grid-auto-rows: minmax(100px, auto);
}
.box1 {
   grid-column-start: 1;
   grid-column-end: 4;
}

If I now add display: contents to the rules for box1, the box for that item vanishes and the sub-items now become grid items and lay themselves out using the auto-placement rules.

<div class="wrapper">
   <div class="box box1">
       <div class="nested">a</div>
       <div class="nested">b</div>
       <div class="nested">c</div>
   </div>
   <div class="box box2">Two</div>
   <div class="box box3">Three</div>
   <div class="box box4">Four</div>
   <div class="box box5">Five</div>
</div>
.wrapper {
   display: grid;
   grid-template-columns: repeat(3, 1fr);
   grid-auto-rows: minmax(100px, auto);
}
.box1 {
   grid-column-start: 1;
   grid-column-end: 4;
   display: contents;
}

This can be a way to get items nested into the grid to act as if they are part of the grid, and is a way around some of the issues that would be solved by subgrids once they are implemented. You can also use display: contents in a similar way with flexbox to enable nested items to become flex items.

As you can see from this guide, CSS Grid Layout is just one part of your toolkit. Don’t be afraid to mix it with other methods of doing layout, to get the different effects you need.

Etiquetas y colaboradores del documento

Colaboradores en esta página: amaiafilo, TavoTrash, aribet, jorgemontoyab
Última actualización por: amaiafilo,