How to target a specific column or row in CSS Grid Layout?

71,057

Solution 1

Not possible with CSS.

CSS targets HTML elements, attributes and attribute values.

Grid columns and rows have none of these "hooks".

You'll have to target the grid items directly.

You wrote:

For example, say I have a 3 row by 2 column CSS Grid Layout: grid-template-rows: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr;. How would I select all elements from the 2nd column?

grid-container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
  grid-gap: 10px;
  padding: 10px;
  height: 50vh;
  background-color: gray;
}

grid-item {
  background-color: lightgreen;
}

grid-item:nth-child(2n) {
  border: 2px dashed red;
}
<grid-container>
  <grid-item></grid-item>
  <grid-item></grid-item>
  <grid-item></grid-item>
  <grid-item></grid-item>
  <grid-item></grid-item>
  <grid-item></grid-item>
</grid-container>

Solution 2

To style an arbitrary row, you could use a wrapper element with its display set to contents. See the code snippet below:

.grid-container {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  grid-gap: 2px;
}

.grid-item {
  border: 1px solid black;
  padding: 5px;
}

.grid-row-wrapper {
  display: contents;
}

.grid-row-wrapper > .grid-item {
  background: skyblue;
}
<div class="grid-container">
  <div class="grid-item">1</div>
  <div class="grid-item">2</div>
  <div class="grid-item">3</div>
  <div class="grid-item">4</div>
  <div class="grid-item">5</div>
  <div class="grid-row-wrapper">
    <div class="grid-item">6</div>
    <div class="grid-item">7</div>
    <div class="grid-item">8</div>
    <div class="grid-item">9</div>
    <div class="grid-item">10</div>
  </div>
  <div class="grid-item">11</div>
  <div class="grid-item">12</div>
  <div class="grid-item">13</div>
  <div class="grid-item">14</div>
  <div class="grid-item">15</div>
  <div class="grid-item">16</div>
  <div class="grid-item">17</div>
  <div class="grid-item">18</div>
  <div class="grid-item">19</div>
  <div class="grid-item">20</div>
</div>

EDIT: As with all implementations, you should check to ensure it works in your target environment(s). You can check the compatibility table on MDN or caniuse.com for support for display: contents:

Solution 3

There are no column or row elements that you can target but if the grid is uniform (same number of cells in each row) you can select cells. Here are some examples.

1. Columns.

Last column in a 5-column grid:

    .item:nth-child(5n) { /* ... */ }

Fourth (2nd last) column in a 5-column grid:

    .item:nth-child(5n-1) { /* ... */ }

First (5th last) column in a 5-column grid:

    .item:nth-child(5n-4) { /* ... */ }

2. Rows

First row in a 5-column grid (first five cells):

    .item:nth-child(-n+5) { /* ... */ }

Second row in a 5-column grid (cells from 6 to 10):

    .item:nth-child(n+6):nth-child(-n+10) { /* ... */ }

Third row in a 5-column grid (cells from 11 to 15):

    .item:nth-child(n+11):nth-child(-n+15) { /* ... */ }

Last row in a 5-column grid with 20 cells (cells from 16 onward):

    .item:nth-child(n+16) { /* ... */ }

Solution 4

If you ever want to style a row the same principle applies. Taking that example from above:

grid-container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr 1fr;
  grid-gap: 10px;
  padding: 10px;
  height: 50vh;
  background-color: gray;
}

grid-item {
  background-color: lightgreen;
}

grid-item:nth-child(4n+3),grid-item:nth-child(4n) {
  border: 2px dashed red;
}
<grid-container>
  <grid-item></grid-item>
  <grid-item></grid-item>
  <grid-item></grid-item>
  <grid-item></grid-item>
  <grid-item></grid-item>
  <grid-item></grid-item>
  <grid-item></grid-item>
  <grid-item></grid-item>
</grid-container>

Solution 5

You can not. You have no such selectors.

But that is strange, because you can easily target row/colum from CSS

#item3 {
  background-color: blue;
  grid-row: span 2 / 7;
}

This is natural to expect something:

div[style*="display:grid"]:grid-row(3) {
    background-color: blue;
}

div[style*="display:grid"]:grid-column(3) {
    background-color: green;
}

Do not the reasons that draft for this is not proposed yet

UPD
Seems there are for columns: https://drafts.csswg.org/selectors-4/#the-nth-col-pseudo

UPD
Issue at W3C repo

Share:
71,057

Related videos on Youtube

Diode Dan
Author by

Diode Dan

Updated on November 05, 2021

Comments

  • Diode Dan
    Diode Dan over 2 years

    Is it possible to select a specific grid column or row with CSS?

    For example, say I have a 3 row by 2 column CSS Grid Layout: grid-template-rows: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr;. How would I select all elements from the 2nd column? For example: grid:nth-child(column:2) (just my idea, not valid code).

    I have tried nth-child selectors on the div elements, but this does not allow me to specify row or column when the items are automatically placed by the Grid Layout engine.

    body {
      display: grid;
      grid-template-rows: 1fr 1fr 1fr;
      grid-template-columns: 1fr 1fr;
      grid-gap: 10px;
    }
    
    .item {
      background: #999;
    }
    <div class="item">
      <p>Customer Name</p>
      <p>Element 1 | Element 2</p>
    </div>
    
    <div class="item">
      <p>Right Justify</p>
      <p>Element 1 | Element 2</p>
    </div>
    
    <div class="item">
      <p>Customer Name</p>
      <p>Element 1 | Element 2</p>
    </div>
    
    <div class="item">
      <p>Customer Name</p>
      <p>Element 1 | Element 2</p>
    </div>
    <div class="item">
      <p>Customer Name</p>
      <p>Element 1 | Element 2</p>
    </div>
    <div class="item">
      <p>Customer Name</p>
      <p>Element 1 | Element 2</p>
    </div>
    <div class="item">
      <p>Customer Name</p>
      <p>Element 1 | Element 2</p>
    </div>

  • vsync
    vsync almost 6 years
    This "solution" is coupled to the number of items and also does not take into account any line-breaks (AKA wrap), therefor it is not so useful.
  • Domenik Reitzner
    Domenik Reitzner almost 6 years
    @vsync: This is not flexbox, there is no wrap/line break. In grid you have a fixed layout and can apply a fixed styling to those items.
  • Jens Törnell
    Jens Törnell about 5 years
    This should be the correct answer. The browser support is not perfect but display: contents; is made to solve this issue without hack. It's great for DOM stepping for styling the correct row, but at the same time being invisible and skipped from the grid rendering (it does not mess anything up).
  • James Cat
    James Cat over 3 years
    but you can't for example style a background-image that spans a entire row, which you can in css display: table
  • Julian Suggate
    Julian Suggate over 3 years
    Very nice solution but browser support is still sorely lacking as of Jan 2021
  • Diode Dan
    Diode Dan over 2 years
    This is very interesting, are there any implementation demos that you can point out?
  • Temani Afif
    Temani Afif over 2 years
    @DiodeDan not yet, we are still far from any implementations because no browser support this for now but shortly we will have such feature as experimental in some browsers and we can test it
  • chovy
    chovy about 2 years
    This is the correct answer.
  • Mesqalito
    Mesqalito about 2 years
    No, this is NOT a valid answer. Styling rows and columns with static grid is never a problem since you always know where exactly each element will occur. The question that was initially asked is how to target specific items that were placed on particular row/column automatically by dynamic grid.
  • chipit24
    chipit24 about 2 years
    Yes, this IS a valid answer! You can add the grid-row-wrapper element dynamically.