grid-row-end

Avatar of Mojtaba Seyedi
Mojtaba Seyedi on (Updated on )

The grid-row-end CSS property is part of the CSS Grid Layout specification, used to indicate the row grid line where a grid item ends in a grid layout. This property — among other line-based placement grid properties — controls the size of a grid item and where it sits on the grid.

.grid-container {
  display: grid;
  grid-template-rows: 100px 100px 100px;
  grid-template-columns: 1fr 1fr 1fr;
}

.grid-item:nth-child(2) {
  grid-row-end: 3; /* Item ends on the third row line */
}

Based on CSS Grid’s default auto-placement behavior, the second child element of the grid in this example should be placed in the first row and the second column. But we declared a grid-row-end position on the second row grid line, moving the grid item into the second row and aligning its ending edge with the third row grid line.

Three by three grid of white rectangles on an orange background. The first item in the second row is green and numbered two.
Shifting the second grid item into the second row using the grid-row-end CSS Grid property.

Syntax

grid-row-end: <grid-line>
Full definition
where
<grid-line> =
  auto |
  <custom-ident> |
  [ [ <integer [−∞,−1]> | <integer [1,∞]> ] && <custom-ident>? ] |
  [ span && [ <integer [1,∞]> || <custom-ident> ] ]

  • Initial value: auto
  • Applies to: grid items and absolutely-positioned boxes whose containing block is a grid container
  • Inherited: no
  • Computed value: as specified
  • Animation type: discrete

Values

/* Keyword value */
grid-row-end: auto;

/* <custom-ident> value */
grid-row-end: myLineName;
grid-row-end: myGridArea;

/* <integer> + <custom-ident> values */
grid-row-end: 3;
grid-row-end: -2;
grid-row-end: main-area 2;
grid-row-end: 3 product-end;

/* span + <integer> + <custom-ident> values */
grid-row-end: span 3;
grid-row-end: span main;
grid-row-end: span myarea 5;

/* Global values */
grid-row-end: inherit;
grid-row-end: initial; /* same as `auto` */
grid-row-end: revert;
grid-row-end: revert-layer;
grid-row-end: unset;

auto

This is the default value. It indicates the default span (1) and auto-placement behavior, which means the grid item is automatically placed in the next available empty grid cell.

<custom-ident>

This syntax allows you to either use an integer to refer to a numbered grid line or a string to refer to a named grid line or a named grid area. In other words, you can specify a grid line by its numerical index or name to the ending edge of a grid item.

Positioning items by line numbers

There are two grid lines before and after each grid track with a numerical index assigned to them automatically, starting from number one.

Three by three grid of white rectangles against an orange background.
This figure only shows the index of row grid tracks

In the first example of this article, we used this syntax to refer to the third grid line by its index (3) to align the ending edge of the grid item with the ending edge of the second row using the <custom-ident> syntax:

.grid-item:nth-child(2) {
  grid-row-end: 3;
}

Note that you can also use a negative number (e.g. -1) to refer to a grid line, but remember that it counts starting from the ending edge of the grid. The following code points to the same grid line in the previous example, but counting in reverse:

.grid-item:nth-child(2) {
  grid-row-end: -2; /* same as 3 */
}

Notice the negative integers have been assigned to our grid as well as positive ones:

Three by three grid of white rectangles on an orange background. The first item in the second row is green and numbered two.
Shifting the second grid item into the second row using the grid-row-end CSS Grid property.
Positioning items by line names

You can assign a custom name to a grid line using grid-template-columns and grid-template-rows and use line-based placement grid properties to refer to that line by its name.

Let’s go back to our example and name all its row track lines like the following declaration:

.grid {
  display: grid;
  grid-template-rows: [first] 100px [second] 100px [third] 100px [last];  
  grid-template-columns: 1fr 1fr 1fr;
}

We can refer to the third line by our custom name instead of its index:

.grid-item:nth-child(2) {
  grid-row-end: third; /* same as index number 3 */
}

Note that the <custom-ident> cannot take the span value since span is a reserved keyword for grid placement properties (e.g. grid-column: 1 / span 2).

Positioning items by grid areas

When defining grid areas using the grid-template-areas property, you get implicit line names for free based on the name of the areas. For instance, a grid area with the name header generates a line name header-start before it and a header-end after it. You can refer to these lines to set the position of a grid item.

.grid-item:nth-child(2) {
  grid-row-end: header-end;
}

Alternately, you can refer to the area’s name to position an item at the end line of the header named area:

.grid-item:nth-child(2) {
  grid-row-end: header;
}

Since you are using the grid-row-end property in this example, the browser understands that you want the header-end line of the header area; therefore, it will align the ending edge of the grid item with the ending edge of the grid area.

Here is a full example:

<body>
  <header></header>
  <main></main>
  <footer></footer>
</body>
body {
  display: grid;
  grid-template-rows: min-content 1fr min-content;   
  grid-template-areas: 
    "header"
    "main"
    "footer";
}

