This demonstrates how to add JavaScript and CSS files to the functions.php file for a WordPress plugin, theme, or child theme, with a few convenience features added in.

Which Hooks to Use

Use the following hooks to add JavaScript and CSS files to a WordPress plugin, theme, or child theme:

  • wp_enqueue_scripts for front end
  • admin_enqueue_scripts for back end (admin interface)

Convenience Features Added

Detect Plugin vs. Theme vs. Child theme:
The example below detects whether the code was dropped into a plugin, theme, or child theme, and uses the appropriate function to get the path and URL to the directory.

Cache-Busting:
The example below includes a trick to prevent browsers from ignoring new versions of the CSS and JS files by automatically setting the file version number based on the last modified time. No need to update the version number manually or force-refresh the browser to get the latest changes.

Passing Variables to JS:
The example below also implements wp_localize_script(), which is a handy way to pass variables from the PHP back-end and ensure they're available on the page before the associated script is loaded.

Updated 2025 Version with Automatic Plugin/Theme Directory Detection

<?php
// ********** Sample plugin metadata. Omit most of it for a theme or child theme. **********
/**
 * Plugin Name: My Test Plugin
 * Plugin URI: http://benjaminray.com/codebase
 * Description: A test plugin to demonstrate adding css & js files correctly, with optional cache-busting
 * Version: 1.1
 * Author: Benjamin Ray
 * Author URI: http://benjaminray.com/codebase
 */

/**
 * Enqueue Scripts & Styles for the front end. Use file modified timestamp as version for cache-busting.
 * Loads files in directory of theme, child theme, or plugin:
 *      /css/style.css
 *      /css/script.js
 */
add_action( 'wp_enqueue_scripts', 'mypluginortheme_add_assets_frontend' );
function mypluginortheme_add_assets_frontend() {

    // Detect whether we're in a theme, child theme, or plugin, and use the correct function to get the directory
    if ( defined( 'ABSPATH' ) && strpos( __FILE__, get_stylesheet_directory() ) !== false ) {
        // Inside a child theme (this check must be first)
        $base_dir = get_stylesheet_directory();
        $base_url = get_stylesheet_directory_uri();
    } elseif ( defined( 'ABSPATH' ) && strpos( __FILE__, get_template_directory() ) !== false ) {
        // Inside a theme
        $base_dir = get_template_directory();
        $base_url = get_template_directory_uri();
    } else {
        // Assume inside a plugin
        $base_dir = plugin_dir_path( __FILE__ );
        $base_url = plugin_dir_url( __FILE__ );
    }

    // Ensure no trailing slash (usually added by plugin_dir_url but not get_*_directory_uri)
    $base_url = untrailingslashit( $base_url );
    
    // CSS
    $css_file = $base_dir . '/css/style.css';
    $css_ver  = file_exists( $css_file ) ? filemtime( $css_file ) : false;
    wp_enqueue_style( 'mypluginortheme', $base_url . '/css/style.css', array(), $css_ver, 'all' );

    // JS
    $js_file = $base_dir . '/js/script.js';
    $js_ver  = file_exists( $js_file ) ? filemtime( $js_file ) : false;
    wp_enqueue_script( 'mypluginortheme', $base_url . '/js/script.js', array( 'jquery' ), $js_ver, true );

    // Pass variables to JS. Access through "myPluginOrThemeVars", e.g.: `myPluginOrThemeVars.pluginUrl`
    wp_localize_script(
        'mypluginortheme', // Must match handle of enqueued JS script
        'myPluginOrThemeVars',
        array(
            'url'             => $base_url, // Often handy for plugins
            'someOtherString' => 'Some other string value'
        )
    );
}


/**
 * Enqueue Scripts & Styles for the admin interface. Use file modified timestamp as version for cache-busting.
 * Loads files in directory of theme, child theme, or plugin:
 *      /css/style-admin.css
 *      /css/script-admin.js
 */
