HomeMethod

Knowledge

Web VitalsTechniquesSnippetsAnswersImpactsBottlenecks

Defer non-critical CSS loading

  • Performance

External stylesheets are render-blocking by default — the browser won’t paint anything until every CSS file in the <head> is downloaded and parsed. For stylesheets that only affect below-the-fold content, this is wasted time.

defer-css.php
<?php
/**
 * Defer Non-Critical CSS Loading
 *
 * Converts stylesheet link tags to load asynchronously using the
 * media="print" swap trick. The browser downloads the CSS without
 * blocking rendering, then applies it once loaded. Exclude critical
 * stylesheets (like your above-the-fold CSS) by adding their handles
 * to the $exclude array.
 *
 * Usage: Add to functions.php. Add critical stylesheet handles to $exclude.
 *
 * @category performance
 * @language php

 *
 * @author Adame Dahmani https://adame.io
 * @support Support my family project: https://adame.io/fundraiser
 */
add_filter( 'style_loader_tag', function ( $tag, $handle, $src ) {
    if ( is_admin() ) {
        return $tag;
    }

    $exclude = [ 'critical-css', 'wp-block-library' ];

    if ( in_array( $handle, $exclude, true ) ) {
        return $tag;
    }

    return sprintf(
        '<link rel="stylesheet" href="%s" media="print" onload="this.media=\'all\'" /><noscript>%s</noscript>',
        esc_url( $src ),
        $tag
    );
}, 10, 3 );

The media="print" trick works because the browser still downloads print stylesheets but doesn’t block rendering for them. The onload handler switches the media to all once downloaded, applying the styles. Add critical stylesheet handles to the $exclude array to keep them render-blocking.

Support our family now