Search code examples
csscss-grid

Simple CSS Grid Items Not Positioning As Expected On Smaller Viewports


I'm attempting to use CSS Grid. I created a simple four item grid where I expect the first and last elements to span across all columns, while the 2nd element will span across only one column and start at column 1, while the 2nd column will span 2 columns and end at the last column.

I wrote this codepen as a simple example of what I'm attempting.

The Problem:

When the viewport shrinks down to a small enough size (~800px width), the first and last elements no longer appear in the first column.

The idea here is to not use static counts so that the elements can wrap on the page and size according to the user's screen. What is it that I'm doing wrong?

    .container {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
      border: 4px solid #BADA55
    }
    .item {
      border: 1px solid red;
    }
    
    .item1 {
      grid-column: 1/-1;
      background: pink;
    }
    
    .item2 {
      background: deeppink;
      grid-column: span 1;
      width: 300px;
    }
    
    .item3 {
      grid-column: span 2/-1;
      background: blue;
    }
    
    .item4 {
      grid-column: 1/-1;
      background: purple;
    }
<div class="container">
  <div class="item item1">1</div>
  <div class="item item2">2</div>
  <div class="item item3">3</div>
  <div class="item item4">4</div>
</div>


Solution

  • The issue is related to the item3 that is creating an implicit column before the first one since you specified span 2/-1. This happen below 800px because below this value the implicit grid contain only one column whereas item3 need at least 2.

    An idea is to add a media query to fix this issue:

    .container {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
      border: 4px solid #BADA55
    }
    
    .item {
      border: 1px solid red;
    }
    
    .item1 {
      grid-column: 1/-1;
      background: pink;
    }
    
    .item2 {
      background: deeppink;
      grid-column: span 1;
      width: 300px;
    }
    
    .item3 {
      grid-column: span 2/-1;
      background: blue;
    }
    @media (max-width:800px) {
    .item3 {
      grid-column: 1/-1;
     }
    }
    
    .item4 {
      grid-column: 1/-1;
      background: purple;
    }
    <div class="container">
      <div class="item item1">1</div>
      <div class="item item2">2</div>
      <div class="item item3">3</div>
      <div class="item item4">4</div>
    </div>

    Here is a simplified example to better illustrate the issue of explicit/implcit grid you are having.

    .grid {
      border:2px solid;
      display:inline-grid;
      grid-template-columns:200px 200px; /* The explicit grid */
      grid-auto-columns:100px; /* In case of implicit grid this will be used */
      margin:10px;
    }
    .grid div {
      height:50px;
      background:red;
      grid-column:1/-1
    }
    .grid div.s1 {
      grid-column:span 3/-1;
      background:blue;
    }
    .grid div.s2 {
      grid-column:span 3;
      background:blue;
    }
    <div class="grid">
    <div></div>
    </div>
    <div class="grid">
    <div></div>
    <div class="s1"></div>
    </div>
    <div class="grid">
    <div></div>
    <div class="s2"></div>
    </div>

    As you can see in the above, I defined an explicit grid with 2 columns and one element spanning full width using grid-column:1/-1. If we add another item that needs 3 columns you will simply have an extra column and this will belong to the implicit grid. You are having the exact same issue when you fall under 800px and your repeat(auto-fill, minmax(400px, 1fr)); generate only one column inside the explicit grid.