32 notes &
Use CSS to Specify the Aspect Ratio of a Fluid Element
[Update: Although I discovered this trick independently, I’ve since learned that Thierry Koblentz beat me to it. You can find his 2009 article on A List Apart. Credit where credit is due.]
This technique can be used to specify the aspect ratio of a fluid element using only CSS, no JavaScript or placeholder image required. By “fluid element”, I mean an element that can be dynamically resized. This requires that the width of the element be specified, and that the height of the element be expressed as a function of the width (or vice versa, though here the width must be specified).
The example below assumes an inline-level element in the normal flow, though the technique can be extended to block-level elements and absolutely positioned elements.
First, the HTML:
<div id="container">
<div id="dummy"></div>
<div id="element">
some text
</div>
</div>
The element whose aspect ratio we want to specify has the ID “element”. The element is wrapped by a container that will be used to specify the width. Additionally, the element has a dummy element as a previous sibling that will be used the express the height as a function of the width. Effectively, the dummy element enforces the aspect ratio.
Now, the CSS:
#container {
display: inline-block;
position: relative;
width: 50%;
}
#dummy {
padding-top: 75%; /* 4:3 aspect ratio */
}
#element {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: silver /* show me! */
}
A working example can be seen here.
Why does this work?
display:inline-blockgives the container a shrink-to-fit box.position:relativegives the container a position box. The position box acts as the containing block of the inner elements. (Note: Usingposition:absolutewould give the element a shrink-to-fit box that would act as the containing block of the inner elements.)width:50%gives the box of the container a width that will be used for the aspect ratio. The width can be specified as a length or as a percentage.padding-top:75%gives the box of the dummy element a height that is 75% of the aforementioned width, thus defining the aspect ratio. The key here is that a percentage value forpadding-toporpadding-bottom(or formargin-topormargin-bottom, for that matter) refers to the width of the containing block. Because the container is an inline-level block container, the height of the container is automatically computed as the height of the dummy element, which is based on the width of the container. Voilà, instant aspect ratio using only CSS.position:absoluteremoves the element from the normal flow inside the container, allowing the dummy element to dictate the sizing of the container.top/bottom/left/right:0stretches the element to the edges of the container, which are determined by the aspect ratio as per the above. The element will thus receive all user events. Set margin/border/padding to taste.
[Edit: In the explanation of padding-top above, I swapped padding and margin from the original version of this post, in response to the excellent catch by Matthew and the follow-up suggestion from ciantic.]
I have tested this on the latest versions of Google Chrome, Firefox, Safari, and Opera as of this writing, with no apparent hangups.