Search code examples
htmlcssgridcss-grid

How to have different column widths across rows in CSS Grid?


I need to create the grid items shown as in the image attached. First Item need to be of 45% and second and third Item need to be 52.5%, and rest items need to be of 50% each. I can not change the HTML as all the grid child coming from a Loop. So I am not able to achieve it by the CSS written, check snippet, By my css its only possible to have the width of left side all items 50%, or 45%, but how to change the width of items from 4 to rest of the items.

Is it possible without changing the HTML?

enter image description here

.atul {
  display: grid;
  grid-template-columns: 45% 52.5%;
  grid-template-rows: auto;
  grid-gap: 2.5%;
  grid-template-areas: "card1 card2" 
                       "card1 card3";
}

.card:nth-child(1) {
  grid-area: card1;
}

.card:nth-child(2) {
  grid-area: card2;
}

.card:nth-child(3) {
  grid-area: card3;
}
<div class="atul">
  <div class="card" style="background-color: red;">Card 1</div>
  <div class="card" style="background-color: green;">Card 2</div>
  <div class="card" style="background-color: yellow;">Card 3</div>
  <div class="card" style="background-color: skyblue;">Card 4</div>
  <div class="card" style="background-color: skyblue;">Card 5</div>
  <div class="card" style="background-color: skyblue;">Card 6</div>
  <div class="card" style="background-color: skyblue;">Card 7</div>
  <div class="card" style="background-color: skyblue;">Card 8</div>
  <div class="card" style="background-color: skyblue;">Card 9</div>
  <div class="card" style="background-color: skyblue;">Card 10</div>
  <div class="card" style="background-color: skyblue;">Card 11</div>
  <div class="card" style="background-color: skyblue;">Card 12</div>
  <div class="card" style="background-color: skyblue;">Card 13</div>
</div>


Solution

  • To make this work you need to find a common divider for all three lengths (42.5%, 48.75% and 52.5%). With a common divider you can create the right number of columns to accommodate each grid area.

    In my example below, I created 400 columns of .25% width each (400 * .25 = 100%).

    It then spanned grid areas across the correct number of columns:

    45.00 / .25 = 180
    
    48.75 / .25 = 195
    
    52.50 / .25 = 210
    

    It may not be exactly what you're looking for, but hopefully the concept helps you move forward.

    No changes to the HTML.

    .atul {
      display: grid;
      grid-template-columns: repeat(400, .25%);
      grid-auto-rows: 50px; /* for demo only */
      grid-row-gap: 30px;   /* note that you need to create column gaps through
                               the proper distribution of columns, because if you
                               use `grid-column-gap`, it will add a gap between
                               all 400 columns */
    }
    
    .card:nth-child(1) {
      grid-column: 1 / 180;
      grid-row: 1 / 3;
    }
    
    .card:nth-child(2) {
      grid-column: -1 / -210; /* starting at the end line of the grid
                                 (works only in explicit grids) */
      grid-row: 1 / 2;
    }
    
    .card:nth-child(3) {
      grid-column: -1 / -210;
      grid-row: 2 / 3;
    }
    
    /* starting at the 4th item, target even items only */
    .card:nth-child(n + 4):nth-child(even) {
      grid-column: 1 / 195;
    }
    
    .card:nth-child(n + 4):nth-child(odd) {
      grid-column: -1 / -195;
    }
    
    .card:nth-child(4),
    .card:nth-child(5) {
      grid-row: 3;
    }
    
    .card:nth-child(6),
    .card:nth-child(7) {
      grid-row: 4;
    }
    
    .card:nth-child(8),
    .card:nth-child(9) {
      grid-row: 5;
    }
    
    .card:nth-child(10),
    .card:nth-child(11) {
      grid-row: 6;
    }
    
    .card:nth-child(12),
    .card:nth-child(13) {
      grid-row: 7;
    }
    <div class="atul">
      <div class="card" style="background-color: red;">Card 1</div>
      <div class="card" style="background-color: green;">Card 2</div>
      <div class="card" style="background-color: yellow;">Card 3</div>
      <div class="card" style="background-color: skyblue;">Card 4</div>
      <div class="card" style="background-color: skyblue;">Card 5</div>
      <div class="card" style="background-color: skyblue;">Card 6</div>
      <div class="card" style="background-color: skyblue;">Card 7</div>
      <div class="card" style="background-color: skyblue;">Card 8</div>
      <div class="card" style="background-color: skyblue;">Card 9</div>
      <div class="card" style="background-color: skyblue;">Card 10</div>
      <div class="card" style="background-color: skyblue;">Card 11</div>
      <div class="card" style="background-color: skyblue;">Card 12</div>
      <div class="card" style="background-color: skyblue;">Card 13</div>
    </div>

    jsFiddle demo