During the last months as part of my work in Igalia I’ve been focused on finishing the new/missing bits of the CSS Grid Layout Blink’s implementation related to items placement. In summary the task was mostly related to 2 things:
Support implicit grid before explicit. So the grid can add tracks on demand not only on the growing direction (usually right/bottom) but also on the opposite one.
Fix unknown named grid lines resolution. This is the case when an item is placed in a line called “
foo”, but no lines with that name exist in the grid.
These might seem quite simple tasks, but they implied quite a lot of changes in the underlying implementation. I ended up refactoring all the code to resolve grid positions in order to complete them. I even wrote a document explaining the whole plan and all the technical details, where you can find links to all the related patches.
Now that we’ve finished this, it’s time to explain how you can use it. Although my colleague Sergio already wrote about this in 2014, the specification has changed since that time, so I think it’s better to try to explain the whole thing from scratch. This post is a kind of summary with examples of “Placing Grid Items” section of the CSS Grid Layout spec.
This is probably one of the most important concepts of the grid layout spec.
The grid lines are the ones dividing horizontally and vertically a grid.
And they’re actually numbered, starting at
Let’s use a 3x2 grid as example to explain how this works:
Grid placement properties
In order to position the items inside the grid container, you need to use the grid placement properties. These properties are:
grid-column-start: Set the first vertical line for the item.
grid-column-end: Set the last vertical line for the item.
grid-row-start: Set the first horizontal line for the item.
grid-row-end: Set the last horizontal line for the item.
With these properties you define the area where the grid item will be placed. In order to do that, you use the line numbers.
The initial value for these properties is
auto, which makes possible
that items are automatically placed looking for empty cells inside the grid.
For more information about this, please review a previous post on the matter.
On top of that, there’re some handy shorthands:
grid-column: Shorthand for
grid-row: Shorthand for
grid-area: Shorthand to set the 4 placement properties in just one declaration.
So, imagine that you add the following item in the previous grid:
Probably easier to read if you use some shorthands:
This means that the grid item will be placed taking the 2nd and 3rd columns in the first row.
Previous item was spanning 2 columns (2nd and 3rd ones) referencing the lines.
You could do the same using the
together with the number of cells you want to span.
So, you could place the item in the very same position using:
Note that here you’re not setting the end line for the row.
This means that
grid-row-end takes a value of
In this case
auto defaults to a span of one.
Negative line numbers
So far we’ve only seen positive numbers, but lines have also negative indexes. Negative numbers allow you to reference the lines starting from the end of the grid.
Following with the same example, you could place the item again in the same position using the negative indexes:
This might be really useful in some situations.
For example, if you want to be sure that the item is in the last column,
independently of the number of tracks,
you’ll just need to set:
Named grid lines
Not only that, but you can also name the grid lines, so you don’t need to remember the specific number to reference to them.
Let’s modify the definition of the grid, keeping the size of tracks but adding names to the lines:
And again if we want to place the item in the same position, we just need to reference the name of the lines:
One line can have several names, you just need to set them in the definition:
grid-template-rows: [top start] 100px [middle center] 50px [bottom end];.
Also the names of the lines can be repeated. To reference them you’ve to use a number that can be again positive or negative. Let’s use a different example to showcase this:
And imagine that you place some items like this:
And of course, you can span to a named grid line:
Better still, you can define grid areas and place items directly on them.
You have to use the
to put names to the different areas in your grid.
And you could use the
grid-area shorthand directly to place the items.
Let’s use a bigger grid (5x4) to show an example:
And position one item in each of the areas:
Grid areas & Named grid lines
One interesting thing about areas and placement is that grid areas
create implicit names for the grid lines surrounding them.
These implicit names use the “
-start” and “
And you can reference those lines when placing an item,
instead of using the whole area.
E.g. the “
title” area from previous example
creates 4 implicit names for the lines (2 in each axis):
- Left line: “
- Right line: “
- Top line: “
- Bottom line: “
Following with that example you could place an item using the implicit names:
And the same can happen the other way around. If you name lines using those suffixes, you’re actually creating implicit areas. So, we could just create the very same grid using named grid lines:
All the examples of items positioned in this section will be exactly in the same place with this new grid.
With the grid definition properties
you determine the explicit number of tracks (columns and rows) in your grid.
However, grid spec allows you to place items outside of the explicit grid.
In order to support that, implicit tracks are created automatically,
the size of these tracks is controlled
In the following examples I’ll use red color
to highlight the implicit lines.
This time let’s use a simple 2x1 grid:
And imagine that you place an item in the 5th column (
As the grid only has 2 columns, 3 implicit columns
will be added in order to position the item.
Again you can also create implicit tracks with items that span several cells.
For example, if an item takes 3 columns starting on the 2nd one
grid-column: 2 / span 3);
Originally, the implicit tracks could only be added at the end.
But now it’s possible to add implicit tracks before the explicit grid.
For example, if you place an item using
it’ll add 2 columns on the left and it’ll be placed in the -2nd column.
Implicit grid & Named grid lines
But this is not the only way to create implicit tracks, you can also create them if you use undefined named grid lines. This is more a way to show mistakes on the user CSS than a feature itself, but maybe someone finds it useful. The idea is that all the lines in the implicit grid will take any random name you might need to position an item.
The basic example is placing items referencing
a nonexistent line called “
For example you will create 3 implicit columns
(1 before and 2 after the explicit grid)
with the following items:
Note that the simplest example
is being placed in the 4th column
(adding an extra empty column just after the explicit grid).
This is because first line that is considered to be called “
is the first implicit line (line 4),
so last line of the grid (line 3) is not included.
Also, the last item
grid-column: -1 foo is placed on the -1th column
(maybe you was not expecting that).
This is because of you start looking for a line named “
from the edge of the explicit grid.
So, you ignore lines -1, -2 and -3 (as they’re not called “
and consider line -4 (first line on the implicit grid) to have that name.
This is a bit trickier if the line actually exists, as you’ve to count it too in order to place the item. Specially it’s complex if you’re using span to a named grid line, but there’re not enough lines. In that case only implicit lines in the search direction are considered to have that name.
Again, hopefully an example can help to understand this. Let’s add a name to the middle line in the previous example:
And now, let’s use place a few items referencing that “
The strange case here is
grid-column: span 2 middle / 5;,
as you can see it takes from -1th column to 4th column (both included).
The item ends at line 5,
and it has to span 2 lines called “
middle” to find the start.
You could think that it should count line 4 and line 2,
but, as explained before,
you have to start counting lines from the edge of the explicit grid.
So you actually count line 2
and then you’ve to consider the implicit lines on the left
to find the start position (line -4).
Grid placement properties have a few special situations that are resolved by the conflict handling section of the spec.
For example, if you place an item where
the end line is before than the start line, both lines are swapped.
Thus, something like
grid-column: 5 / 2; would become
grid-column: 2 / 5;.
Another situation is the one in which you have
in both the start and end positions.
span for the end position is discarded.
grid-column: span 2 / span 3; would become
grid-column: span 2;.
Which will use the grid placement algorithm to find an empty area
(of 2 columns in this particular example) to position itself.
Last one is the case when you only have a
span to named grid line.
In that case, it’s replaced by
grid-column: span foo; will become
grid-column: span 1;.
If you have read that far it seems you’re really interested on CSS Grid Layout. The main conclusion is that the specification is really flexible regarding how to place items on the grid. As you can see there’re quite a lot of different ways to position an item in the very same place. Probably each person will get used to a few of them and just forget about the rest.
IMHO the basic stuff (line indexes, spans, line names and areas) is quite straightforward. And the implicit grid is not that hard either. Then negative indexes bring some fun. However undefined named grid lines behavior is really tricky (hopefully not something you should care about anyway). But it’s true that I’m biased as I’ve been dealing with this for a long time.
Last, I thought it would be nice to finish this with a big example which uses most of the things described in this post. If you got it right and don’t get confused at all you’re mastering grid layout placement. Congrats! 😄
This is the definition of the grid container used in this example:
And in the next picture you can see how different items will be placed.
You can try it live in our examples repository: http://igalia.github.io/css-grid-layout/grid-placement.html
As commented on the introduction Blink’s implementation should support now (Chrome 50+) all these different placement possibilities. Igalia has been working on this implementation and we’re porting it now to WebKit too.
On the other side, Gecko has already support for it too, in this case developed by Mozilla.
- Russian (February 3, 2016): Подробно о размещении элементов в грид-раскладке (CSS Grid Layout)
- Spanish (February 7, 2016): Guía exhaustiva de colocación de elementos en el Grid Layout
- French (February 23, 2016): Le positionnement dans les Grilles CSS