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>

CSS Grid version

.square-container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(30%, 1fr));
  grid-gap: 10px;
}

.square {
  position: relative;
  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%;
}
<div class="square-container">

  <div class="square">
    <div class="content">
    </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>

Leave a Comment