How do I get CSS row-gap and column-gap to not show up if row or column is missing?

Viewed 570

I have a grid with three images and one text section. I have column and row gaps for the gride which work fine if I have all three images. However, if any of the images are missing, I still get column or row gaps for the missing column or rows. Is there any way for those gaps to collapse to nothing if the rows or columns are not there?

The example that I have included gives the three cases with 1, 2 or 3 images in a responsive design. In the one image example you can see the extra column gap at the right. When the browser gets skinny the row gaps for the missing rows become visible.

div.thumbnail
{
    background-color: green;
    padding : 1em;
    break-inside : avoid;
    display : grid;
    column-gap : 1em;
    row-gap : 1em;
    grid-template-columns : auto 1fr auto;
    grid-template-areas : "image1 text image2"
                          "image1 text image3";
}

div.thumbnail div.image1
{
    background-color : cyan;
    text-align : right;
    grid-area : image1;
}

div.thumbnail div.image2
{
    background-color : pink;
    text-align : left;
    grid-area : image2;
}

div.thumbnail div.image3
{
    background-color : limegreen;
    text-align : left;
    grid-area : image3;
}

div.thumbnail div.text
{
    background-color : orange;
    grid-area : text;
}

/* for printing and small devices like iPhone #1 */
@media screen and (max-width: 760px), print and (max-width: 5in)
{
    div.thumbnail
    {
        grid-template-columns : 1fr !important;
        grid-template-areas : "image1"
                                "image2"
                                "image3"
                                "text";
    }

    div.thumbnail div.image1,
    div.thumbnail div.image2,
    div.thumbnail div.image3,
    div.thumbnail div.text
    {
        text-align : center;
        width : auto !important;
    }
}
<h2>One Image</h2>

<div class="thumbnail">
    <div class="image1" style="width:200px">
        image 1
    </div>
    <div class="text">
        Text
    </div>
</div>

<h2>Two Images</h2>

<div class="thumbnail">
    <div class="image1" style="width:200px">
        image 1
    </div>
    <div class="image2" style="width:200px">
        image 2
    </div>
    <div class="text">
        Text
    </div>
</div>

<h2>Three Images</h2>

<div class="thumbnail">
    <div class="image1" style="width:200px">
        image 1
    </div>
    <div class="image2" style="width:200px">
        image 2
    </div>
    <div class="image3" style="width:200px">
        image 3
    </div>
    <div class="text">
        Text
    </div>
</div>

Thanks,

Mike

1 Answers

Don't use template but place the item explicitely in the needed place. Notice how I changed the media query to have min-width instead of max-width so we only need to define the item placement on big screen and we keep the default one on small screen

div.thumbnail {
  background-color: green;
  padding: 1em;
  display: grid;
  gap: 1em;
}

div.image1 {
  background-color: cyan;
}
div.image2 {
  background-color: pink;
}
div.image3 {
  background-color: limegreen;
}
div.text {
  background-color: orange;
}

@media screen and (min-width: 760px) {
  div.thumbnail {
    grid-template-columns: auto 1fr; /* define only 2 explicit column */
    grid-auto-flow: dense;
  }
  div.image2,
  div.image3 {
    grid-column: 3; /* add another column if (2) or (3) is present */
  }
  div.text {
    grid-column: 2;
  }
  /* (1) and text span 2 row when (3) is present */
  div.image1:nth-last-child(4),
  .image3 + div.text{
    grid-row: span 2;
  }
  [class*=image] {
    width:200px;
  }
}
<h2>One Image</h2>

<div class="thumbnail">
  <div class="image1">
    image 1
  </div>
  <div class="text">
    Text
  </div>
</div>

<h2>Two Images</h2>

<div class="thumbnail">
  <div class="image1">
    image 1
  </div>
  <div class="image2">
    image 2
  </div>
  <div class="text">
    Text
  </div>
</div>

<h2>Three Images</h2>

<div class="thumbnail">
  <div class="image1">
    image 1
  </div>
  <div class="image2">
    image 2
  </div>
  <div class="image3">
    image 3
  </div>
  <div class="text">
    Text
  </div>
</div>

Related