This site is getting rebuilt from scratch. Watch this space.

How to conditionally enqueue WordPress scripts and styles

Serve only the assets you need on each page, slash load times, and boost core web vitals with a compact conditional-enqueue pattern any theme can adopt.

Why conditional enqueuing matters

Each extra script or style sheet is another HTTP request, more bytes over the wire, and a longer main-thread execution time. Core Web Vitals – especially Largest Contentful Paint (LCP) and Interaction to Next Paint (INP) penalize unnecessary assets. By enqueueing files only when a post explicitly requests them, you deliver leaner markup and better metrics without resorting to heavy optimizers or critical-CSS plugins.

  1. Install MetaBox Lite or a similar plugin which enables custom fields
  2. Create a switch field for each feature, for example:
    • Switch 1 – Label: Enable Code Box → Field ID: advance_codebox
    • Switch 2 – Label: Enable read progress bar → Field ID: progress_bar
  3. Assign the field group to Posts (or any CPT).
  4. Check a toggle → corresponding script loads; leave unchecked → script never touches the DOM.

Pro-tip: Most field plugins (ACF, CMB2, Carbon Fields) expose a similar boolean control.

Example of my setup here:

The code snippet

Here is an extract of the functions.php in my child theme:

<?php
if ( ! defined( 'ABSPATH' ) ) exit;

/* Helper */
function conditional_enqueue( $field, $type, $handle, $path ) {
    $active = get_post_meta( get_the_ID(), $field, true );
    if ( $active == 1 || $active === true ) {
        $uri  = get_stylesheet_directory_uri() . $path;
        $ver  = filemtime( get_stylesheet_directory() . $path );
        $type === 'script'
            ? wp_enqueue_script( $handle, $uri, [], $ver, true )
            : wp_enqueue_style ( $handle, $uri, [], $ver       );
    }
}

/* Master hook */
add_action( 'wp_enqueue_scripts', function () {

    /* Conditional modules */
    conditional_enqueue( 'advance_codebox',   'script', 'prism',        '/includes/vendor/prism.js' );
    conditional_enqueue( 'force_darkmode',    'script', 'darkmode',     '/assets/js/darkmode.js'   );
    conditional_enqueue( 'table_of_contents', 'script', 'toc',          '/assets/js/toc.js'        );
    conditional_enqueue( 'read_progress_bar', 'script', 'progress-bar', '/assets/js/progress-bar.js');
    conditional_enqueue( 'social_share',      'script', 'social-share', '/assets/js/social-share.js');

}, 15 );
BlockPurposePayoff
conditional_enqueue()Reusable helper; asks “Is this toggle on?” then enqueues assetOne liner per module, no repeated logic
filemtime()Grabs file’s last-modified timestamp for the ver argBusts cache only when the file actually changes
Reusable path patternget_stylesheet_directory_uri() + relative pathKeeps child themes modular
Back to blog