header {
  grid-row-end: header;
}

This sets the position of the <header> element to the header area in our grid.

<integer> && <custom-ident>?

This flavor of syntax allows you to position grid items by grid lines when there are repeated names. If there are grid lines with the same name, this syntax helps specify which of those lines you are referring to.

.grid {
  display: grid;
  grid-template-rows: [bar] 100px [foo] 100px [bar] 150px [bar];
}

Let’s assume you want to choose the fourth line, but that line has the same name as the first and the third grid line — all of them are called bar. Since the third line named bar is the fourth grid line, you can use 3 to select it as the ending point:

.grid-item:nth-child(2) {
  grid-row-end: 3 bar; /* The third `bar` named line which is the fourth line */
}
A single column layout of white rectangles with three rows. The second item is placed in the third row and is green.

Note that the order doesn’t matter, so the previous code can also be written like this as well:

.grid-item:nth-child(2) {
  grid-row-end: bar 3;
}

Like the previous syntax, you can use a negative integer to count the grid lines starting from the end edge of the grid too. In our example, if we want to refer to the first bar, we can count starting from the ending edge of our grid and write it like this:

.grid-item:nth-child(2) {
  grid-row-end: -3 bar;
}

Note that the integer value cannot be zero because lines are assigned non-zero values.

span && [ <integer> || <custom-ident> ]

This syntax allows a grid item to span across the grid tracks. It can be specified in three different ways.

If the integer is not specified anywhere in this syntax, the default value is 1.

span <integer>

Using the span keyword followed by an integer indicates the number of tracks a grid item spreads across, starting from a specific grid line. For example, if we want a grid item to span three row tracks towards its ending edge, we can apply the following value:

.grid-item:nth-child(2) {
  grid-row-end: span 3;
}
A three by four grid  where the second item is green, in the second column, and spans the first three rows.
The grid item spans three rows using the grid-row-end CSS property.
span <custom-ident>

You can combine span with a name of a grid line to make the grid item expand until it reaches that specified grid line.

.grid-item:nth-child(2) {
  grid-row-start: 3;
  grid-row-end: span lastline;
}

Since the start line of the grid item is known (3) we can span the item towards the end line until it hits a grid line named lastline.

The grid item spans across grid until it hits the specified grid line named lastline using the grid-row-end property.
span <custom-ident> <integer>

If the specified grid line name is assigned to more than one grid line — in other words, if we have repeated named grid lines — we need to say which ones we want to target. To do that, we can add an integer to our value specifying which grid line we are referring to.

Take the following grid as an example:

.grid-container {
  display: grid;
  grid-template-rows: [y] 50px [x] 50px [x] 50px [y] 50px [x] 50px [x];
}

.grid-item:nth-child(2) {
  grid-row-start: 2;
  grid-row-end: span x 2; /* equivalent to grid-row-end: 5; */
}

We set the starting line of the grid item to the second line. Then we want it to span downward until it hits a grid line named x. And since we want it to be the second x grid line, we wind up with grid-row-end: span x 2.

As a result, our grid item starts spanning toward the end line from the second line, as illustrated below. The first line that it hits is the first x, next is named y, and finally, it hits the desired second line named x.

A two-by-five layout where the second item is green, in the first column and spans the second, third, and fourth rows.
Setting the position of a grid item from the second line to the second instance of a line named x line using the grid-row-end CSS property.

This syntax is helpful when you want to span a grid item towards a grid line using its name, but you are aware that there is more than one grid line with that name, so we add an integer to say we want the N of that grid line.

Positioning grid items may generate implicit tracks

Setting the position of a grid item to a grid line’s index or a grid line’s name that does not exist in an explicit grid will force the grid to create implicit tracks to add that position to the grid.

Let’s create a grid with two rows and set the position of its item to non-existent lines. In the following example, we have only two rows and we didn’t name any of our gird lines. So, there is no line with an index of 5 and no line with the name of test, but we set these values to our properties:

.grid {
  display: grid;
  grid-template-rows: 100px 100px;
  grid-auto-rows: 100px;
}

.grid-item {
  grid-row-start: span test;
  grid-row-end: 5;
}

