Home > Mobile >  Change grid layout depending on number of elements
Change grid layout depending on number of elements

Time:07-20

I have a wrapper that can have 1-5 elements.

<div >
  <div ></div>
</div>

I'd like to change the layout in which they're displayed depending on the number of them:

  • 1 element: 1x1, 33.3% width

enter image description here

  • 2 elements: 2x1, 33.3% width

enter image description here

  • 3 elements: 3x1, 33.3% width

enter image description here

  • 4 elements: 2x2, 50% width

enter image description here

  • 5 elements: 3x2, 33.3% width

enter image description here

How can I do this without JavaScript?

This is the Codepen for reference.

body {
  padding: 20px;
}

.wrapper {
  width: 500px;
  padding: 5px 10px;
  margin: 10px 0;
  border: 2px dashed #5f5f5f;
  display: flex;
  flex-wrap: wrap;
}

.element {
  font-family: Helvetica, sans-serif;
  background-color: #ededed;
  flex: 33.3%;
  max-width: 33.3%;
  margin: 10px 0;
}

.wrapper.with-4-elements .element {
  flex: 50%;
  max-width: 50%;
}

.wrapper-with-5-elements .element:nth(4),
.wrapper-with-5-elements .element:nth(5) {
  flex: 50%;
  max-width: 50%;
}
<div >
  <div >Element 1</div>
</div>

<div >
  <div >Element 1</div>
  <div >Element 2</div>
</div>

<div >
  <div >Element 1</div>
  <div >Element 2</div>
  <div >Element 3</div>
</div>

<div >
  <div >Element 1</div>
  <div >Element 2</div>
  <div >Element 3</div>
  <div >Element 4</div>
</div>

<div >
  <div >Element 1</div>
  <div >Element 2</div>
  <div >Element 3</div>
  <div >Element 4</div>
  <div >Element 5</div>
</div>

CodePudding user response:

You can do it like below using CSS grid:

.wrapper {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 5px;
  border: 1px solid;
  padding: 10px;
  margin: 10px;
}
.element {
  grid-column: span 2;
  height: 20px;
  background: red;
}
/* the case with 4 elements */
.element:first-child:nth-last-child(4),
.element:first-child:nth-last-child(4) ~ *{
  grid-column: span 3;
}
<div >
  <div ></div>
</div>

<div >
  <div ></div>
  <div ></div>
</div>
<div >
  <div ></div>
  <div ></div>
  <div ></div>
</div>
<div >
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
</div>
<div >
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
</div>

And with flexbox:

.wrapper {
  display: flex;
  flex-wrap: wrap;
  border: 1px solid;
  gap: 5px;
  padding: 10px;
  margin: 10px;
}
.element {
  flex: 0 0 calc((100% - 10px)/3); /* 10px = 2 * gap */
  height: 20px;
  background: red;
}
/* the case with 4 elements */
.element:first-child:nth-last-child(4),
.element:first-child:nth-last-child(4) ~ *{
  flex: 0 0 calc((100% - 5px)/2);
}
<div >
  <div ></div>
</div>

<div >
  <div ></div>
  <div ></div>
</div>
<div >
  <div ></div>
  <div ></div>
  <div ></div>
</div>
<div >
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
</div>
<div >
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
</div>

CodePudding user response:

If I understand correctly, I think you might have 1 to 5 items but they are dynamic.

If so you can do it using JS

const addElement = document.getElementById('addElement');
const wrapper = document.querySelector('.wrapper');
let counter = 1;

addElement.addEventListener('click', () => {
 if (counter > 4) return
 const div = document.createElement('div')
 div.classList.add('element')
 div.innerText = `Element ${  counter}`
 counter === 4 ? wrapper.classList.add('four-elements') : wrapper.classList.remove('four-elements')
 wrapper.appendChild(div)
})
body {
  padding: 20px;
}

.wrapper {
  width: 500px;
  padding: 5px 10px;
  margin: 10px 0;
  border: 2px dashed #5f5f5f;
  display: flex;
  flex-wrap: wrap;
}

.element {
  font-family: Helvetica, sans-serif;
  background-color: #ededed;
  flex: 33.3%;
  max-width: 33.3%;
  margin: 10px 0;
}

.four-elements .element {
  flex: 50%;
  max-width: 50%;
}
<div >
  <div >Element 1</div>
</div>

<button id="addElement">Add Element</button>

  • Related