0

I'm not sure if this is possible, but I'm trying to create a layout like so:

enter image description here

The elements are <div>'s with text inside, coming from a PHP foreach loop. While being pulled from the database, there is an if conditional that can add a class, where I can can control the width/height of the element. This will make the element larger.

I've looked into CSS Grid & Flexbox, and can't see a solution. The amount of larger boxes can change from page to page, but should always keep the same pattern.

I'm wondering if the best solution would be to somehow re-arrange the array in PHP to re-order the output of the elements.

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Ghost Echo
  • 1,997
  • 4
  • 31
  • 46
  • what makes a box a larger box? And what have you tried? – Jeff Feb 16 '18 at 00:22
  • I've tried various Bootstrap, CSS grid and CSS flexbox solutions. The larger box is essentially determined from a WordPress meta field. If it has the field, I add the large class, if it doesn't I add the small class. The items in the database are in no particular order. – Ghost Echo Feb 16 '18 at 00:25
  • I doubt this could be done with css only. You'd need to somehow group your data. Either while in the loop or before. – Jeff Feb 16 '18 at 00:26

2 Answers2

1

I've really tried to find a solution for this with CSS Grid, but unfortunately I've come only on possibilities which don´t make the whole thing dynamic as you might want. But I think there are currently no other options - if someone knows a way, please correct me. ;)

According to my knowledge, there is also currently no selector in css that allows you to accurately address every second element of a class, which unfortunately makes it more complicated.

In my first solution, I have built on the :nth-child(even) selector. For this approach the element with the class you want to address must be the in the right order to the parent element, so that the index is correct. Thereby you would have to adjust the PHP code, so that the larger elements already get in the right place in the HTML output.

For the second solution (which I like much less), I tried to build the whole thing on the general sibling combinator selector. With this I address all existing elements on the page individually like: .class ~ .class = second element or .class ~ .class ~ .class = third element. As a result, the PHP code would not have to be adjusted and you get "more flexibility" on this part, but you would be limited in the number of elements per page, since the settings for them would be fixed in the CSS code.

Here now the two solutions:


1. The :nth-child(even) way

.grid {
  display: grid;
  height: 100%;
  width: 100%;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: 1fr;
  grid-gap: 20px;
  grid-auto-flow: row dense;
}

.grid__item--large {
  grid-column: -3 / span 2;
  grid-row: span 2;
}

.grid__item--large:nth-child(even) {
  grid-column: 1 / span 2;
}

/* just for the snippet styling */

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

  body {
    margin: 20px;
  }

  .grid__item {
    min-height: 200px;
    background: gray;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 2em;
    color: white;
  }
    
  .grid__item--large {
    min-height: 400px;
  }

/* --- */
<div class="grid">

  <div class="grid__item grid__item--large">1</div>
  <div class="grid__item">2</div>
  <div class="grid__item">3</div>
  <div class="grid__item">4</div>
  <div class="grid__item">5</div>

  <div class="grid__item grid__item--large">6</div>
  <div class="grid__item">7</div>
  <div class="grid__item">8</div>
  <div class="grid__item">9</div>
  <div class="grid__item">10</div>

  <div class="grid__item grid__item--large">11</div>
  <div class="grid__item">12</div>
  <div class="grid__item">13</div>
  <div class="grid__item">14</div>
  <div class="grid__item">15</div>

  <div class="grid__item grid__item--large">16</div>
  <div class="grid__item">17</div>
  <div class="grid__item">18</div>
  <div class="grid__item">19</div>
  <div class="grid__item">20</div>

</div>

2. The "general sibling combinator" way

.grid {
  display: grid;
  height: 100%;
  width: 100%;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: 1fr;
  grid-gap: 20px;
  grid-auto-flow: row dense;
}

.grid__item--large {
  grid-column: -3 / span 2;
  grid-row: span 2;
}

.grid__item--large ~ .grid__item--large {
  grid-column: 1 / span 2;
}

.grid__item--large ~ .grid__item--large ~ .grid__item--large {
  grid-column: -3 / span 2;
}

.grid__item--large ~ .grid__item--large ~ .grid__item--large  ~ .grid__item--large { 
  grid-column: 1 / span 2;
}

/* just for the snippet styling  */

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

  body {
    margin: 20px;
  }

  .grid__item {
    min-height: 200px;
    background: gray;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 2em;
    color: white;
  }
    
  .grid__item--large {
    min-height: 400px;
  }

/* --- */
<div class="grid">

  <div class="grid__item">1</div>
  <div class="grid__item grid__item--large">2</div>
  <div class="grid__item">3</div>
  <div class="grid__item">4</div>
  <div class="grid__item grid__item--large">5</div>

  <div class="grid__item">6</div>
  <div class="grid__item">7</div>
  <div class="grid__item">8</div>
  <div class="grid__item">9</div>
  <div class="grid__item grid__item--large">10</div>

  <div class="grid__item">11</div>
  <div class="grid__item">12</div>
  <div class="grid__item">13</div>
  <div class="grid__item">14</div>
  <div class="grid__item">15</div>

  <div class="grid__item grid__item--large">16</div>
  <div class="grid__item">17</div>
  <div class="grid__item">18</div>
  <div class="grid__item">19</div>
  <div class="grid__item">20</div>

</div>

I hope that can help somehow. :)

Arne
  • 995
  • 1
  • 8
  • 16
0

hope to help you.

var row=5; // total row layout
var count=0;
var strLayout='';
for(var i=0;i<row*2;i++){
  if(count%3==0){
   strLayout +='<div style="float:left;width:100px;height:100px;"><div style="float:left;width:40px;height:40px;margin: 5px;;background:black"></div>'; 
   strLayout +='<div style="float:left;width:40px;height:40px;margin: 5px;;background:black"></div>';
   strLayout +='<div style="float:left;width:40px;height:40px;margin: 5px;;background:black"></div>';
   strLayout +='<div style="float:left;width:40px;height:40px;margin: 5px;;background:black"></div></div>';
  }else{
   strLayout +='<div style="float:left;width:90px;height:90px;margin: 5px;background:black"></div>'; 
  }
  if (count==3){
   count=0;
  }else{
   count++;
  }
}
$('#layout').html(strLayout);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>   
<div id="layout" style="float:left;width:200px;background:white">
</div>