Wordpress - How to add stylesheets only to pages with specific shortcode?

Loading Scripts and Styles Dynamically Using Shortcode

Advantages

  • Does not search through all the posts every time the shortcode is called.
  • Able to add styles as well as scripts dynamically only when shortcode is on the page.
  • Does not use regexes since they tend to be slower than strstr() or strpos(). You could switch to regex if you need to accept args.
  • Reduces file calls

Explanation of Code

  1. Finds the shortcodes on page using the save_post hook only when the post is not a revision and matches the specified post_type.

  2. Saves the found post ids as an array using add_option() with autoload set to yes unless the entry is already present. Then it will use update_option().

  3. Uses hook wp_enqueue_scripts to call our add_scripts_and_styles() function.

  4. That function then calls get_option() to retrieve our array of page ids. If the current $page_id is in the $option_id_array then it adds the scripts and styles.

Please note: I converted the code from OOP Namespaced classes so I may have missed something. Let me know in the comments if I did.

Code Example: Finding Shortcode Occurences

function find_shortcode_occurences($shortcode, $post_type = 'page')
{
    $found_ids = array();
    $args         = array(
        'post_type'   => $post_type,
        'post_status' => 'publish',
        'posts_per_page' => -1,
    );
    $query_result = new \WP_Query($args);
    foreach ($query_result->posts as $post) {
        if (false !== strpos($post->post_content, $shortcode)) {
            $found_ids[] = $post->ID;
        }
    }
    return $found_ids;
}

function save_option_shortcode_post_id_array( $post_id ) {
    if ( wp_is_post_revision( $post_id ) OR 'page' != get_post_type( $post_id )) {
        return;
    }
    $option_name = 'yourprefix-yourshortcode';
    $id_array = find_shortcode_occurences($option_name);
    $autoload = 'yes';
    if (false == add_option($option_name, $id_array, '', 'yes')) update_option($option_name, $id_array);
}

add_action('save_post', 'save_option_shortcode_id_array' );

Code Example: Shortcode Dynamically Include Scripts and Styles

function yourshortcode_add_scripts_and_styles() {
    $page_id = get_the_ID();
    $option_id_array = get_option('yourprefix-yourshortcode');
    if (in_array($page_id, $option_id_array)) {
        wp_enqueue_script( $handle, $src, $deps, $ver, $footer = true );
        wp_enqueue_style( $handle, $src , $deps);
    }
}

add_action('wp_enqueue_scripts', 'yourshortcode_add_scripts_and_styles');

This works for me:

function register_my_css () {
    wp_register_style('my-style', plugins_url('styles.css', __FILE__));
}

function register_my_scripts () {
    wp_register_script('my-script', plugins_url('scripts.js', __FILE__));
}

// only enqueue the scripts / styles when the short code is called
function do_my_shortcode () {
    wp_enqueue_style('my-style');
    wp_enqueue_script('my-script');

    // do short code stuff...
}

// register css
add_action('wp_enqueue_scripts', 'register_my_css');

// register javascript
add_action('wp_enqueue_scripts', 'register_my_scripts');

// register shortcode
add_shortcode('my-shortcode', 'do_my_shortcode');

More info here: http://mikejolley.com/2013/12/sensible-script-enqueuing-shortcodes/