Home

Height equals width with pure CSS

I was looking for a solution for flexible elements which remain the aspect ratio when resized. Until now I used some Javascript for resizing the elements.

Article //

But using the resize event and recalculate the height of an element is some kind of nasty and never felt right. Recently I found a solution in an article from A List Apart and a topic on StackOverflow, which works quite well. There was also potential for further reducing the code.

Examples (resize your browser to see the remaining ratios)

Aspect ratio of 1:1
Aspect ratio of 2:1
Aspect ratio of 1:2
Aspect ratio of 4:3
Aspect ratio of 16:9

Description

If you have an image with a certain aspect ratio you can easily keep the proportion with the "auto" value. Like:

img {
	min-width: 100%;
	height: auto;
}

The problem is that you can't use the "auto" value for the height property of a block element like a DIV or alike. It will always resize depending on the inner content/elements.

The trick

I found a solution which was already posted four years ago on A List Apart. Also a kind of follow-up on Stack Overflow. This is so brilliant that I want to share the beauty (NERD!) of that solution with you:

HTML

<div class='box'> 
	<div class='content'>Aspect ratio of 1:1</div> 
</div>

We need two block elements to achieve the desired behaviour. No images, no Javascript.

CSS

.box {
	position: relative;
	width: 50%;		/* desired width */
}
.box:before {
	content: "";
	float: left;
	padding-top: 100%; 	/* initial ratio of 1:1*/
}

So, what's this? We define a pseudo element for our box and give it a padding-top of 100%. Since this 100% value relates to the element's width... you get it (height: 0; padding-bottom: 100%; would also work, but then you have to adjust the padding-bottom value every time you change the width).

So our box is already as high as wide. If you only want to display some colored tiles, you are already done. But since the user experience is way better if you also provide some content we add a content element to our box.

The content

And here is the trick: We just float the content element. This lets the content fill the outer box.

.content {
	float: left;
}

That's it. Brilliant, isn't it? Even a padding doesn't break it, no need for box-sizing: border-box here.

Other aspect ratios

If you want to create other ratios just change the padding-top value of the pseudo element (see example):

/* Other ratios */
.ratio2_1:before {
	padding-top: 50%;
}
.ratio1_2:before {
	padding-top: 200%;
}
.ratio4_3:before {
	padding-top: 75%;
}
.ratio16_9:before {
	padding-top: 56.25%;
}

Replies