Wordpress Page Specific Styles or Scripts

I wanted an efficient way to load page or post specific stylesheets and or scripts which lead me to see if I could utilize custom fields for this. Using custom fields combined with wp_enqueue_style and wp_enqueue_script worked perfectly. This solution allows me to link css or javascript files for only the posts or pages I want.

1. Add a couple of custom fields, one for styles and one for scripts to a page using the editor:

Add bn_styles custom field
Wordpress editor - Add bn_styles custom field

bn_styles and bn_scripts custom fields added
Wordpress editor - bn_styles and bn_scripts custom fields added

Loading WordPress theme stylesheets and scripts is typically done within the functions.php file using wp_enqueue_style and wp_enqueue_script respectively. Using the Twenty Fifteen functions.php file as an example, take a look at the twentyfifteen_scripts function:

function twentyfifteen_scripts() {
    // Add custom fonts, used in the main stylesheet.
    wp_enqueue_style( 'twentyfifteen-fonts', twentyfifteen_fonts_url(), array(), null );

    // Add Genericons, used in the main stylesheet.
    wp_enqueue_style( 'genericons', get_template_directory_uri() . '/genericons/genericons.css', array(), '3.2' );

    // Load our main stylesheet.
    wp_enqueue_style( 'twentyfifteen-style', get_stylesheet_uri() );

    // Load the Internet Explorer specific stylesheet.
    wp_enqueue_style( 'twentyfifteen-ie', get_template_directory_uri() . '/css/ie.css', array( 'twentyfifteen-style' ), '20141010' );
    wp_style_add_data( 'twentyfifteen-ie', 'conditional', 'lt IE 9' );

    // Load the Internet Explorer 7 specific stylesheet.
    wp_enqueue_style( 'twentyfifteen-ie7', get_template_directory_uri() . '/css/ie7.css', array( 'twentyfifteen-style' ), '20141010' );
    wp_style_add_data( 'twentyfifteen-ie7', 'conditional', 'lt IE 8' );

    wp_enqueue_script( 'twentyfifteen-skip-link-focus-fix', get_template_directory_uri() . '/js/skip-link-focus-fix.js', array(), '20141010', true );

    if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
        wp_enqueue_script( 'comment-reply' );
    }

    if ( is_singular() && wp_attachment_is_image() ) {
        wp_enqueue_script( 'twentyfifteen-keyboard-image-navigation', get_template_directory_uri() . '/js/keyboard-image-navigation.js', array( 'jquery' ), '20141010' );
    }

    wp_enqueue_script( 'twentyfifteen-script', get_template_directory_uri() . '/js/functions.js', array( 'jquery' ), '20150330', true );
    //wp_enqueue_script( 'twentyfifteen-script', get_template_directory_uri() . '/js/main.js', array( 'jquery' ), '20150527', true );
    wp_localize_script( 'twentyfifteen-script', 'screenReaderText', array(
        'expand'   => '' . __( 'expand child menu', 'twentyfifteen' ) . '',
        'collapse' => '' . __( 'collapse child menu', 'twentyfifteen' ) . '',
    ) );
}
add_action( 'wp_enqueue_scripts', 'twentyfifteen_scripts' );

Edit functions.php

Add some code to the twentyfifteen_scripts function to get the custom field data and use it to load stylesheets and scripts.

2. At the top of the twentyfifteen_scripts function, add the get_post_custom function to retrieve the custom field data:

function twentyfifteen_scripts() {

    // retrieve custom fields from the current post
    $custom_fields = get_post_custom();

3. After the last stylesheet is queued for loading, add the code that checks for and loads our styles custom_field stylesheets. In this example, add the code after wp_style_add_data( 'twentyfifteen-ie7', 'conditional', 'lt IE 8' ); as shown here:

    wp_style_add_data( 'twentyfifteen-ie7', 'conditional', 'lt IE 8' );

    // styles custom_field
    if (!empty($custom_fields['bn_styles'])) {
        foreach ( $custom_fields['bn_styles'] as $key => $value ) {
            wp_enqueue_style('twentyfifteen_custom_field_' . $key, get_template_directory_uri() . '/css/' . $value, false, null);
        }
    }

4. At the end of the twentyfifteen_scripts function, add the code that checks for and loads our scripts custom_field javascript as shown here:

    // scripts custom_field
    if (!empty($custom_fields['bn_scripts'])) {
        foreach ( $custom_fields['bn_scripts'] as $key => $value ) {
            wp_enqueue_script('twentyfifteen_custom_field_' . $key, get_template_directory_uri() . '/js/' . $value, [], null, true);
        }
    }
}
add_action( 'wp_enqueue_scripts', 'twentyfifteen_scripts' );

5. Here is the entire twentyfifteen_scripts function after the modifications above:

function twentyfifteen_scripts() {

    // retrieve custom fields from the current post
    $custom_fields = get_post_custom();

    // Add custom fonts, used in the main stylesheet.
    wp_enqueue_style( 'twentyfifteen-fonts', twentyfifteen_fonts_url(), array(), null );

    // Add Genericons, used in the main stylesheet.
    wp_enqueue_style( 'genericons', get_template_directory_uri() . '/genericons/genericons.css', array(), '3.2' );

    // Load our main stylesheet.
    wp_enqueue_style( 'twentyfifteen-style', get_stylesheet_uri() );

    // Load the Internet Explorer specific stylesheet.
    wp_enqueue_style( 'twentyfifteen-ie', get_template_directory_uri() . '/css/ie.css', array( 'twentyfifteen-style' ), '20141010' );
    wp_style_add_data( 'twentyfifteen-ie', 'conditional', 'lt IE 9' );

    // Load the Internet Explorer 7 specific stylesheet.
    wp_enqueue_style( 'twentyfifteen-ie7', get_template_directory_uri() . '/css/ie7.css', array( 'twentyfifteen-style' ), '20141010' );
    wp_style_add_data( 'twentyfifteen-ie7', 'conditional', 'lt IE 8' );

    // styles custom_field
    if (!empty($custom_fields['bn_styles'])) {
        foreach ( $custom_fields['bn_styles'] as $key => $value ) {
            wp_enqueue_style('twentyfifteen_custom_field_' . $key, get_template_directory_uri() . '/css/' . $value, false, null);
        }
    }

    wp_enqueue_script( 'twentyfifteen-skip-link-focus-fix', get_template_directory_uri() . '/js/skip-link-focus-fix.js', array(), '20141010', true );

    if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
        wp_enqueue_script( 'comment-reply' );
    }

    if ( is_singular() && wp_attachment_is_image() ) {
        wp_enqueue_script( 'twentyfifteen-keyboard-image-navigation', get_template_directory_uri() . '/js/keyboard-image-navigation.js', array( 'jquery' ), '20141010' );
    }

    wp_enqueue_script( 'twentyfifteen-script', get_template_directory_uri() . '/js/functions.js', array( 'jquery' ), '20150330', true );
    //wp_enqueue_script( 'twentyfifteen-script', get_template_directory_uri() . '/js/main.js', array( 'jquery' ), '20150527', true );
    wp_localize_script( 'twentyfifteen-script', 'screenReaderText', array(
        'expand'   => '' . __( 'expand child menu', 'twentyfifteen' ) . '',
        'collapse' => '' . __( 'collapse child menu', 'twentyfifteen' ) . '',
    ) );

    // scripts custom_field
    if (!empty($custom_fields['bn_scripts'])) {
        foreach ( $custom_fields['bn_scripts'] as $key => $value ) {
            wp_enqueue_script('twentyfifteen_custom_field_' . $key, get_template_directory_uri() . '/js/' . $value, [], null, true);
        }
    }
}
add_action( 'wp_enqueue_scripts', 'twentyfifteen_scripts' );

Handle Script Dependencies

A nice feature of the wp_enqueue_script function is that it allows us to pass in dependencies as a parameter. The optional dependencies parameter consists of an array of handles that map to javascript files. To apply this feature to our scripts custom field code, we need to create a $deps array that will retrieve optional handles added to the custom field value. Replace the code block at the bottom of function twentyfifteen_scripts() as follows:

REPLACE
// scripts custom_field
if (!empty($custom_fields['bn_scripts'])) {
    foreach ( $custom_fields['bn_scripts'] as $key => $value ) {
        wp_enqueue_script('twentyfifteen_custom_field_' . $key, get_template_directory_uri() . '/js/' . $value, [], null, true);
    }
}
WITH
// scripts custom_field
if (!empty($custom_fields['bn_scripts'])) {
    foreach ( $custom_fields['bn_scripts'] as $key => $value ) {
        $script = explode(',', $value);
        $deps = array();
        foreach ( $script as $i => $v ) {
            if ($i > 0) { // values after $script[0]
                $deps[] = trim($v);
            }
        }
        wp_enqueue_script('twentyfifteen_custom_field_' . $key, get_template_directory_uri() . '/js/' . $value, $deps, null, true);
    }
}

For a detailed list of handle names that can be used, see Handles and Their Script Paths Registered by WordPress.

6. Here is the entire twentyfifteen_scripts function after updating the scripts custom field parser to handle script dependencies:

function twentyfifteen_scripts() {

    // retrieve custom fields from the current post
    $custom_fields = get_post_custom();

    // Add custom fonts, used in the main stylesheet.
    wp_enqueue_style( 'twentyfifteen-fonts', twentyfifteen_fonts_url(), array(), null );

    // Add Genericons, used in the main stylesheet.
    wp_enqueue_style( 'genericons', get_template_directory_uri() . '/genericons/genericons.css', array(), '3.2' );

    // Load our main stylesheet.
    wp_enqueue_style( 'twentyfifteen-style', get_stylesheet_uri() );

    // Load the Internet Explorer specific stylesheet.
    wp_enqueue_style( 'twentyfifteen-ie', get_template_directory_uri() . '/css/ie.css', array( 'twentyfifteen-style' ), '20141010' );
    wp_style_add_data( 'twentyfifteen-ie', 'conditional', 'lt IE 9' );

    // Load the Internet Explorer 7 specific stylesheet.
    wp_enqueue_style( 'twentyfifteen-ie7', get_template_directory_uri() . '/css/ie7.css', array( 'twentyfifteen-style' ), '20141010' );
    wp_style_add_data( 'twentyfifteen-ie7', 'conditional', 'lt IE 8' );

    // styles custom_field
    if (!empty($custom_fields['bn_styles'])) {
        foreach ( $custom_fields['bn_styles'] as $key => $value ) {
            wp_enqueue_style('twentyfifteen_custom_field_' . $key, get_template_directory_uri() . '/css/' . $value, false, null);
        }
    }

    wp_enqueue_script( 'twentyfifteen-skip-link-focus-fix', get_template_directory_uri() . '/js/skip-link-focus-fix.js', array(), '20141010', true );

    if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
        wp_enqueue_script( 'comment-reply' );
    }

    if ( is_singular() && wp_attachment_is_image() ) {
        wp_enqueue_script( 'twentyfifteen-keyboard-image-navigation', get_template_directory_uri() . '/js/keyboard-image-navigation.js', array( 'jquery' ), '20141010' );
    }

    wp_enqueue_script( 'twentyfifteen-script', get_template_directory_uri() . '/js/functions.js', array( 'jquery' ), '20150330', true );
    //wp_enqueue_script( 'twentyfifteen-script', get_template_directory_uri() . '/js/main.js', array( 'jquery' ), '20150527', true );
    wp_localize_script( 'twentyfifteen-script', 'screenReaderText', array(
        'expand'   => '' . __( 'expand child menu', 'twentyfifteen' ) . '',
        'collapse' => '' . __( 'collapse child menu', 'twentyfifteen' ) . '',
    ) );

    // scripts custom_field
    if (!empty($custom_fields['bn_scripts'])) {
        foreach ( $custom_fields['bn_scripts'] as $key => $value ) {
            $script = explode(',', $value);
            $deps = array();
            foreach ( $script as $i => $v ) {
                if ($i > 0) { // values after $script[0]
                    $deps[] = trim($v);
                }
            }
            wp_enqueue_script('twentyfifteen_custom_field_' . $key, get_template_directory_uri() . '/js/' . $value, $deps, null, true);
        }
    }
}
add_action( 'wp_enqueue_scripts', 'twentyfifteen_scripts' );
Source Code

7. Now the bn_scripts custom field can be updated to include dependencies. List the dependency handles after the script separated by a comma as shown below.

bn_styles and bn_scripts custom fields added
Wordpress editor - bn_scripts custom field dependencies added

More often than not jQuery will already be loaded. However, if your script is dependent upon jQuery you should add its handle to the dependencies comma separated list in the bn_scripts custom field value. wp_enqueue_script prevents double loading of scripts and their dependencies.

Given the default theme location, if you view source of the page that has the custom fields added and search for tree.css or tree.js, they should be linked to /wp-content/themes/twentyfifteen/css/tree.css and /wp-content/themes/twentyfifteen/js/tree.js. Any dependencies will also be linked.


Bourboneat version

If you would like to explore using this code with the bourboneat Wordpress starter theme, here is the modified /functions/asset.php assets function that is used to enqueue stylesheets and scripts:

function assets() {
    wp_enqueue_style('bn_css', asset_path('styles/main.css'), false, null);

    $custom_fields = get_post_custom();

    // styles custom_field
    if (!empty($custom_fields['bn_styles'])) {
        foreach ( $custom_fields['bn_styles'] as $key => $value ) {
            wp_enqueue_style('bn_custom_field_' . $key, asset_path('styles/' . $value), false, null);
        }
    }

    if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
        wp_enqueue_script( 'comment-reply' );
    }

    //wp_enqueue_script('modernizr', asset_path('scripts/modernizr.js'), [], null, true);
    wp_enqueue_script('bn_js', asset_path('scripts/main.js'), ['jquery'], null, true);

    // scripts custom_field
    if (!empty($custom_fields['bn_scripts'])) {
        foreach ( $custom_fields['bn_scripts'] as $key => $value ) {
            $script = explode(',', $value);
            $deps = array();
            foreach ( $script as $i => $v ) {
                if ($i > 0) { // values after $script[0]
                    $deps[] = trim($v);
                }
            }
            wp_enqueue_script('bn_custom_field_' . $key, asset_path('scripts/' . $script[0] ), $deps, null, true);
        }
    }
}
comments powered by Disqus