skip to Main Content

I am trying to span my second grid item over two rows.

I am able to achieve what I am looking for using the grid-row: span 2 syntax. However I would like to achieve the same result using the grid-row: x/y syntax, where x and y are numeric values.

Problem is, the second syntax is producing unexpected results.
May someone please help me understand what it is I am doing wrong?

* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
}

body {
  font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif;
  font-size: 16px;
  line-height: 1.5;
  color: rosybrown;
  background: #ffff;
}

.container {
  display: grid;
  max-width: 960px;
  padding: 10px;
  margin: 0;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: auto;
}

.item {
  background: steelblue;
  color: white;
  font-size: 20px;
  padding: 20px;
  border: skyblue 1px solid;
}

.item:nth-child(1) {
  grid-column: 1/3;
  background-color: springgreen;
}

.item:nth-child(2) {
  background-color: royalblue;
  grid-row: 1/3;
}

.item:nth-child(3) {
  background: darkred;
}

.item:nth-child(5) {
  grid-column: 1/4;
}
<div class="container">
  <div class="item"> item1 </div>
  <div class="item"> item2 </div>
  <div class="item"> item3 </div>
  <div class="item"> item4 </div>
  <div class="item"> item5 </div>
</div>

Result:

Expected result:

I tried reading through the CSS to find the cause of the problem, and I also tried using different values.

2

Answers


  1. Solution

    Add grid-row: 1 to the first item, or grid-column: 3 to the second item.

    .item:nth-child(1) {
       grid-column: 1/3;
       grid-row: 1; /* new */
     }
    

    OR

    .item:nth-child(2) {
       grid-row: 1/3;
       grid-column: 3; /* new */
     }
    
    .container {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      grid-template-rows: auto;  
      max-width: 960px;
      padding: 10px;
      margin: 0;
    }
    
    .item {
      background: steelblue;
      color: white;
      font-size: 20px;
      padding: 20px;
      border: skyblue 1px solid;
    }
    
    .item:nth-child(1) {
      grid-column: 1/3;
      background-color: springgreen;
      grid-row: 1; /* new */
    }
    
    .item:nth-child(2) {
      background-color: royalblue;
      grid-row: 1/3;
      /* grid-column: 3; */ /* new */
    }
    
    .item:nth-child(3) {
      background: darkred;
    }
    
    .item:nth-child(5) {
      grid-column: 1/4;
    }
    
    * {
      box-sizing: border-box;
      padding: 0;
      margin: 0;
    }
    
    body {
      font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif;
      font-size: 16px;
      line-height: 1.5;
      color: rosybrown;
      background: #ffff;
    }
    <div class="container">
      <div class="item"> item1 </div>
      <div class="item"> item2 </div>
      <div class="item"> item3 </div>
      <div class="item"> item4 </div>
      <div class="item"> item5 </div>
    </div>

    Explanation

    Line-Based Placement

    Let’s start by keeping in mind that grid-row and grid-column are shorthand properties for:

    • grid-row-start / grid-row-end
    • grid-column-start / grid-column-end

    enter image description here

    Item #1 is set to span across the first two columns.

    .item:nth-child(1) {
       grid-column: 1/3;
     }
    

    But it has no rows defined. Therefore, grid-row defaults to auto.

    Item #2 is set to span the first two rows.

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

    But it has no columns defined. Therefore, grid-column defaults to auto.

    Side note: Because the explicit grid has only one row defined (grid-template-rows: auto), and no height defined, Item #2 is actually spanning across two rows—one explicit, one implicit—not just one as it appears. (This matter is worthy of another question.)

    enter image description here

    The Grid Item Placement Algorithm

    The grid item layout process is handled by the Grid Item Placement Algorithm. One of the first steps in the process is this:

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

    Therefore:

    • Item #1 gets its defined columns (rows are auto).
    • Item #2 gets its defined rows (columns are auto).

    This is how Item #2 gets placed above Item #1. Defined rows and columns have precedence over undefined rows and columns—the latter subject to more control by the algorithm.

    As mentioned at the top, the simplest solution is to remove the auto variable from the process. You can do this by adding grid-row: 1 to the first item, or grid-column: 3 to the second item.


    span

    grid-row: 1 / 3 is shorthand for:

    • grid-row-start: 1
    • grid-row-end: 3

    grid-row: span 2 is equivalent to grid-row: span 2 / auto, which is shorthand for:

    • grid-row-start: span 2
    • grid-row-end: auto

    When you switch from grid-row: 1 / 3 to grid-row: span 2, you remove the grid-row-start: 1 component. In other words, you unlock the item from the first row. The algorithm now has more control, moving the item to its natural position.

    Login or Signup to reply.
  2. You could take advantage of grid-template-areas & grid-area, like so:

    * {
      box-sizing: border-box;
      padding: 0;
      margin: 0;
    }
    
    body {
      font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif;
      font-size: 16px;
      line-height: 1.5;
      color: rosybrown;
      background: #ffff;
    }
    
    .container {
      display: grid;
      max-width: 960px;
      padding: 10px;
      margin: 0;
      grid-template-columns: repeat(3, 1fr);
      grid-template-rows: auto;
      grid-template-areas:
          "item1 item1 item2"
          "item3 item4 item2"
          "item5 item5 item5"
    }
    
    .item {
      background: steelblue;
      color: white;
      font-size: 20px;
      padding: 20px;
      border: skyblue 1px solid;
    }
    
    .item:nth-child(1) {
      grid-area: item1;
      background-color: springgreen;
    }
    
    .item:nth-child(2) {
      background-color: royalblue;
      grid-area: item2;
    }
    
    .item:nth-child(3) {
      background: darkred;
      grid-area: item3;
    }
    
    .item:nth-child(4) {
      grid-area: item4;
    }
    
    .item:nth-child(5) {
      grid-area: item5;
    }
    <div class="container">
      <div class="item"> item1 </div>
      <div class="item"> item2 </div>
      <div class="item"> item3 </div>
      <div class="item"> item4 </div>
      <div class="item"> item5 </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search