Responsive images and other fluid media (like videos) are fundamental elements of modern web development. Despite the fact that responsive design has become ubiquitous in the web industry, a solution for high quality media that loads quickly and looks great on all viewports remains elusive.

There are two factors which determine how media is presented in the browser:

Applied Styles
the styling which is applied to a media element which defines it’s appearance (dimensions) at different viewport sizes.
Intrinsic Dimensions
the inherent dimensions encoded within the metadata of a media element.

Fluid Layout

See the Pen BWEjjQ by Joey Hoer (joeyhoer).

Layout Attributes

When thinking about how a media element’s dimensions affects page layout, it is important to consider how dimensions are calculated by the browser. Each image has an intrinsic width and height which is defined in the image metadata or described in the encoded image data and a layout width and height which is defined by the size at which the image is actually rendered on the page.

Before the browser can layout the appropriate amount of space on the page based on the intrinsic dimensions, it must download the image (or a sufficient amount of metadata from the image). This can lead to content “jumping” when a reflow occurs as the image dimensions are discovered by the browser during download. Fortunately, the HTML specification provides width and height attributes on image elements to allow authors to define the desired size of the image. I will refer to these attributes as “layout attributes”.

The height and width attributes give user agents an idea of the size of an image or object so that they may reserve space for it and continue rendering the document while waiting for the image data.

HTML 4.01 specification

Old Standards

It was once best practice to define both the width and height attributes of image elements to ensure that a page rendered quickly and allowed images to load asynchronously without triggering layout reflows and repaints. As older versions of Google’s Page Speed recommendations explained:

When the browser lays out the page, it needs to be able to flow around replaceable elements such as images. It can begin to render a page even before images are downloaded, provided that it knows the dimensions to wrap non-replaceable elements around. If no dimensions are specified in the containing document, or if the dimensions specified don’t match those of the actual images, the browser will require a reflow and repaint once the images are downloaded. To prevent reflows, specify the width and height of all images, either in the HTML tag, or in CSS.

Google Page Speed

Note: The Google Page Speed article linked above is from a cached version from March 2012. I was unable to find any equivalent recommendation in more recent versions of Google Page Speed.

Matching the layout attributes to the intrinsic dimensions of an image will ensure that the appropriate amount of space is reserved for the image. It is also possible to proportionally adjust these layout attributes (based on the intrinsic dimensions) without affecting the aspect ratio of the rendered image (which may be useful for displaying images on displays with high pixel density). For example, a 400px × 200px image could be scaled proportionally to a size of 200px × 100px on devices with 2x pixel density.

400px200px=200px100px=21

Images also have an intrinsic aspect ratio which is based on the intrinsic dimensions. When only one dimension is defined, and when the width and height properties are set to auto (the default value), the browser uses the image’s intrinsic aspect ratio to scale images proportionally to different sizes. In other words, if only one layout attribute is defined (e.g. width), the image will be scaled proportionally to match that dimension. This characteristic of images allows CSS to be used to smoothly scale images between different sizes in responsive design.

Fluid Width Images

To achieve fluid media elements, an image’s layout attributes must be overwritten with CSS. By setting the max-width of and image to 100%, developers can ensure that images will never be larger than their parent container. Defining a maximum width, and allowing the height to be calculated using the intrinsic aspect ratio, discussed earlier, effectively creates a fluid image solution.

However, an issue arises when max-width is set on an image that also has the height attribute defined. Because the image does not correctly maintain it’s aspect ratio as the parent container becomes smaller than the image width; instead the image becomes “smushed”. To work around this issue, the height property must always be set to auto—this can be accomplished with CSS.

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

See the Pen Visualizing Fluid Media by Joey Hoer (joeyhoer).

Note: Some developers may be confused here, knowing that inline styles have a higher specificity than other CSS rules. While this is true, “presentational attributes” (e.g. width and height attributes) are not the same as “inline styles” (i.e. the style attribute). The CSS specification outlines how browsers may implement specificity for “stylistic attributes”:

