Home > Software engineering >  CSS grid with dynamic number of rows and adjustable width
CSS grid with dynamic number of rows and adjustable width

Time:08-01

I am trying to create a dynamic grid layout with two columns that is #red-container and #green-container. Each container or column should be resizable horizontally and the main container #container should be resizable vertically. Resizing the container should adjust the height of the child elements. The #red-container and #green-container have cells which are added dynamically to the container with the JavaScript function in a row-wise fashion. I have the following working implementation:

function addCell(color) {
  let container = document.getElementById(color   "-container");
  
  let cell = document.createElement("div");
  cell.innerText = color;
  container.appendChild(cell).className = "container-item";
}
#container {
  border: 1px solid #ddd;
  display: flex;
  flex-grow: 1;
  flex-direction: row;
  height: 50vh;
  resize: vertical;
  overflow: auto;
}

#red-container {
  flex-grow: 1;
  display: grid;
  grid-auto-flow: row;
  margin: 10px;
  resize: horizontal;
  overflow: auto;
  border: 1px solid red;
}

#green-container {
  flex-grow: 1;
  display: grid;
  grid-auto-flow: row;
  margin: 10px; 
  resize: horizontal; 
  overflow: auto;
  border: 1px solid green;
}

.container-item {
  padding: 10px;
  border: 1px solid black;
}
<button onclick="addCell('red')">add red cell</button>
<button onclick="addCell('green')">add green cell</button>

<div id="container">
  <div id="red-container"></div>
  <div id="green-container"></div>
</div>

However, there are two problems with it:

  1. The first time the user clicks add red cell it increases the width of #red-container.
  2. adjusting the width of the red and green container is inconsistent and I am unable to adjust the width of the red container to less than 50% of the width.

Any ideas on how to fix these two problems? Additionally, any advice on writing the css in a more concise manner is welcome (#red-container and #green-container contain duplicate code).

CodePudding user response:

do these two things to solve the problem:

  1. make the #container with grid-template-columns: 1fr 1fr; so whatever it happens, the child will be always half-width.

because if you want to use flex, it only grows to 1, but does not always mean half precisely, so go for grid layout

  1. for not making repetitive code just make the two selectors in one by using , (comma)
    #red-container, #green-container

not important but can help:

  1. adding box-sizing: border-box for solving extra problems if you add padding or something similar

  2. also don't write grid-auto-flow: row because grid is by default row

  3. also use gap instead of margin, gap makes the same value of px between element on a grid/flex layout.
    if you are using margin, then if you write for example 10px as a value you will get 20px


here the correct code:

function addCell(color) {
  let container = document.getElementById(color   "-container");

  let cell = document.createElement("div");
  cell.innerText = color;
  container.appendChild(cell).className = "container-item";
}
* {
  box-sizing: border-box;
}

#container {
  border: 1px solid #ddd;
  display: grid;
  grid-template-columns: 1fr 1fr;
  height: 50vh;
  resize: vertical;
  overflow: auto;
  gap: 10px;
  /* if you want like before, here in gap: write 20px */
  padding: 10px;
}

#red-container,
#green-container {
  display: grid;
  resize: horizontal;
  overflow: auto;
}

#red-container {
  border: 1px solid red;
}

#green-container {
  border: 1px solid green;
}

.container-item {
  padding: 10px;
  border: 1px solid black;
}
<button onclick="addCell('red')">add red cell</button>
<button onclick="addCell('green')">add green cell</button>

<div id="container">
  <div id="red-container"></div>
  <div id="green-container"></div>
</div>

if you didn't understand something, write me a comment here, I will answer to you
however here some documentations that can help you:

CodePudding user response:

Make only the red container resizable with an initial width equal to 50% and use flex-grow:1 on the green container

function addCell(color) {
  let container = document.getElementById(color   "-container");
  
  let cell = document.createElement("div");
  cell.innerText = color;
  container.appendChild(cell).className = "container-item";
}
#container {
  border: 1px solid #ddd;
  display: flex;
  gap: 10px;
  padding: 10px;
  height: 50vh;
  resize: vertical;
  overflow: auto;
}

#green-container,
#red-container {
  display: grid;
  overflow: auto;
}
#red-container {
  border: 1px solid red;
  width: 50%;
  resize: horizontal; 
}
#green-container {
  border: 1px solid green;
  flex-grow: 1;
}


.container-item {
  padding: 10px;
  border: 1px solid black;
}
<button onclick="addCell('red')">add red cell</button>
<button onclick="addCell('green')">add green cell</button>

<div id="container">
  <div id="red-container"></div>
  <div id="green-container"></div>
</div>

  • Related