Display grid elements in columns

Viewed 81

I didn't find the good solution so I ask help to the comunity!

I have 12 elements from bdd.

I want to display this elements in 3 columns (to have like 3 pages of 4 elements) without changing the order of the records from the bdd.

I don't want to have new container for the 3 pages (for responsive reason and to simplify the final code).

I don't want to set the width of the container.

Here is the code to explain my problem :

body {
  width: 900px;
}
.container {
    display: flex;
    flex-wrap: wrap;
}
.element {
    background-color: red;
    margin: 20px;
    height: 100px;
    width: 100px;
    color: white;
    font-size: 50px;
    line-height: 100px;
    text-align: center; 
}

.container.good .element {
  background-color: green;
}
<body>
  <h1>Elements from bdd</h1>
  <div class="container">
      <div class="element">1</div>
      <div class="element">2</div>
      <div class="element">3</div>
      <div class="element">4</div>
      <div class="element">5</div>
      <div class="element">6</div>
      <div class="element">7</div>
      <div class="element">8</div>
      <div class="element">9</div>
      <div class="element">10</div>
      <div class="element">11</div>
      <div class="element">12</div>
  </div>
  <h1>Expected 3 columns (with elements order above of course)</h1>
  <div class="container good">
      <div class="element">1</div>
      <div class="element">2</div>
      <div class="element">5</div>
      <div class="element">6</div>
      <div class="element">9</div>
      <div class="element">10</div>
      <div class="element">3</div>
      <div class="element">4</div>
      <div class="element">7</div>
      <div class="element">8</div>
      <div class="element">11</div>
      <div class="element">12</div>
  </div>
</body>

A bonus question, is there an easy way to adjsut margin beetwen columns/pages

Many thanks for your help, Pedro

4 Answers

You can use Bootstrap to make a grid of element and it will make your page responsive.

Bootstrap Grid System:

<div class = "container">
       <div class = "row">

          *1 Grid With 4 Element*

           <div class = "col-md-4" >
             <div class="element">1</div>
             <div class="element">2</div>
             <div class="element">3</div>
             <div class="element">4</div>
           </div>

           *2 Grid With 4 Element*

           <div class = "col-md-4" >
             <div class="element">5</div>
             <div class="element">6</div>
             <div class="element">7</div>
             <div class="element">8</div>
           </div>

            *3 Grid With 4 Element*

           <div class = "col-md-4" >
             <div class="element">9</div>
             <div class="element">10</div>
             <div class="element">11</div>
             <div class="element">12</div>
           </div>

       </div>
</div>

Add this to your style:

   .container.good {
       display: grid;
       grid-template-columns: repeat(3, auto);
       width: fit-content; 
   }

I've added in width: fit-content just to bring the elements closer together but sounds like you'll have to adjust for your own setup as you've got a few constraints.

I don't think so if there is any way to create columns in a flexbox without using extra containers. Extra containers are necessary to create a grid-like structure.

Also, if you'll just use the grid, then things won't get too messy.

Although there could be a workaround for the same if you don't wish to specify a width and add containers. If you need, let's say n columns, then after every nth child element add an empty division and make this division occupy the rest of the remaining space.

.Spacing {
  width: 100%;
}

I added the Spacing class to the empty divisions. width: 100%; will make the division occupy the remaining space horizontally and force the elements next to it to start from the bottom.

To explain this a little further, if you have a screen width of 100px and 4 squares require 60px, then the empty division will acquire the remaining width i.e. 40px.

body {
  width: 900px;
}
.container {
    display: flex;
    flex-wrap: wrap;
}
.element {
    background-color: red;
    margin: 20px;
    height: 100px;
    width: 100px;
    color: white;
    font-size: 50px;
    line-height: 100px;
    text-align: center; 
}

.Spacing {
  width: 100%;
}

.container.good .element {
  background-color: green;
}
<body>
  <h1>Elements from bdd</h1>
  <div class="container">
      <div class="element">1</div>
      <div class="element">2</div>
      <div class="element">3</div>
      <div class="element">4</div>
      <div class="Spacing"></div>
      <div class="element">5</div>
      <div class="element">6</div>
      <div class="element">7</div>
      <div class="element">8</div>
      <div class="Spacing"></div>
      <div class="element">9</div>
      <div class="element">10</div>
      <div class="element">11</div>
      <div class="element">12</div>
  </div>
  <h1>Expected 3 columns (with elements order above of course)</h1>
  <div class="container good">
      <div class="element">1</div>
      <div class="element">2</div>
      <div class="element">5</div>
      <div class="element">6</div>
      <div class="element">9</div>
      <div class="element">10</div>
      <div class="element">3</div>
      <div class="element">4</div>
      <div class="element">7</div>
      <div class="element">8</div>
      <div class="element">11</div>
      <div class="element">12</div>
  </div>
</body>

Again, the best way to add a margin between the columns would be to use separate containers for each column. But if you want to do it the way you are currently doing, then I would suggest the following. If you need an even margin between the columns of, let's say, 20px then you should add padding of 10px to the container of these red squares, and add a margin of 10px to these red squares. This will ensure that the columns are evenly spaced on all sides and in-between.

Here's an example

body {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

#A {
  display: flex;
  background-color: #FF0000;
  margin-bottom: 20px;
}

#B {
  display: flex;
  background-color: #FF0000;
  padding: 10px;
}

.Element {
  width: 75px;
  height: 75px;
  background-color: #0D0D0D;
  margin: 10px;
}
<div id="A">
  <div class="Element"></div>
  <div class="Element"></div>
  <div class="Element"></div>
</div>
<div id="B">
  <div class="Element"></div>
  <div class="Element"></div>
  <div class="Element"></div>
</div>

Compare the margin around the first rectangle and the second rectangle. The former one doesn't have equal margining outside the elements. But the latter one has equal margining everywhere.

Can you please check the below code? Hope it will work for you. With the help of flex properties and height, we have solved this issue as per your requirement without changing the element order.

Please refer to this link: https://jsfiddle.net/yudizsolutions/Lgqkjrxy/1/

body {
  width: 900px;
}

.container {
  display: flex;
  display: -webkit-flex;
  flex-wrap: wrap;
  -webkit-flex-wrap: wrap;
  flex-direction: column;
  -webkit-flex-direction: column;
  align-content: space-between;
  -webkit-align-content: space-between;
  height: 560px;
}

.element {
  background-color: red;
  margin: 20px;
  height: 100px;
  width: 100px;
  color: white;
  font-size: 50px;
  line-height: 100px;
  text-align: center;
}

.container.good .element {
  background-color: green;
}
<body>
  <h1>Elements from bdd</h1>
  <div class="container">
    <div class="element">1</div>
    <div class="element">2</div>
    <div class="element">3</div>
    <div class="element">4</div>
    <div class="element">5</div>
    <div class="element">6</div>
    <div class="element">7</div>
    <div class="element">8</div>
    <div class="element">9</div>
    <div class="element">10</div>
    <div class="element">11</div>
    <div class="element">12</div>
  </div>
</body>

Related