Search code examples
csscss-grid

grid-row-start/grid-row-end puts item in wrong column


Why is it that the below grid-row-start/grid-row-end code puts Item #2 in the 1st column? Nothing was said about columns. The intent is that Item #2 should remain in its 2nd column but take up two rows. The code works if I try this with Item #1: it takes up two rows and remains in its own column, but not Item #2. Item #2 is moved to the front, the 1st column.

.container {
    border: 1px dashed red;
}

.item-grid {
    background-color: rgba(255, 0, 200, .2);
    border: 1px solid green;
    padding: 1rem;
}

.container-grid-example {
    display: grid;
    grid-template-columns: auto auto auto;
    grid-template-rows: auto auto auto;
    width: 50%;
}

/* This works with :nth-child(1), the 1st item */
.container-grid-example :nth-child(2) {
    grid-row-start: 1;
    grid-row-end: 3;
}
    <div class="container container-grid-example">
        <div class="item-grid">1</div>
        <div class="item-grid">2</div>
        <div class="item-grid">3</div>  
        <div class="item-grid">4</div>
        <div class="item-grid">5</div>
        <div class="item-grid">6</div>
        <div class="item-grid">7</div>
        <div class="item-grid">8</div>  
    </div>


Solution

  • The fix is to use span 2 and not define the lines.

    .container {
      border: 1px dashed red;
    }
    
    .item-grid {
      background-color: rgba(255, 0, 200, .2);
      border: 1px solid green;
      padding: 1rem;
    }
    
    .container-grid-example {
      display: grid;
      grid-template-columns: auto auto auto;
      grid-template-rows: auto auto auto;
      width: 50%;
    }
    
    
    /* This works with :nth-child(1), the 1st item */
    .container-grid-example :nth-child(2) {
      grid-row: span 2;
    }
    <div class="container container-grid-example">
      <div class="item-grid">1</div>
      <div class="item-grid">2</div>
      <div class="item-grid">3</div>
      <div class="item-grid">4</div>
      <div class="item-grid">5</div>
      <div class="item-grid">6</div>
      <div class="item-grid">7</div>
      <div class="item-grid">8</div>
    </div>

    To understand what's happening, you need to refer to the placement algorithm to know when each element is placed: https://www.w3.org/TR/css-grid-1/#auto-placement-algo

    You will notice the steps like below:

    1. Position anything that’s not auto-positioned.

    2. Process the items locked to a given row.

    3. Determine the columns in the implicit grid.

    4. Position the remaining grid items.

    In your case, no need to consider (3) because you don't have any implicit grid. We also don't have items "not auto-positioned" so we will consider the (2) and the (4).

    In your example, the second item is locked to a given row so it belongs to the step (2) thus we first position it then we consider the remaining items in steps (4).

    When using span 2, the element is no more locked to a given row so it belongs to the step (4) like all the items and we follow the document order to place all of them so we logically start with the first one then the second one and so on.


    Some related questions:

    CSS Grid : How Auto placement algorithm works

    CSS Grid Item Placement

    Using CSS GRID Why Im getting this gap?