Thursday, January 26, 2017

A Step by Step Guide to the Auto-Placement Algorithm in CSS Grid

Auto-placement algorithm in CSS Grid Layout module

In this tutorial, I'll be going over all the steps the auto-placement algorithm of the CSS Grid Layout module follows when positioning elements. These steps are controlled by the grid-auto-flow property.

In Introducing the CSS Grid Layout and Seven Ways You Can Place Elements Using CSS Grid Layout, I gave an overview of the CSS Grid spec and explained all the different ways Grid lets you arrange elements on the web. However, in my previous articles I explicitly specified the position of just one element in the grid. As for the rest of the items, they got placed properly based on an algorithm.

Here, I am going to show you how this algorithm works. This way, the next time an element ends up in an unexpected location, you are not left scratching your head wondering what just happened.

Basic Concepts for a Better Grasp of the Auto-placement Algorithm

Let's go over some fundamental concepts before diving into the workings of the algorithm.

  • Anonymous grid items - If you place some text directly inside a grid container without wrapping it in any tag, it will form its own anonymous grid item. You can't style an anonymous grid item because there is no element for you to style, but it still inherits style rules from its parent container. On the other hand, note that white space inside the grid container will not create its own anonymous grid item
  • Value of grid spans - Unlike grid positions, the algorithm has no special rules to resolve the value of grid spans. If not explicitly specified, their value is set to 1 (the item only occupies its own cell)
  • Implicit grid - The grid built on the basis of the value of properties like grid-template-rows, grid-template-columns and grid-template-areas is called explicit grid. Now, if you specify the position of a grid item in such a way that it lies outside the bounds of the explicit grid, the browser will generate additional grid lines to accommodate the item. These lines, along with the explicit grid, form the implicit grid. You can read more about it in Where Things Are at in the CSS Grid Layout Working Draft. The auto-placement algorithm can also result in the creation of additional rows or columns in the implicit grid.

Finally, I'd like to make the following preliminary point. The default value of the grid-auto-flow property, which is the property controlling the algorithm, is row. This is also the value I am going to assume in the following explanation of the auto-placement algorithm. On the other hand, if you explicitly set the above property to column, remember to replace instances of the term row with the term column in my explanation of the algorithm. For example, the step "Placement of Elements With a Set Row Position but No Set Column Position" will become "Placement of Elements With a Set Column Position but No Set Row Position".

Now, let's go over the details of all the steps the algorithm follows to build the layout.

Step #1: Generation of Anonymous Grid Items

The first thing that happens when the algorithm is trying to place all the items inside a grid is the creation of anonymous grid items. As I mentioned earlier, you cannot style these elements because there is no item to apply the style to.

The markup below generates an anonymous grid item from the inter-element text:

[code language="html"]
<div class="container">
<span class="nonan">1</span>
Anonymous Item
<div class="nonan floating">2</div>
<div class="nonan">3</div>
<div class="nonan floating">4</div>
<div class="nonan">5</div>
</div>
[/code]

Besides the generation of an anonymous item, one more thing to notice in the demo below is that the grid placement algorithm ignores the CSS floats applied to div 2 and div 4 .

See the Pen Anonymous Grid Items by SitePoint (@SitePoint) on CodePen.

Step #2: Placement of Elements with an Explicitly Specified Position

For this and the next few steps, I will be using a grid of nine different items to show how they are going to be placed.

Here's the relevant markup:

[code language="html"]
<div class="container">
<div class="item a">A</div>
<div class="item b">B</div>
<div class="item c">C</div>
<div class="item d">D</div>
<div class="item e">E</div>
<div class="item f">F</div>
<div class="item f">G</div>
<div class="item f">H</div>
<div class="item f">I</div>
</div>
[/code]

The first items to be placed in the grid are those with an explicitly set position, which in the example below are items A and B. Just ignore all other items in the grid for now. Here is the CSS that explicitly sets the position of A and B:

[code language="css"]
.a {
grid-area: 1 / 2 / 2 / 3;
}

.b {
grid-area: 2 / 1 / 4 / 3;
}
[/code]

Explicitly set position of A and B

The algorithm positions items A and B according to the values of their respective grid-area property. In particular, the algorithm:

  • Sets the position of the top left corner of both A and B using the first and second value of the grid-area property
  • Sets the position of the bottom right corner of both A and B using the third and fourth value of thegrid-area property.

The demo below illustrates the final placement of A and B after this step:

See the Pen Placing Elements with Explicit Positions by SitePoint (@SitePoint) on CodePen.

Step #3: Placement of Elements With a Set Row Position but No Set Column Position

Next, the algorithm places the elements whose row position has been set explicitly by using the grid-row-start and grid-row-end properties.

For this example, I will be setting only the grid-row values of item C and item D to give them a definite row position. Here is the CSS for placing both of them:

[code language="css"]
.c {
grid-row-start: 1;
grid-row-end: 3;
}

.d {
grid-row-start: 1;
grid-row-end: 2;
}
[/code]

To determine the column position, which is not explicitly set, the algorithm behaves in one of two ways, according to the packing mode:

  • sparse packing (default)
  • dense packing

Sparse Packing in Step #3

This is the default behavior. The column-start line of our item will be set to the smallest possible line index which ensures that there won't be any overlap between the item's own grid area and the cells already occupied by other items. The column-start line also needs to be past any other item already placed in this row by this step. Please note that I wrote by this step and not until this step.

Placement of items C and D

To clarify this point further, item D in the demo below did not move to the left of item A, even though it could fit in there without any overlap. This is due to the fact that the algorithm does not allow any item with an explicitly set row position but not set column position to be placed before any other similarly positioned item in that specific row (item C in this case). In fact, if you remove the grid-row rules applied to item C, then item D will move to the left of item A.

In short, item D, which has a definite row position but no explicitly set column position, can end up being placed before item A, but only if C does not interfere (interference takes place in this case because C, like D, has a definite row position but no set column position and is in the same row as D).

See the Pen Placing Elements with Definite Grid Positions by SitePoint (@SitePoint) on CodePen.

Dense Packing in Step #3

If you want to fill that empty space before item A with item D, you will have to set the value of the grid-auto-flow property to row dense.

[code language="css"]
.container {
grid-auto-flow: row dense;
}
[/code]

Placement of D before A using the dense value of the grid-auto-flow property

In this case too, the column-start line is placed at the smallest index which does not cause any overlap with other grid items. The only difference is that this time, if there is some empty space in a row where our element can fit without any overlap, it will be placed in that position, without considering the previous item in the same row with the same position rules (in this case item C).

See the Pen Elements with Definite Grid Positions - Dense by SitePoint (@SitePoint) on CodePen.

Continue reading %A Step by Step Guide to the Auto-Placement Algorithm in CSS Grid%


by Nitish Kumar via SitePoint

No comments:

Post a Comment