Since we know there are implicit tracks in our grid and we want them to have a size so we can see them, we add the grid-auto-rows` property to our code.

Now that we have everything set up, let’s see what happens to our grid:

A single column layout with five grid tracks, two of which are implicit.
Giving grid placement properties the values that does not exist causes the grid to create implicit tracks to be able to position our grid item.

We set grid-row-end to 5, but the last index of our explicit grid is 3 and because of that, two implicit tracks are created towards the end of the grid to give us implicit lines with an index of 4 and 5, respectively, that the element can align to.

On the other hand, let’s say we set grid-row-end to a grid line named test. Again, since we don’t have such a name in our grid, and because we want that grid line to align with the start edge of our grid item, an implicit row track gets created on the starting side of the explicit grid in the block direction, and its line is named test.

Positioning grid items may cause holes in the layout

As you may have seen in the previous examples, line-based positioning can cause empty spaces between grid items. You can avoid them by applying the grid-auto-flow property with the dense value to the grid container.

Comparing two grid layouts where the first contains gaps between items and the second has no gaps.
The grid-auto-flow CSS property can fill empty spaces caused by line-based positioning.

Stacking grid items

When positioning items across the grid, we can stack or overlap them on top of each other. This gives us the ability to sometimes use CSS Grid as an alternative to absolute positioning. For instance, we can put a caption layer on top of an image without using the position property as demonstrated below:

<figure>
  <img src="image.png" alt="how dare you leave alt empty?">
  <figcaption>The caption of our image</figcaption>
</figure>
figure {
  display: grid;
}

img,
figcaption {
  grid-column-start: 1;
  grid-column-end: -1;
  grid-row-start: 1;
  grid-row-end: -1;  
}

Here’s what we get:

Square photo of a cabin in the woods with a subtle fog behind it. A light gradient overlay is on top that goes from aqua to purple, and on top of that is a caption in white text.
Stacking elements on top of each other using CSS Grid placement properties.

By default, grid items stack in the source order, but you can control their level using the z-index property. In the following example, we overlap some items, and we use the z-index property to bring the second item to the highest level:

.item:nth-child(2) {
  grid-row-start: 2;
  grid-row-end: 4;
  grid-column-start: 2;
  grid-column-end: 4;
  z-index: 1;
}
A grid of four numbered overlapping rectangles flowing from the top-left of the container to the bottom-right. The second item is on top of the stack.
Bringing the second grid item to the top of the stack using the z-index CSS property.

Using negative index for more flexibility

There are cases where you want a full-height item in your grid, meaning it starts from the first grid line and ends with the last one. For example, in a four-row grid, the end line index is 5, so you can write the code below to have your full-height item.

.grid-container {
  display: grid;
  grid-template-rows: repeat(4, min-content);
}

.grid-item.full-height {
  grid-row-start: 1;
  grid-row-end: 5;
}

It works like a charm, but what if the number of rows changes to six? In that case, we need to update the index value for the placement property.

.grid-container {
  display: grid;
  grid-template-rows: repeat(5, min-content);
}

.grid-item.full-height {
  grid-row-start: 1;
  grid-row-end: 6;
}

The more flexible solution, though, is to use the negative index!

.grid-item.full-height {
  grid-row-start: 1;
  grid-row-end: -1;
}

Now the grid item with the .full-height class always stretches across the grid, no matter how many rows we add to or remove from the grid container.

Named area wins over named line

If a named grid area has the same name as a line name, the placement algorithm will prefer to use named grid area’s lines.

Consider the following example:

.grid {
  display: grid;
  grid-template-rows: 80px [y] 80px 80px 80px 80px;
  grid-template-areas: 
    "x"
    "x"
    "x"
    "y"
    "y";
}

The second grid line is named y, and the last two rows are defined as an area with the same name. Now, to position the first grid item, we assign y as a value for grid-row-end. Let’s see which line it will refer to:

.grid-item:first-child {
  grid-row-end: y;
}

As you can see in the next image, although the y line is closer to the first item, the browser chose the grid area’s edge to place the ending edge of the item.

Single column grid with five rows. The first item is green and positioned in the last row.
A grid area and a grid line have the same name y and the browser selects the grid area line over the named grid line when assigning that name to grid placement properties.

Note that this doesn’t apply if you use the implicit name line of a grid area. For instance, let’s change the name of the grid line in the previous example to y-end. Also, we know that the area with the name y has an implicit grid line of y-end assigned. Now, if we set y-end to the grid-row-end, the grid named line will be the winner this time.

.grid {
  display: grid;
  grid-template-rows: 50px [y-end] 50px 50px 50px 50px;
  grid-template-areas: 
    "x"
    "x"
    "x"
    "y"
    "y";
}

.grid-item:first-child {
  grid-row-end: y-end;
}
A single column layout with five rows. The first item is in the first row and colored green.
A grid area and a grid line share the same name, y. The browser selects the grid area line over the named grid line when assigning that name to grid placement properties.

Accessibility

One thing to note when using the grid placement properties is the issue caused by rearranging the items. When you change the position of an item, only the visual order of the grid items changes, and that order might not be the same as the original document order. This may cause a very bad experience for someone tabbing through the document on a keyboard or listening to a screen reader that reads the content in the same order as the HTML.

So, avoid changing the order of grid items when the HTML order of the elements matters. For example, it can be good for a random image gallery but perhaps not so much for your form inputs.

However, at the time of this writing, there is a proposal to tackle this issue that will hopefully resolve this concern in the future.

Demo

You can change the value of grid placement properties in the demo to see what happens to the third grid item:

Browser support

More information