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; }
Making square tiles with flexbox is simple! Just add flex-wrap and width , and everything will magically work as together!
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.
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 ;)
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With