Child 2
Child 2
Child 2
Child 2
Child 2
Child 2

Use css subgrid with automatic column spans

50 Views Asked by At

I have the following html structure.

<div class="grandparent">
  <div class="parent">
    <div class="achild2">Child 2</div>
    <div class="achild2">Child 2</div>
    <div class="achild2">Child 2</div>
    <div class="achild2">Child 2</div>
    <div class="achild2">Child 2</div>
    <div class="achild2">Child 2</div>
  </div>
  <div class="achild1">Child 1</div>
</div>
.parent {
  display: grid;
  grid-template-columns: subgrid;
  grid-column: span 6; /* <-- span is not known prior to runtime. crux of the QUESTION */
  background-color: lightblue;
  padding: 10px;
}

.grandparent {
  display: grid;
  grid-template-columns: repeat(12, 1fr); /* 12 columns */
  gap: 10px;
  background-color: lightgreen;
  padding: 20px;
}

.achild1 {
  background-color: lightpink;
  height: 50px;
  padding: 20px;
}

.achild2 {
  background-color: lightyellow;
  height: 50px;
  border: 2px solid red;
  padding: 10px;
}

to achieve the following effect

Intended Effect

The problem is that the number of achild2 is dynamic and each of these may span variable number of columns. So a parent SPAN cannot be specified.

I can use display: contents on the parent and it works well. I was wondering how to achieve the same effect using SUBGRID

A codepen link to experiment with: https://codepen.io/rsun2100/pen/GRebbvJ

2

There are 2 best solutions below

4
ADITYA On

You can use a combination of CSS Grid and Flexbox.

.grandparent {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 10px;
  background-color: lightgreen;
  padding: 20px;
}

.parent {
  display: flex;
  flex-wrap: wrap;
  background-color: lightblue;
  padding: 10px;
}

.achild1 {
  background-color: lightpink;
  height: 50px;
  padding: 20px;
  margin-bottom: 10px;
  /* Dynamically set the width of child1 */
  width: calc(50% - 5px); /* Subtracting margin and gap */
}

.achild2 {
  background-color: lightyellow;
  height: 50px;
  border: 2px solid red;
  padding: 10px;
  margin-right: 10px;
  margin-bottom: 10px;
  flex-grow: 1;
}

HTML:

<div class="grandparent">
  <div class="parent">
    <div class="achild1">Child 1</div>
    <!-- Dynamic generation of achild2 elements -->
  </div>
  <!-- Separate .achild1 outside of .parent -->
  <div class="achild1">Child 1</div>
  <div class="achild2">Child 2</div>
  <div class="achild2">Child 2</div>
  <div class="achild2">Child 2</div>
  <div class="achild2">Child 2</div>
  <div class="achild2">Child 2</div>
  <div class="achild2">Child 2</div>
</div>
0
vals On

One posibility is to use the new :has selector, to target .parent based on how many children it has.

You will need to set as many styles as posible number of elements. In the snippet, only the styles for 4 and 6 children are present:

.parent {
  display: grid;
  grid-template-columns: subgrid;
  grid-column: span 1; 
  padding: 10px;
}

.parent:has(div:nth-child(4)) {
    grid-column: span 4; 
}

.parent:has(div:nth-child(6)) {
    grid-column: span 6; 
}

.grandparent {
  display: grid;
  grid-template-columns: repeat(12, 1fr); /* 12 columns */
  gap: 10px;
  background-color: lightgreen;
  padding: 20px;
}

.achild1 {
  background-color: lightpink;
  height: 50px;
  padding: 20px;
}

.achild2 {
  background-color: #41974e;
  height: 50px;
  border: 2px solid red;
  padding: 1px;
}
<div class="grandparent">
  <div class="parent">
    <div class="achild2">Child 2</div>
    <div class="achild2">Child 2</div>
    <div class="achild2">Child 2</div>
    <div class="achild2">Child 2</div>
    <div class="achild2">Child 2</div>
    <div class="achild2">Child 2</div>
  </div>
  <div class="achild1">Child 1</div>
</div>
<div class="grandparent">
  <div class="parent">
    <div class="achild2">Child 2</div>
    <div class="achild2">Child 2</div>
    <div class="achild2">Child 2</div>
    <div class="achild2">Child 2</div>
  </div>
  <div class="achild1">Child 1</div>
</div>