Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

css grid of squares with flexbox

I am trying to create a responsive grid of squares. The squares should resize to fit the viewport's width. The squares should not resize when changing the viewport's height.

I got how to adjust the width of each square, but I don't know how to make the elements square and how to scale their height when the viewport width changes.

In the example at the fiddle below the seven squares should always fit horizontally, and they should scale as squares. I do not care how many rows are visible.

Fiddle here http://jsfiddle.net/gonyhvz8/11/

<body> <div class="flex-container">     <div class="flex-item">1</div>     <div class="flex-item">2</div>     <div class="flex-item">3</div>     <div class="flex-item">4</div>     <div class="flex-item">5</div>     <div class="flex-item">6</div>     <div class="flex-item">7</div> </div> <div class="flex-container">     <div class="flex-item">1</div>     <div class="flex-item">2</div>     <div class="flex-item">3</div>     <div class="flex-item">4</div>     <div class="flex-item">5</div>     <div class="flex-item">6</div>     <div class="flex-item">7</div> </div> <div class="flex-container">     <div class="flex-item">1</div>     <div class="flex-item">2</div>     <div class="flex-item">3</div>     <div class="flex-item">4</div>     <div class="flex-item">5</div>     <div class="flex-item">6</div>     <div class="flex-item">7</div> </div> <div class="flex-container">     <div class="flex-item">1</div>     <div class="flex-item">2</div>     <div class="flex-item">3</div>     <div class="flex-item">4</div>     <div class="flex-item">5</div>     <div class="flex-item">6</div>     <div class="flex-item">7</div> </div> <div class="flex-container">     <div class="flex-item">1</div>     <div class="flex-item">2</div>     <div class="flex-item">3</div>     <div class="flex-item">4</div>     <div class="flex-item">5</div>     <div class="flex-item">6</div>     <div class="flex-item">7</div> </div> <div class="flex-container">     <div class="flex-item">1</div>     <div class="flex-item">2</div>     <div class="flex-item">3</div>     <div class="flex-item">4</div>     <div class="flex-item">5</div>     <div class="flex-item">6</div>     <div class="flex-item">7</div> </div> <div class="flex-container">     <div class="flex-item">1</div>     <div class="flex-item">2</div>     <div class="flex-item">3</div>     <div class="flex-item">4</div>     <div class="flex-item">5</div>     <div class="flex-item">6</div>     <div class="flex-item">7</div> </div> 

.flex-container {   padding: 0;   margin: 0;   list-style: none;   display: -webkit-box;   display: -moz-box;   display: -ms-flexbox;   display: -webkit-flex;   display: flex;   -webkit-flex-flow: row;   justify-content: space-around;   height: 50px;   line-height:30px; }  .flex-item {   background: tomato;   margin: 5px;   color: white;   font-weight: bold;   font-size: 1.5em;   text-align: center;   flex: 1 0 0px;   height: auto; } 
like image 652
Moto Avatar asked Mar 27 '15 18:03

Moto


People also ask

How do you make a flexbox square grid?

Making square tiles with flexbox is simple! Just add flex-wrap and width , and everything will magically work as together!

Can you mix CSS grid and flexbox?

With Grid and Flexbox, CSS is changing dramatically. Whereas in the past, creating complex layouts required all sorts of CSS hacks, JavaScript, or both, now you can use Flexbox and Grid—tools designed specifically for layouts—to create responsive web pages with precise, custom layouts.


2 Answers

you should not set any size. you may use an extra element or a pseudo elemnt with vertical padding in %. this will allow you to use width as reference : a snippet to show:

.flex-container {     padding: 0;     margin: 0;     list-style: none;     display: -webkit-box;     display: -moz-box;     display: -ms-flexbox;     display: -webkit-flex;     display: flex;     -webkit-flex-flow: row;     justify-content: space-around;         line-height:30px; } .flex-item {     background: tomato;     margin: 5px;     color: white;     font-weight: bold;     font-size: 1.5em;     text-align: center;     flex: 1 0 auto;     height:auto; } .flex-item::before {     content:'';     float:left;     padding-top:100%; }
<body>     <div class="flex-container">         <div class="flex-item">1</div>         <div class="flex-item">2</div>         <div class="flex-item">3</div>         <div class="flex-item">4</div>         <div class="flex-item">5</div>         <div class="flex-item">6</div>         <div class="flex-item">7</div>     </div>     <div class="flex-container">         <div class="flex-item">1</div>         <div class="flex-item">2</div>         <div class="flex-item">3</div>         <div class="flex-item">4</div>         <div class="flex-item">5</div>         <div class="flex-item">6</div>         <div class="flex-item">7</div>     </div>     <div class="flex-container">         <div class="flex-item">1</div>         <div class="flex-item">2</div>         <div class="flex-item">3</div>         <div class="flex-item">4</div>         <div class="flex-item">5</div>         <div class="flex-item">6</div>         <div class="flex-item">7</div>     </div>     <div class="flex-container">         <div class="flex-item">1</div>         <div class="flex-item">2</div>         <div class="flex-item">3</div>         <div class="flex-item">4</div>         <div class="flex-item">5</div>         <div class="flex-item">6</div>         <div class="flex-item">7</div>     </div>     <div class="flex-container">         <div class="flex-item">1</div>         <div class="flex-item">2</div>         <div class="flex-item">3</div>         <div class="flex-item">4</div>         <div class="flex-item">5</div>         <div class="flex-item">6</div>         <div class="flex-item">7</div>     </div>     <div class="flex-container">         <div class="flex-item">1</div>         <div class="flex-item">2</div>         <div class="flex-item">3</div>         <div class="flex-item">4</div>         <div class="flex-item">5</div>         <div class="flex-item">6</div>         <div class="flex-item">7</div>     </div>     <div class="flex-container">         <div class="flex-item">1</div>         <div class="flex-item">2</div>         <div class="flex-item">3</div>         <div class="flex-item">4</div>         <div class="flex-item">5</div>         <div class="flex-item">6</div>         <div class="flex-item">7</div>     </div> </body>

