Unsized-images audit failure for SSR'ed responsive/intrinsic-sized images in AMP
See original GitHub issueProvide the steps to reproduce
Run LH on https://weston.ruter.net/2020/09/30/story-running-on-mount-tabor/
This is an AMP page that includes server-side rendering via the AMP Optimizer.
AMP has support for responsive/intrinsically-sized images with markup like so:
<amp-img
width="1200"
height="1600"
src="https://i1.wp.com/weston.ruter.net/wp-content/uploads/2020/09/PXL_20200927_205658004-scaled.jpg?fit=1200%2C1600&ssl=1"
class="attachment-post-thumbnail size-post-thumbnail wp-post-image amp-wp-enforced-sizes"
alt="Pump house for Mount Tabor reservoir #5 with Downtown Portland in the distance"
srcset="https://i1.wp.com/weston.ruter.net/wp-content/uploads/2020/09/PXL_20200927_205658004-scaled.jpg?w=1920&ssl=1 1920w, https://i1.wp.com/weston.ruter.net/wp-content/uploads/2020/09/PXL_20200927_205658004-scaled.jpg?resize=225%2C300&ssl=1 225w, https://i1.wp.com/weston.ruter.net/wp-content/uploads/2020/09/PXL_20200927_205658004-scaled.jpg?resize=525%2C700&ssl=1 525w, https://i1.wp.com/weston.ruter.net/wp-content/uploads/2020/09/PXL_20200927_205658004-scaled.jpg?resize=768%2C1024&ssl=1 768w, https://i1.wp.com/weston.ruter.net/wp-content/uploads/2020/09/PXL_20200927_205658004-scaled.jpg?resize=1152%2C1536&ssl=1 1152w, https://i1.wp.com/weston.ruter.net/wp-content/uploads/2020/09/PXL_20200927_205658004-scaled.jpg?resize=1536%2C2048&ssl=1 1536w, https://i1.wp.com/weston.ruter.net/wp-content/uploads/2020/09/PXL_20200927_205658004-scaled.jpg?w=1740&ssl=1 1740w"
sizes="(max-width: 1200px) 100vw, 1200px"
layout="intrinsic"
disable-inline-width="">
</amp-img>
Without server-side rendering, the AMP boilerplate CSS is included which hides the page until AMP’s v0.js
is loaded and can initialize these custom elements to provide the proper dimensions. However, when server-side rendering is enabled then the above markup is served as follows:
<amp-img
width="1200"
height="1600"
src="https://i1.wp.com/weston.ruter.net/wp-content/uploads/2020/09/PXL_20200927_205658004-scaled.jpg?fit=1200%2C1600&ssl=1"
class="attachment-post-thumbnail size-post-thumbnail wp-post-image amp-wp-enforced-sizes i-amphtml-layout-intrinsic i-amphtml-layout-size-defined"
alt="Pump house for Mount Tabor reservoir #5 with Downtown Portland in the distance"
srcset="https://i1.wp.com/weston.ruter.net/wp-content/uploads/2020/09/PXL_20200927_205658004-scaled.jpg?w=1920&ssl=1 1920w, https://i1.wp.com/weston.ruter.net/wp-content/uploads/2020/09/PXL_20200927_205658004-scaled.jpg?resize=225%2C300&ssl=1 225w, https://i1.wp.com/weston.ruter.net/wp-content/uploads/2020/09/PXL_20200927_205658004-scaled.jpg?resize=525%2C700&ssl=1 525w, https://i1.wp.com/weston.ruter.net/wp-content/uploads/2020/09/PXL_20200927_205658004-scaled.jpg?resize=768%2C1024&ssl=1 768w, https://i1.wp.com/weston.ruter.net/wp-content/uploads/2020/09/PXL_20200927_205658004-scaled.jpg?resize=1152%2C1536&ssl=1 1152w, https://i1.wp.com/weston.ruter.net/wp-content/uploads/2020/09/PXL_20200927_205658004-scaled.jpg?resize=1536%2C2048&ssl=1 1536w, https://i1.wp.com/weston.ruter.net/wp-content/uploads/2020/09/PXL_20200927_205658004-scaled.jpg?w=1740&ssl=1 1740w"
sizes="(max-width: 1200px) 100vw, 1200px"
layout="intrinsic"
disable-inline-width=""
i-amphtml-layout="intrinsic"
>
<i-amphtml-sizer class="i-amphtml-sizer">
<img alt="" aria-hidden="true" class="i-amphtml-intrinsic-sizer" role="presentation" src="data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9JzE2MDAnIHdpZHRoPScxMjAwJyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZlcnNpb249JzEuMScvPg==">
</i-amphtml-sizer>
</amp-img>
Notice the i-amphtml-sizer > img
element. This is what is used to give the responsive image a static layout, and because of this AMP doesn’t need to hide the page until the AMP runtime loads.
Nevertheless, herein lies a problem with Lighthouse. The i-amphtml-sizer > img
image here is flagged by the unsized-images audit for lacking a width
and height
:
Nevertheless, the lack of the width
and height
is precisely how AMP is able to implement responsive support for such intrinsically-sized responsive images. The img[src]
here has a base64-encoded data:
URL for an SVG image:
<svg height='1600' width='1200' xmlns='http://www.w3.org/2000/svg' version='1.1'/>
Notice that it has the same dimensions (1200x1600) that the container image is needing. This is a hack that is used given that the web platform does not yet have aspect-ratio()
CSS yet available, although work is underway to make use of it: https://github.com/ampproject/amphtml/issues/30291. The only way this hack works is if the intrinsic size of the image is used for layout, and this breaks if the width
and height
are provided on the img
.
All this being said, I believe the unsized-images audit should be explicitly exempt images that have a src
containing a data:
URL, especially when decoding=async
is absent. Such images do not contribute to CLS because the intrinsic sizing is available at the time of parsing. Currently the unsized-images audit is showing a false positive.
What is the current behavior?
Images in AMP used for intrinsic sizing are flagged as being unsized.
What is the expected behavior?
Images with data:
for src
should be exempted from the audit, especially when decoding=async
is absent.
Environment Information
- Affected Channels: All
- Lighthouse version: 6.4.0
- Chrome version: 88.0.4294.0 (Official Build) canary (x86_64)
- Node.js version: n/a
- Operating System: MacOS
Related issues
Issue Analytics
- State:
- Created 3 years ago
- Reactions:3
- Comments:6 (1 by maintainers)
Top GitHub Comments
I just checked in Chrome Canary (which is running Lighthouse 7.2.0) and I’m not seeing the audit failure anymore.
yup, that’s quite the hack. nice.
Your suggested change sounds good to me. Inline data urls can’t reference external sources, so it should always be sized correctly and not result in shifts later on
let’s also make sure we are handling decoding=async correctly.