Grid of Responsive Squares

Grid of responsive squares

New solution (2022)

CSS has changed since this aswer was written. We now have several properties that can drasticaly simplify code for a square grid :

  • The grid property to handle the grid layout (MDN reference)
  • The aspect ratio property to handle the square aspect ratio of each grid item (MDN reference)
  • The object-fit property to handle image centering and wether they should cover the square or not (MDN reference)

Here is an example :

.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 2%;
}

.square {
aspect-ratio: 1/ 1;
display: flex;
align-items: center;
padding: 5%;
background-color: #1E1E1E;
color: #fff;
}

.square img {
width: 100%;
height: 100%;
object-fit: contain;
object-position: center;
}

.square.fullImg {
padding: 0;
}

.square.fullImg img {
object-fit: cover;
}
<div class="grid">
<div class="square">
<ul>This demo shows you can center multiple types of content :
<li>Text</li>
<li>Images</li>
<li>Lists</li>
<li>... (you can also do it with forms)</li>
</ul>
</div>
<div class="square">98%</div>
<div class="square">3.9/5</div>
<div class="square"><img src="https://farm3.staticflickr.com/2878/10944255073_973d2cd25c.jpg" /></div>
<div class="square"><img src="https://farm9.staticflickr.com/8461/8048823381_0fbc2d8efb.jpg" /></div>
<div class="square"><img class="rs" src="https://farm5.staticflickr.com/4144/5053682635_b348b24698.jpg" /></div>
<div class="square fullImg"><img src="https://farm9.staticflickr.com/8461/8048823381_0fbc2d8efb.jpg" /></div>
<div class="square fullImg"><img class="rs" src="https://farm5.staticflickr.com/4144/5053682635_b348b24698.jpg" /></div>
<div class="square fullImg"><img src="https://farm3.staticflickr.com/2878/10944255073_973d2cd25c.jpg" /></div>
</div>

A grid layout with responsive squares

The padding-bottom trick is the most used to accomplish that.

You can combine it with both Flexbox and CSS Grid, and since using percent for margin/padding gives inconsistent result for flex/grid items (on older browser versions, see edit note below), one can add an extra wrapper, or like here, using a pseudo, so the element with percent is not the flex/grid item.


Edit: Note, there's an update made to the specs., that now should give consistent result when used on flex/grid items. Be aware though, the issue still occurs on older versions.


Note, if you will add content to the content element, it need to be position absolute to keep the square's aspect ratio.

Fiddle demo - Flexbox

Edit 2: In a comment I were asked how to have a centered text, so I added that in below snippet.

.square-container {
display: flex;
flex-wrap: wrap;
}

.square {
position: relative;
flex-basis: calc(33.333% - 10px);
margin: 5px;
border: 1px solid;
box-sizing: border-box;
}

.square::before {
content: '';
display: block;
padding-top: 100%;
}

.square .content {
position: absolute;
top: 0; left: 0;
height: 100%;
width: 100%;

display: flex; /* added for centered text */
justify-content: center; /* added for centered text */
align-items: center; /* added for centered text */
}
<div class="square-container">

<div class="square">
<div class="content">
<span>Some centered text</span>
</div>
</div>

<div class="square">
<div class="content spread">
</div>
</div>

<div class="square">
<div class="content column">
</div>
</div>

<div class="square">
<div class="content spread">
</div>
</div>

<div class="square">
<div class="content column">
</div>
</div>

</div>

How to make responsive squares for every element besides the last one, which has to have the same height as the others?

You need to filter the last-child and reset the vertical padding . codepen demo

possible fix to start from :

&:not(:last-child)::before {
content: "";
display: block;
padding-top: 100%;
}
&:last-child::before {
content: "";
display: block;
padding-top: 20%;/*here the values you want to reset */
}

if it is only about styling the padding, then

&::before {
content: "";
display: block;
padding-top: 100%;
}
&:last-child::before {
padding-top: 20%;
}

is plenty enough


:root {
/**
* [Changeable Settings]
* These are meant for updating the font and
* background colour later in JavaScript.
*/
--main-color: #415160;
--secondary-color: #fbfbf8;
--additional-color: #92928b;
--font-size: 1rem;
--line-height: 1.6rem;
--letter-spacing: 0rem;
--font-type: inherit;
/* FIXED SETTINGS */
/* [Colour Settings] */
--ink-blue: #415160;
--paper-white: #fbfbf8;
--drk-paper-white: #efefe7;
--brown-spot: #92928b;
/* [Font Settings] */
--xs-font-size: 0.6rem;
--sm-font-size: 0.8rem;
--reg-font-size: 1rem;
/* [Grid Settings] */
--grid-margin: 26px;
--grid-gutters: 9px;
--grid-column: 74px;
}

#font-settings {
margin-left: var(--grid-margin);
margin-right: var(--grid-margin);
background-color: var(--ink-blue);
padding: var(--reg-font-size);
border-radius: var(--reg-font-size);
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
}
#font-settings .square {
position: relative;
flex: 1 1 20%;
margin: var(--grid-gutters);
}
#font-settings .square::before {
content: "";
display: block;
padding-top: 100%;
}
#font-settings .square:last-child::before {
padding-top: calc(25% - var(--grid-gutters) );
}
#font-settings .square * {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
#font-settings .square *:hover {
box-shadow: 0px 0px 10px 10px rgba(0, 0, 0, 0.15);
}
<div id="font-settings">
<div class="square"><button>aaa</button></div>
<div class="square"><button>aaa</button></div>
<div class="square"><button>aaa</button></div>
<div class="square"><button>aaa</button></div>
<div class="square"><button>aaa</button></div>
<div class="square"><button>aaa</button></div>
<div class="square"><button>aaa</button></div>
<div class="square"><button>aaa</button></div>
<div class="square"><select>
<option>A</option>
<option>B</option>
<option>C</option>
</select></div>
</div>


Related Topics



Leave a reply



Submit