## DEV Community 👩‍💻👨‍💻 is a community of 921,001 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Aleksei Berezkin

Posted on • Updated on

# Making perfect square tiles with flexbox

Added on May 30, 2021. The post was originally written keeping old browsers in mind. For recent browsers there's better solution kindly suggested by Temani Afif.

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

<div class='container'>
<div class='tile'>1</div>
<div class='tile'>2</div>
<div class='tile'>3</div>
<div class='tile'>4</div>
<div class='tile'>5</div>
<div class='tile'>6</div>
</div>

.container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}

.tile {
width: 32%;
&:nth-child(2n) {
background-color: Bisque;
}
&:nth-child(2n+1) {
background-color: PowderBlue;
}
}


Hmm... That doesn't look nice: tiles are far from being square; and the problem here is that we didn't specify any height. But here comes a tricky thing: the height must be equal width. Is it even possible when width is not fixed? It is! But it's very hard to guess unless you know 😉 See what MDN says about padding-top:

<percentage>
The size of the padding as a percentage, relative to the width of the containing block

Let's apply it:

.tile {
width: 32%;
// backgrounds...
}


Again, something went terribly wrong. Why is that? Well, padding-top works correctly, and it took the width from .container, not .tile. In other words, tiles are as high as the container is wide 😄 Can we fix it? Let's move padding to an inner element of .tile which we create with ::before pseudo-element:

.tile {
width: 32%;
&::before {
content: '';
display: block;
}
// backgrounds...
}


Much better! However, there are still 3 small issues.

#### There's no vertical space between tiles

It's quite easy: just add some bottom-margin to .tile. What should it be? Let's calculate:

$space = {100\% - 32\% \sdot 3 \over 2} = 2\%$
.tile {
width: 32%;
margin-bottom: 2%;
// ::before...
// backgrounds...
}


#### Last tile is right-aligned

That's because flex allocates space between elements even if the row is not full. The easiest way to fix this is to add some right-margin to the last element. The trick is to select it only when it's the second in a row:

.tile {
width: 32%;
margin-bottom: 2%;
&:last-child:nth-child(3n+2) {
margin-right: 34%;
}
// ::before...
// backgrounds...
}


What is 34%? It's simply $32\%+2\%$ — a width normally occupied by the last tile and the space before it.

#### Having just colored numbers is not fun

That's easy yet the most important! Let's plug in some photo.

.tile {
background-image: url(...);
background-position: center;
background-size: cover;
// width, margins, ::before...
}


We can also remove numbers from HTML:

<div class='container'>
<div class='tile'></div>
...
</div>


### Let's enjoy the result!

Thanks for reading this! Do you know other interesting flexbox use cases?

## Top comments (6)

Temani Afif

You can do like this too: jsfiddle.net/s85o9ag6/2/ (aspect-ratio + calc + gap) and you no more need to bother with complex calculation and the padding that will push your content..

Aleksei Berezkin • Edited on

Thanks, bookmarked your solution. EDIT: updated the post

Andrew Boddy

I am hunting for a solution you might like to write about... responsive tiles ( not square) . I am trying flexbox but the last row is stretching but I want all the tiles to be equal. Also height is a ratio of width... any tips?

Aleksei Berezkin

What about this comment? dev.to/afif/comment/1ei41 It's better than my solution 😉 Of course given you are free of old browsers.

Aria Janke

Hello, under which license are your code snippets released? I cannot use anything posted here until I'm sure that it is legal to use.

Thank you

Aleksei Berezkin

Hi, I believe Code Pen license applies blog.codepen.io/documentation/lice...

#### Find what you were looking for? Join hundreds of thousands of developers on DEV so you can:

🌚 Enable dark mode
🔠 Change your default font
📚 Adjust your experience level to see more relevant content