I'm trying to create a Grid with React and Chakra-UI that behaves as follows:
Basically, depending on the amount of colors it is given (with a maximum of 6) it will automatically display them as shown.
The code so far is the following:
<Grid
width={'20vw'}
minWidth={'200px'}
height={'20vh'}
minHeight={'100px'}
boxShadow={`${shadowColor} 0px 0px 2px`}
// Grid settings here
>
{simulationPalette.colors.map((color) => (
<Box backgroundColor={color} />
))}
</Grid>
I tried some settings like
gridTemplateColumns={`repeat(auto-fit, minmax(50%, 1fr))`}
which would create empty space in case of an odd number of colors
or simply
gridTemplateColumns={auto-fill}
which would just use a new columns for ever color
You need flexbox:
#container {
display: flex;
flex-wrap: wrap;
}
#container div {
/* Make them as wide as possible from a basis of 0 and shrink as needed */
/* (see https://stackoverflow.com/q/37386244 for more information) */
flex: 1;
/* ...but not narrower than 1 / 3 of the container. */
box-sizing: border-box;
min-width: calc(100% / 3);
}
You also need to add a class or similar to let CSS know if #container
has more than 4 children:
#container.more-than-4-colors div {
min-width: calc(100% / 3);
}
const method = container.children.length > 4 ? 'add' : 'remove';
container.classList[method]('more-than-4-colors');
When the :has()
pseudo-class gets widely supported, you can use this:
/* Not yet widely supported */
#container:has(> :nth-child(5)) div {
min-width: calc(100% / 3);
}
Try it:
const container = document.querySelector('#container');
const button = document.querySelector('button');
button.addEventListener('click', () => {
const element = document.createElement('div');
if (container.children.length === 6) {
container.innerHTML = '';
}
container.appendChild(element);
const method = container.children.length > 4 ? 'add' : 'remove';
container.classList[method]('more-than-4-colors');
});
#container {
display: flex;
flex-wrap: wrap;
}
#container div {
flex: 1;
box-sizing: border-box;
min-width: calc(100% / 2);
}
#container.more-than-4-colors div {
min-width: calc(100% / 3);
}
/* Not yet widely supported */
#container:has(> :nth-child(5)) {
min-width: calc(100% / 3);
}
/* Demo only */
#container {
margin: 1em 0;
}
#container div {
height: 100px;
outline: 1px solid var(--border);
background: var(--background);
}
#container div:nth-child(1) {
--border: #6c8ebf;
--background: #dae8fc;
}
#container div:nth-child(2) {
--border: #82b366;
--background: #d5e8d4;
}
#container div:nth-child(3) {
--border: #9673a6;
--background: #e1d5e7;
}
#container div:nth-child(4) {
--border: #d79b00;
--background: #ffe6cc;
}
#container div:nth-child(5) {
--border: #b85450;
--background: #f8cecc;
}
#container div:nth-child(6) {
--border: #d6b656;
--background: #fff2cc;
}
<button>Add</button>
<div id="container">
<div></div>
</div>