Creating a responsive layout based on squares.

Creating a responsive layout based on squares may be more tricky than expected, because it require you to always ensure a given aspect ratio of 1:1. Here are some thoughts on a solution I came up with.

Imagine a layout should define a square, that is supposed to be biggest unit. All other elements are fractals of this biggest square, going down to a square that is supposed to be the smallest unit. I tried out various approaches to solve this and here is the one, that made out really well in the end.

Ensuring aspect ratio in responsive design.

When building a responsive design, the widths of all elements are related to the page's width (that's not the definition of responsive design and not always the fact, but true for most cases). To create a square, or other shape with an given aspect ratio, an element's height must also be related the pages's width. So, how can you do this?

Your first guess may be: use viewport units vw to set the width and height properties. Unfortunately there is one quirk with this idea. Viewport units are intended to be related to the viewport's size, not the page's width. That means, if your pages has a vertical scrollbar (which is the case mostly), 100vw will be wider than your page (exactly: by the width of the scrollbar). Therefore, elements placed beside each other, that add up to 100vw, will not be in one row.

The page's width, which we are interested in, can be taken into account by using width with a percentage value. So, width: 100% will always be the page's width, even if there is a vertical scrollbar in place.

But how can we address an element's height? Using percentage value for width and vw for height is possible, but this will not end up in a perfect square. Though width: 10% will always be a little less than height: 10vw.

Have you ever heard of the (fairly old) trick for intrinsic rations for video. With the use of this trick you can ensure a video will always match a given ratio, like 16:9.

This sound like the situation we are in, except the ratio should be 1:1 and we are not talking about videos. But anyway, this trick will do for us. It is based on a nifty, not very obvious, definition of in the CSS specs for padding.

The percentage is calculated with respect to the width of the generated box's containing block, even for 'padding-top' and 'padding-bottom'.

You got that? padding-bottom and padding-top are always related to the width of the surrounding block element. That's the key to build nice and perfect squares.

Implementation draft.

At first we define the biggest element to display on a pages. All other elements should fit into this element. This allows us to give more the page some structure and avoid complicated calculation. Let's call this our container.

Each container consists of one or multiple elements, which we'll call box.

In HTML code the outline of this structure will look as following:

<div class="container">
    <div class="box">
    <div class="box">
</div>

<div class="container">
    <div class="box">
</div>

<div class="container">
    <div class="box">
    <div class="box">
    <div class="box">
</div>

The container is the element where we'll use padding-bottom to ensure it always matches the required aspect ratio. On higher breakpoints we reduce the size of the container to place them beside each other instead of after each other.

.container {
    position: relative;
    width: 100%;
    padding-bottom: 100%;
    @media (min-width: 600px) {
        width: 50%;
        padding-bottom: 50%;
    }
    @media (min-width:1024px) {
        width: 33.3%;
        padding-bottom: 33.3%;
    }
}

Please make sure to understand, that padding-bottom does not refer the the width of container, but the the width of the block element surrounding it - which is the page. Therefore we need to set width and padding-bottom to the same value.

Now, that we have a structure to layout the main parts of the page, let's care about the squares we like to draw. A box is positioned absolute within a container and will a get a position and size based on percentages of the container size.

.box {
    position: absolute;
    width: 50%;
    height: 50%;
    top: 50%;
    left: 50%;
}

This box, for example, will fit in the lower right quarter of the   container.

Complete example.

After having all the important build blocks straight, all we have to do, is to defined different types of container, that will have an own way of organizing it's box elements. Something like this:

<div class="container type-c">  
    <div class="box box-1">
    <div class="box box-2">
    <div class="box box-3">
</div> 
.container.type-c {
    .box-1 {
        width: 50%; height: 50%;
        top: 0; left: 0;
    }
    .box-2 {
        width: 50%; height: 50%;
        top: 50%; left: 0;
    }
    .box-3 {
        width: 50%; height: 100%;
        top: 0; left: 50%;
    }
}

Putting all of this together ends up in an complete example, which can be found in this pen.

See the Pen Layout based on squares by aclaes (@aclaes) on CodePen.