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.

#### 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.

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.

$400px 200px = 200px 100px = 2 1$

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.

### 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.

#### 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.

##### 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;
}

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.