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
- 2 elements: 2x1, 33.3% width
- 3 elements: 3x1, 33.3% width
- 4 elements: 2x2, 50% width
- 5 elements: 3x2, 33.3% width
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>