add_action( 'admin_enqueue_scripts', 'mypluginortheme_add_assets_admin' );
function mypluginortheme_add_assets_admin() {

    // Detect whether we're in a theme, child theme, or plugin, and use the correct function to get the directory
    if ( defined( 'ABSPATH' ) && strpos( __FILE__, get_stylesheet_directory() ) !== false ) {
        // Inside a child theme (this check must be first)
        $base_dir = get_stylesheet_directory();
        $base_url = get_stylesheet_directory_uri();
    } elseif ( defined( 'ABSPATH' ) && strpos( __FILE__, get_template_directory() ) !== false ) {
        // Inside a theme
        $base_dir = get_template_directory();
        $base_url = get_template_directory_uri();
    } else {
        // Assume inside a plugin
        $base_dir = plugin_dir_path( __FILE__ );
        $base_url = plugin_dir_url( __FILE__ );
    }
    
    // Ensure no trailing slash (usually added by plugin_dir_url but not get_*_directory_uri)
    $base_url = untrailingslashit( $base_url );

    // CSS
    $css_file = $base_dir . '/css/style-admin.css';
    $css_ver  = file_exists( $css_file ) ? filemtime( $css_file ) : false;
    wp_enqueue_style( 'mypluginortheme-admin', $base_url . '/css/style-admin.css', array(), $css_ver );

    // JS
    $js_file = $base_dir . '/js/script-admin.js';
    $js_ver  = file_exists( $js_file ) ? filemtime( $js_file ) : false;
    wp_enqueue_script( 'mypluginortheme-admin', $base_url . '/js/script-admin.js', array( 'jquery' ), $js_ver, true );

    // Pass variables to JS. Access through "myPluginOrThemeAdminVars", e.g.: `myPluginOrThemeAdminVars.pluginUrl`
    wp_localize_script(
        'mypluginortheme-admin', // Must match handle of enqueued JS script
        'myPluginOrThemeAdminVars', 
        array(
            'url'             => $base_url, // Often handy for plugins
            'someOtherString' => 'Some other string value'
        )
    );
}

Original Version for Plugins Only

<?php
/**
 * Plugin Name: My Test Plugin
 * Plugin URI: http://benjaminray.com/codebase
 * Description: A test plugin to demonstrate adding css & js files correctly, with optional cache-busting
 * Version: 1.0
 * Author: Benjamin Ray
 * Author URI: http://benjaminray.com/codebase
 */

/**
 * Enqueue Scripts & Styles for the front end
 */
add_action( 'wp_enqueue_scripts', 'add_assets_client' );
function add_assets_client() {

    // Use cache-busting trick to append version numbers based on file modified time so latest version always loads

    // CSS
    $css_ver  = date("Ymd-Gis", filemtime( plugin_dir_path( __FILE__ ) . 'css/style.css' ));
    wp_enqueue_style( 'myplugin-css', plugins_url( '/css/style.css', __FILE__ ), array(), $css_ver);

    // JS (final parameter loads script in footer - recommended)
    $js_ver  = date("Ymd-Gis", filemtime( plugin_dir_path( __FILE__ ) . 'js/script.js' ));
    wp_enqueue_script( 'myplugin-js', plugins_url( '/js/script.js', __FILE__ ), array( 'jquery' ), $js_ver, true);

    // Pass variables from PHP to JS. Access them through "myPluginVars", e.g.: `myPluginVars.pluginUrl`
    wp_localize_script('myplugin-js', 'myPluginVars', array(
        'pluginUrl' => plugin_dir_url(__FILE__),
        'someOtherString' => 'Some other string value'
    ));

}

/**
 * Enqueue Scripts & Styles for the back end
 */
add_action( 'admin_enqueue_scripts', 'add_assets_admin' );
function add_assets_admin() {
    // Use cache-busting trick to append version numbers based on file modified time so latest version always loads

    // CSS
    $css_ver  = date("Ymd-Gis", filemtime( plugin_dir_path( __FILE__ ) . 'css/style-admin.css' ));
    wp_enqueue_style( 'myplugin-css-admin', plugins_url( '/css/style-admin.css', __FILE__ ), array(), $css_ver);

    // JS (final parameter loads script in footer - recommended)
    $js_ver  = date("Ymd-Gis", filemtime( plugin_dir_path( __FILE__ ) . 'js/script-admin.js' ));
    wp_enqueue_script( 'myplugin-js-admin', plugins_url( '/js/script-admin.js', __FILE__ ), array( 'jquery' ), $js_ver, true);

    // Pass variables from PHP to JS. Access them through "myPluginAdminVars", e.g.: `myPluginAdminVars.pluginUrl`
    wp_localize_script('myplugin-js-admin', 'myPluginAdminVars', array(
        'pluginUrl' => plugin_dir_url(__FILE__),
        'someOtherString' => 'Some other string value'
    ));

}
Published On: November 9, 2019Categories: WordPressTags: ,