Image Aspect Ratios

An issue that seems to pop up on every project is when a client is able to upload images through a CMS to their website and the design requires a specific aspect ratio. How do we maintain a specific ratio and preserve the layout when we can't control the source image size.

Lets say the design calls for circular portraits. Thats fine if the source images are square, but as soon as a non-circular image is uploaded the design breaks. Here we have a fine portrait of Admiral Ackbar, but the client uploaded a rectangular source image. You can see the circle is stretched out to an oval and the design has been compromised.

Admiral Ackbar

One solution would be to hard-code the image dimensions to a specific ratio, however this could stretch the image. To avoid stretching it, in CSS you could set object-fit: cover which will prevent the image from stretching. Yes, we have our ratio set, and no distortion, however it's no longer responsive.

Admiral Ackbar

Okay, how do we keep it responsive and remain a circle? It involves a little more work but the result is worth it. Create an empty div and define both the width and top padding to create our container. Make sure the top padding is equal to the width and the div will remain square. Define the background-image inline, and set the border-radius to 50% and you've got a perfectly circular and responsive portrait, no matter the source image:

This approach also works for preserving the aspect ratio of square or rectangular images. Let's say your design contains beautiful 16:9 letterbox size hero image, set the width to 100% and padding-top to 56.25%. Why 56.25? 9 divided by 16 = 0.5625.

Using the top-padding we can control our aspect ratio: 56.25% for 9:16, 75% for 4x3, and so on...

The most common example of this is when the design calls for a 50/50 split between content and a full bleed image. Here we can also tweak the aspect ratio on mobile if a square is too tall.

content goes here

In this example if the right side content is more than expected it will pull the image along with it, growing the whole div instead of breaking the layout or clipping out of the container.

Okay, thats nice, but what about accessibility?

To preserve accessibility, David MacDonald recommends inserting a span with role="img" and aria-label="alt text of image".

from a screen reader perspective the div with the background image is ignored and so placing the span directly following it will provide that information in a way that will seem as if the alternate text was in the same place as the background image.

The only other issues are when the subject is near one of the edges, sometimes they can get clipped at certain screen sizes. Be sure to try to spot these situations before the come up - its typically team member photos or group shots that cause problems. Sometimes you're able to define the background position but not always.

Update: My current client is using CosmicJS for their CMS which apparently has face-detection baked in and will adjust images to avoid clipping peoples heads. I haven't used this feature yet, but I want to take a look.

Previous PostCSS Clip Path Next PostOS X Dark Mode Flip