Maintain Aspect Ratio of Background Image
Image source: Joshua Brandenburg

Maintain Aspect Ratio of Background Image

November 27, 2015

At times we want to have the div of a background image maintain the same aspect ratio as the image in the background. The most common use case for this I have encountered is when creating a full-width hero/masthead with a background image and text overlayed on top.

Here are a couple of ways to approach this.

vw method

If the width of the box is 100% of the viewport, you can use a height with a vw value. (1vw is 1/100th of the width of the viewport.)

Advantages:

  • No extra wrappers necessary.
  • Less scss.

Disadvantages:

  • less browser compatible (no IE8 and below)
  • (In Chrome at least) vw includes the scrollbar in the calculation, so the ratio is not perfect when scrollbars are present.

padding/absolute method

Using an extra wrapper, padding on a before pseudo class and absolutely positioning the inner div method.

This works because a padding percentage (even for top or bottom padding) is calculated based on the WIDTH of the element.

Advantages:

  • Greater browser compatibility.
  • Not limited to full viewport width. (Can be used at any width.)

Disadvantage:

  • Extra inner wrapper required.

Mixin

Here is the mixin I wound up using for the padding/absolute method. Watch out for the assumed inner div that is absolutely positioned. You may want to use a specific class name there such as .inner-wrapper instead of just > div.

@mixin aspect-ratio($width, $height) {
  position: relative;
  &:before {
    display: block;
    content: "";
    width: 100%;
    padding-top: ($height / $width) * 100%;
  }
  > div {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
  }
}

Then simply call the mixin when needed…

.my-masthead-div-with-background-image {
  @include aspect-ratio(8,1);
}

Experiment around with the techniques…

Edit this CodePen and change the scss values to see it in action.

See the Pen Maintaining Aspect Ratio by Brad Wade (@bradwade) on CodePen.