SponsoredHosinger Special Offer

WP+ WordPress Plugin Development

Build WordPress plugins from scratch: actions and filters, shortcodes, settings pages, custom post types, meta boxes, AJAX, REST endpoints, custom tables, cron and blocks.

Loading Plugin Scripts and Styles

WordPress Plugin Development Lesson 17 of 27 ~4 min read

Overview

Plugins load CSS and JavaScript with wp_enqueue_style() and wp_enqueue_script() on the wp_enqueue_scripts and admin_enqueue_scripts hooks — and a well-built plugin loads them only on the pages that actually use them.

Admin assets on your own screen only

The admin_enqueue_scripts hook passes the current screen's hook suffix. Compare it to the value add_menu_page() returned, and your scripts never touch any other admin page:

<?php
function gdc_books_admin_menu() {
    $hook = add_menu_page( 'GDC Books', 'Books Library', 'manage_options', 'gdc-books', 'gdc_books_render_dashboard', 'dashicons-book-alt' );

    // Load assets only when this exact page loads.
    add_action( 'admin_print_styles-' . $hook, 'gdc_books_admin_assets' );
}
add_action( 'admin_menu', 'gdc_books_admin_menu' );

function gdc_books_admin_assets() {
    wp_enqueue_style( 'gdc-books-admin', GDC_BOOKS_URL . 'assets/css/admin.css', array(), GDC_BOOKS_VERSION );
    wp_enqueue_script( 'gdc-books-admin', GDC_BOOKS_URL . 'assets/js/admin.js', array( 'wp-api-fetch' ), GDC_BOOKS_VERSION, true );
}

For post edit screens, check the screen object instead:

<?php
function gdc_books_editor_assets( $hook_suffix ) {
    $screen = get_current_screen();

    if ( in_array( $hook_suffix, array( 'post.php', 'post-new.php' ), true ) && 'gdc_book' === $screen->post_type ) {
        wp_enqueue_script( 'gdc-books-isbn', GDC_BOOKS_URL . 'assets/js/isbn-check.js', array(), GDC_BOOKS_VERSION, true );
    }
}
add_action( 'admin_enqueue_scripts', 'gdc_books_editor_assets' );
Watch out: Loading your scripts on every admin page is the top cause of plugin conflicts. Your jQuery plugin or your CSS rule for .button can break a completely unrelated screen.

Front-end assets only where needed

<?php
function gdc_books_public_assets() {
    // Register everywhere; enqueue only when used.
    wp_register_style( 'gdc-books', GDC_BOOKS_URL . 'assets/css/books.css', array(), GDC_BOOKS_VERSION );

    if ( is_singular( 'gdc_book' ) || is_post_type_archive( 'gdc_book' ) ) {
        wp_enqueue_style( 'gdc-books' );
    }
}
add_action( 'wp_enqueue_scripts', 'gdc_books_public_assets' );

The shortcode from lesson 8 calls wp_enqueue_style( 'gdc-books' ) itself, so the stylesheet also loads on any page where the shortcode appears — and nowhere else.

Passing data from PHP to JavaScript

<?php
wp_enqueue_script( 'gdc-books-favourites', GDC_BOOKS_URL . 'assets/js/favourites.js', array(), GDC_BOOKS_VERSION, true );

wp_add_inline_script(
    'gdc-books-favourites',
    'window.gdcBooks = ' . wp_json_encode(
        array(
            'ajaxUrl' => admin_url( 'admin-ajax.php' ),
            'nonce'   => wp_create_nonce( 'gdc_books_favourite' ),
            'i18n'    => array(
                'saved'   => __( 'Saved to favourites', 'gdc-books' ),
                'removed' => __( 'Removed from favourites', 'gdc-books' ),
            ),
        )
    ) . ';',
    'before'
);

Your script now reads window.gdcBooks.ajaxUrl and window.gdcBooks.nonce. wp_json_encode() escapes the values safely for use inside a <script> tag. You may also see wp_localize_script() in older plugins; it does the same job but was designed for translations and converts every value to a string.

Practice

  • Load an admin stylesheet only on your Books Library page and confirm in the page source that other admin pages do not include it.
  • Load the front-end stylesheet only on book pages and pages containing [gdc_books].
  • Pass a nonce and a translated string to JavaScript and console.log them.
Create a free account to save which lessons you've finished. Save my progress