Skip to content

<picture> and <source> elements: How should 404s with placeholder image data be handled? #8916

@DavidJCobb

Description

@DavidJCobb

It's possible for a request for an image to receive a 404 response that has an image Content-Type with valid image data attached, to be displayed as a placeholder. Currently, img elements are required to display this placeholder data (per 4.8.4.3 Processing Model):

Whether the image is fetched successfully or not (e.g. whether the response status was an ok status) must be ignored when determining the image's type and whether it is a valid image.

What's less clear is how this should apply to the case of picture elements with a list of sources, when one of those sources fails with a placeholder 404 image.

The status quo

My understanding of the spec is that if a source fails with a 404, regardless of whether placeholder data is received, the browser is supposed to try the next source in the list:

  • The media resource selection algorithm, step 9, case children, sub-step 8 requires that the source's target resource be fetched using the resource fetch algorithm.
  • The resource fetch algorithm, step 4, case remote, sub-step 8, sub-sub-step 4 requires that the network request used to fetch the resource be verified. Verification fails if the internal response's status code is not 200 or 206.
  • Some of the steps around there link to the HTTP fetch standard; I dug around and didn't find anything in that standard that would result in the browser "lying" about a 404 request with placeholder data not being a 404. Looking at the HTTP-network fetch steps, it seems like the server's original status code is applied to the response directly, at least for codes outside the [100, 199] range.
  • If the resource fetch algorithm fails, then the media resource selection algorithm, step 9, case children will not be aborted at sub-step 8, and so will continue to the next steps, which involve moving onto the next source (if any) and trying that one.

It seems that the spec-compliant behavior would be:

  • If a source fails with a 404, try the next source, regardless of whether the failing source had placeholder image data attached to the 404 response.
  • If all sources fail, and the img also fails, then use only any placeholder image data attached to the img's 404 response. If the img 404 response did not contain placeholder data, then display a broken image (i.e. no placeholder data from any source will be used).

Current browser behavior

If Chromium and Mozilla Firefox encounter a source that 404s with placeholder content, they will display that placeholder content, instead of making any attempt to try the next source(s) in the list. Additionally, neither browser makes any attempt to try more than the first source with a supported MIME type. Consider the code below:

<!doctype html>
<html>
   <body>
      <picture>
         <!-- <source srcset="https://example.com/nonexistent.png" type="image/jpeg" /> -->
         <source srcset="https://i.ytimg.com/vi/asdf/nonexistent.jpg" type="image/jpeg" />
         <source srcset="https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg" type="image/jpeg" />
         <source srcset="https://i.ytimg.com/vi/dQw4w9WgXcQ/sddefault.jpg" type="image/jpeg" />
         <img set="https://i.ytimg.com/vi/dQw4w9WgXcQ/default.jpg" />
      </picture>
   </body>
</html>

We are here trying to display the YouTube thumbnail for Rick Astley's "Never Gonna Give You Up." There are multiple possible URLs for a YouTube thumbnail, and not all such URLs are available for every video; additionally, if any image request to the YouTube thumbnail server fails, the server returns a 404 response with a 120x90px image/jpeg placeholder attached. This placeholder is what the above code displays in Firefox and Chromium. If we uncomment the obviously broken example.com URL, then Firefox and Chromium just display a broken image; watching the network requests allows us to see that they never attempt to request anything else after failing to load nonexistent.png.

It seems, then, like a key portion of the spec for picture and source elements is completely unimplemented in every major browser.

So I guess my questions are...

  1. Should the spec be amended to match existing browser behavior? It seems like it'd be far more useful if web browsers actually implemented the "try each source until one works" part of the spec instead.

  2. Suppose that web browsers were to ignore 404 placeholder data on a source: if a source 404s, the browser tries the next source or, if none remain, the img, instead of just displaying any placeholder data that was sent along with the 404.

    If all sources fail, the img also fails, and one or more sources had placeholder data, then should the spec be amended to have the browser display one of those sources' placeholders? Should the browser prefer the earliest source in the list that had a placeholder? Should the browser prefer the img placeholder, if one was received, over all source placeholders?

    I don't know terribly much about how network requests are done under the hood, but I'd imagine that if browsers can use the earliest placeholder in the list, then they don't have to actually bother to fully load the placeholders for any failing source elements after that one.

  3. ...Am I even interpreting these parts of the spec properly to begin with?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions