Skip to content

How to make WordPress OEmbeds work in Chrome

I observed that embedded blog posts are no longer loading when the site is viewed with Chrome-based browsers. This is serious, and nobody seems to be talking about it!

When you embed a WordPress blogpost in a blogpost, WordPress has a fancy way of providing fall-back content in case that the embedded content doesn’t load.

  1. A simple link to the embedded content is placed as part of the blog content. This is in case the embedded content can’t be loaded – at least the reader sees something.
  2. An iframe referencing the embedded content is placed underneath. This iframe is hidden with a clipping rectangle of 0 dimension.
  3. Once the iframe content is loaded, a message is sent to the parent frame (your blogpost) to notify that the embedded content is ready.
  4. The simple link is removed and the iframe clipping retangle is removed.

Follow this link to learn more about WordPress embeds.

This is a smooth way of handling embedded content. The reader is never left feeling that something is completely missing.

Simple link to the embedded content
The embedded content is loaded

Loading an iframe can be data and performance heavy, especially in a world where speed is king and mobile browsing brings significant traffic. It’s better to defer content loads as much as possible to keep the initial page load quick and reduce the data usage of the reader to only what they actually consume.

This doesn’t work in Chrome or Edge – the embedded content remains hidden

Major browsers now support lazy loading, but Chrome seems to have taken things very literally – lazy-loaded iframes have set conditions that prevent loading.

The loading attribute affects iframes differently than images, depending on whether the iframe is hidden. (Hidden iframes are often used for analytics or communication purposes.) Chrome uses the following criteria to determine whether an iframe is hidden:

The iframe’s width and height are 4px or smaller.
display: none or visibility: hidden is applied.
The iframe is placed off-screen using negative X or Y positioning.

https://web.dev/iframe-lazy-loading/

WordPress hides the iframe with an inline style clip: rect(1px, 1px, 1px, 1px) and that makes the width and height smaller than 4px. This prevents the iframe from loading and the embedded content remains hidden – the reader will only see the simple link when viewing this blogpost in Chrome or Edge.

Here’s what can be done

I’ve found a few workarounds to this behaviour. You can drop either of these as MU plugins, add them to your theme functions.php, etc.

Solution 1: Eager Load

If deferred content isn’t a priority for your site, the iframes can be overridden to eager loading.

add_filter(
  'wp_iframe_tag_add_loading_attr',
  function( $loading, $iframe ) {
    // this will never be found at pos 0
    if( strpos( $iframe, 'clip: rect(1px, 1px, 1px, 1px)' ) ) {
      $loading = 'eager';
    }

    return $loading;
  },
  11, 2
);

Solution 2: One Pixel Frame

It is possible to keep the deferred loading behaviour through compromise by making the iframe a pixel instead of totally hidden. This is preferred as you maintain the benefits of lazy-loading, on fast connections the load and swap will happen so quickly that the reader won’t notice, and on slow connections the load and swap doesn’t seem to work well anyway (tested with Chrome DevTool’s simulated connection throttling).

Despite the referenced source above, I observed through testing that 1 pixel dimension was sufficient for an iframe to not be hidden.

add_filter(
  'oembed_dataparse',
  function( $embed ) {
    $embed = str_replace(
      'clip: rect(1px, 1px, 1px, 1px)',
      'clip: rect(0px, 1px, 1px, 0px)',
      $embed
    );

    return $embed;
  },
  11
);

What’s If: Ball, Then: Catch ?

Great question! It’s a children’s literature book that introduces robotics and programming in a way that doesn’t sound scary at all. Find out more with this conveniently placed embedded content below.

Wait, comments are loading...