an inline-block element could do too, just adapt the display/behavior of the box and it's content. the magic here comes from padding:50% 0; (100% vertical padding equals width of parent). see w3c about vertical margin and padding

[edit 07/2021]about centering the content inside that square for who ever needs this too (make the square itself a flex boxe too):

.flex-container {     padding: 0;     margin: 0;     list-style: none;     display: -webkit-box;     display: -moz-box;     display: -ms-flexbox;     display: -webkit-flex;     display: flex;     -webkit-flex-flow: row;     justify-content: space-around;         line-height:30px; } .flex-item {     background: tomato;     margin: 5px;     color: white;     font-weight: bold;     font-size: 1.5em;     text-align: center;     flex: 1 0 auto;     height:auto;          display:flex;     align-items:center;     justify-content:center; } .flex-item::before {     content:'';     padding-top:100%; }
<body>     <div class="flex-container">         <div class="flex-item">1</div>         <div class="flex-item">2</div>         <div class="flex-item">3</div>         <div class="flex-item">4</div>         <div class="flex-item">5</div>         <div class="flex-item">6</div>         <div class="flex-item">7</div>     </div>     <div class="flex-container">         <div class="flex-item">1</div>         <div class="flex-item">2</div>         <div class="flex-item">3</div>         <div class="flex-item">4</div>         <div class="flex-item">5</div>         <div class="flex-item">6</div>         <div class="flex-item">7</div>     </div>     <div class="flex-container">         <div class="flex-item">1</div>         <div class="flex-item">2</div>         <div class="flex-item">3</div>         <div class="flex-item">4</div>         <div class="flex-item">5</div>         <div class="flex-item">6</div>         <div class="flex-item">7</div>     </div>     <div class="flex-container">         <div class="flex-item">1</div>         <div class="flex-item">2</div>         <div class="flex-item">3</div>         <div class="flex-item">4</div>         <div class="flex-item">5</div>         <div class="flex-item">6</div>         <div class="flex-item">7</div>     </div>     <div class="flex-container">         <div class="flex-item">1</div>         <div class="flex-item">2</div>         <div class="flex-item">3</div>         <div class="flex-item">4</div>         <div class="flex-item">5</div>         <div class="flex-item">6</div>         <div class="flex-item">7</div>     </div>     <div class="flex-container">         <div class="flex-item">1</div>         <div class="flex-item">2</div>         <div class="flex-item">3</div>         <div class="flex-item">4</div>         <div class="flex-item">5</div>         <div class="flex-item">6</div>         <div class="flex-item">7</div>     </div>     <div class="flex-container">         <div class="flex-item">1</div>         <div class="flex-item">2</div>         <div class="flex-item">3</div>         <div class="flex-item">4</div>         <div class="flex-item">5</div>         <div class="flex-item">6</div>         <div class="flex-item">7</div>     </div> </body>

You may also think interesting : Responsive grid of squares within a responsive grid of squares & 4x4 grid of squares that scale up to a maximum width if this answer do not fully suits your square needs ;)

like image 54
G-Cyrillus Avatar answered Sep 16 '22 17:09

G-Cyrillus


For those that also want to use display: flex inside the square divs, you need to use display: table for the :before element, otherwise the square will work with Chrome but won't work with Firefox or Edge (as of Firefox 47 and Edge 13).

In the snippet bellow, which should work for all browsers, I also demonstrate how to wrap unlimited items with percentage columns (in this case 20%) and separate them with padding and inner divs, since margins with percentages do not work correctly in FF and of course Edge.

.flex-container {    display: flex;    justify-content: start;    flex-wrap: wrap;   }    .flex-cell {    flex: 0 0 20%;    display: flex;    justify-content: center;    align-items: stretch;    padding: 0.5rem;    box-sizing: border-box;  }    .flex-cell:before {    content: '';    display: table;    padding-top: 100%;  }    .flex-item {    flex-grow: 1;    border: 1px solid black;    background: tomato;    color: white;        display: flex;    justify-content: center;    align-items: center;  }
<body>      <div class="flex-container">          <div class="flex-cell">              <div class="flex-item">1</div>          </div>          <div class="flex-cell">              <div class="flex-item">2</div>          </div>          <div class="flex-cell">              <div class="flex-item">3</div>          </div>          <div class="flex-cell">              <div class="flex-item">4</div>          </div>          <div class="flex-cell">              <div class="flex-item">5</div>          </div>          <div class="flex-cell">              <div class="flex-item">6</div>          </div>          <div class="flex-cell">              <div class="flex-item">7</div>          </div>          <div class="flex-cell">              <div class="flex-item">8</div>          </div>          <div class="flex-cell">              <div class="flex-item">9</div>          </div>          <div class="flex-cell">              <div class="flex-item">10</div>          </div>          <div class="flex-cell">              <div class="flex-item">11</div>          </div>          <div class="flex-cell">              <div class="flex-item">12</div>          </div>      </div>  </body>
like image 31
CGodo Avatar answered Sep 20 '22 17:09

CGodo