Make WordPress Core

05/13/2024 10:37:38 PM (5 weeks ago)

Embeds: Enable lazy-loading of post embeds and fix keyboard a11y for hidden iframes.

Chrome unreliably loads a lazy-loaded iframe when it is hidden using clip: rect(1px, 1px, 1px, 1px). Instead of using clip, a lazy-loaded iframe can also be hidden with visibility:hidden which results in it loading not only in Chrome but all other browsers. With this change applied, the hard-coded check to prevent lazy-loading post embeds is now removed. An added benefit to using visibility:hidden is that the entire iframe in this case is not interactable, meaning that users navigating the document with the keyboard will not unexpectedly encounter tab stops inside of the hidden iframe, as can happen now with clip when the JS fails to reveal the loaded iframe. Note also that the clip property is deprecated.

Lastly, when such a post embed iframe is rendered in an RSS feed, the style attribute is now removed using the HTML Tag Processor as opposed to using string replacement.

Fixes #58773.
Props westonruter, joemcgill, swissspidy, joedolson, adamsilverstein.

1 edited


  • trunk/src/wp-includes/embed.php

    r58097 r58143  
    967967    if ( ! empty( $content[1] ) ) {
    968968        // We have a blockquote to fall back on. Hide the iframe by default.
    969         $html = str_replace( '<iframe', '<iframe style="position: absolute; clip: rect(1px, 1px, 1px, 1px);"', $html );
     969        $html = str_replace( '<iframe', '<iframe style="position: absolute; visibility: hidden;"', $html );
    970970        $html = str_replace( '<blockquote', '<blockquote class="wp-embedded-content"', $html );
    971971    }
    11001100 */
    11011101function _oembed_filter_feed_content( $content ) {
    1102     return str_replace( '<iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted" style="position: absolute; clip: rect(1px, 1px, 1px, 1px);"', '<iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted"', $content );
     1102    $p = new WP_HTML_Tag_Processor( $content );
     1103    while ( $p->next_tag( array( 'tag_name' => 'iframe' ) ) ) {
     1104        if ( $p->has_class( 'wp-embedded-content' ) ) {
     1105            $p->remove_attribute( 'style' );
     1106        }
     1107    }
     1108    return $p->get_updated_html();
Note: See TracChangeset for help on using the changeset viewer.