Natively lazy-loading Facebook social plugins

July 24th, 2020. Tagged: facebook, JavaScript


tl;dr: Add data-lazy="true" to your Facebook social plugins that are below the fold and reap the benefits.

In code:

// before
<div 
  class="fb-like" 
  data-href="https://phpied.com"></div>
// after
<div 
  class="fb-like" 
  data-href="https://phpied.com" 
  data-lazy="true"></div>

The following 18 seconds video demonstrates the difference. Where currently your visitors load Facebook iframe content even if it's way down the page, after you implement lazy-loading, they'll only load the iframes if there's a chance of ever seeing them. Look for the like.php request and its dependencies.

How these plugins work?

Facebook's social plugins are pieces of Facebook content you can embed into your pages. Like buttons, share buttons, comments, embedded videos, posts and photos and so on.

The plugins are iframes that point to e.g. facebook.com/plugins/like.php, facebook.com/plugins/comments.php and so on. Some plugins allow you to create the iframes youself, where others do not. And in general it's better not to. Why? Because content can vary based on language and other factors and by creating the iframe yourself you risk the content being cut off.

So who writes the iframes then? The FB JSSDK. You load the SDK (asynchronously, of course) and sprinkle divs where you want the plugins to appear. The SDK writes and resizes the iframes as required.

What's new?

Browsers now support native lazy-loading of iframes.

Facebook now supports native lazy-loading of all social plugins.

All you have to do is add the data-lazy="true" attribute to your plugin div elements.

Why only below the fold

Quick answer: otherwise your visitors may see some content shift.

Long answer: in order to resize the plugins in the best possible way, based on content, the FB JSSDK initially creates the plugin with visibility: hidden and with a size of 1000x1000 pixels. The iframe itself is inside a 0x0 container. After the iframe loads, it informs the SDK of its size and the SDK resizes the iframe and makes it visible.

In this case visibility: hidden prevents native lazy-loading in Chrome. Reason: analytics should not lazy-load even when the developer sets iframe loading="lazy". This is a questionable decision, but that's how it works for now.

So to support native lazy-loading as currently implemented, the FB JSSDK creates a visible iframe inside a 1x1 container (turns out 0x0 container also kills native lazy-loading in Chrome). So if the content is above the fold a 1000x1000 iframe inside 1x1 container may cause some visible content shift or overlap other content even if not visible outside 1x1.

If your plugin is only visible below the fold (most often), Chrome's aggressive (or "safe" is the right word?) loading gives plenty of time for the loading and resizing to take place.

Why am I reading this on a random blog?

This should be on developers.facebook.com, no? Right. However two weeks ago was my last day at Facebook. The Sunday prior my last Monday I debugged with the help of Chrome folks Addy and Dominic and managed to send the diff on Sunday, get it approved Monday, land (thanks Brad!) and barely had time to update the docs. No time for official announcement.

Make the web faster

Your turn! Go to your plugin implementations and add data-lazy="true" for all plugins below the fold. Comments, embeds, like/share buttons at the end of an article and so on.

Your users will love you for it! Battery lives and data allowances will be saved. The web will be less congested.

Tell your friends about this post on Facebook and Twitter

Sorry, comments disabled and hidden due to excessive spam.

Meanwhile, hit me up on twitter @stoyanstefanov