The UA may choose to honor presentational attributes in an HTML source document. If so, these attributes are translated to the corresponding CSS rules with specificity equal to 0, and are treated as if they were inserted at the start of the author style sheet. They may therefore be overridden by subsequent style sheet rules. In a transition phase, this policy will make it easier for stylistic attributes to coexist with style sheets.

CSS 2.1 specification §6.4.4

Other Elements

The same styling may also be applied to other media elements which have an intrinsic height, allowing them to maintain their aspect ratio as they scale (when height is set to auto). These elements include:

  • audio
  • canvas
  • img
  • svg
  • video

Other elements may also benefit from having a max-width of 100% applied, but do not have an intrinsic height. These elements include:

  • select
  • textarea
  • input
  • iframe
  • embed
  • object

Reflows on Fluid Images

A layout issue occurs before the image has loaded; if height is set to auto and the intrinsic dimensions have not yet been determined, the calculated image height will be 0. Because the most common fluid image technique (seen above) relies on the height being set to auto, this approach causes reflows and repaints as images are downloaded.

An img element is initially unavailable.

When an img element is [partially or completely] available, it provides a paint source whose width is the image’s intrinsic width, whose height is the image’s intrinsic height, and whose appearance is the intrinsic appearance of the image.

[The] attributes width and height must return the rendered width and height of the image … if the image is being rendered … to a visual medium; or else the intrinsic width and height of the image … if the image is available but not being rendered to a visual medium; or else 0, if the image is not available.

HTML5 Embedded Content Specification §4.7.5. The img element

Placeholder Solutions

One solution to prevent reflows when using fluid images is to utilize a placeholder element that reserves space for the image. This technique is common for lazy-loaded images, but provides benefits to all users, as devices with poor connections may require some time to download images, and content reflows always present a jarring user experience.

For a placeholder solutions to be effective, the author must know the desired aspect ratio of the image in advance.

Canvas Placeholder

For example, a blank canvas element could be used:

<div class="placeholder">
  <canvas width="{{ width }}" height="{{ height }}"></canvas>
  <img src="…" alt="…"/>
</div>
.placeholder {
  display: inline-block;
  position: relative;

  canvas {
    display: block;
    max-width: 100%;
  }

  img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }
}

In this example, a canvas element is defined with width and height attributes equal to that of the image which will be “replacing” it. The canvas will be “painted over” when the image loads due to absolute positioning of the image. This technique works because the canvas element scales proportionately when resized, even when constrained by a max-width. This is because:

The intrinsic dimensions of the canvas element when it represents embedded content are equal to the dimensions of the element’s bitmap.

HTML5 Specification §4.11.4 The canvas element

Aspect-Ratio Placeholder

Alternatively, a placeholder can be created with a div rather than the canvas element. By using a pseudo element to preserve the aspect ratio of the container, a fluid placeholder can be created, allowing the area to be “painted over” by absolutely positioning the image.

<div class="placeholder" style="--aspect-ratio:calc(100%/({{ width }}/{{ height }}));max-width:{{ width }}px">
  <img src="…" alt="…"/>
</div>
.placeholder {
  display: inline-block;
  width: 100%;
  position: relative;

  &::before {
    content: '';
    display: block;
    padding-top: var(--aspect-ratio);
  }

  img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }
}

Sizes Attribute

In addition to the layout attributes (width and height) described above, the sizes attribute (introduced win HTML5) may also be used to specify varying images sizes for different pixel densities and viewport widths.

<img src="…" width="100" height="100" sizes="100vw" />

While these layout attributes are useful for preventing layout reflows, they do not directly make the images scale as their container scales.

Future Solutions

A proposal for a permanent solution to this problem is in development. The intrinsicsize attribute may one day allow authors to define the aspect ratio of a media element in advance without the need for additional styling hooks or placeholder elements.