What is the idea way to register/enqueue scripts and/or styles for use in plugins?
I recently made a plugin simple plugin to add the user avatar/gravatar with a shortcode. I have different style options for displaying the avatar (square, round, etc.) and decided to put the css directly in the shortcode itself.
However, I realize now this isn’t a good approach since it will repeat the css every time the shortcode is used on a page. I’ve seen several other approaches on this site and the wp codex even has two examples of their own so it’s hard to know what approach is most consistent and fastest.
Here are the methods I currently am aware of:
Method 1: Include directly in shortcode –
This is what I’m currently doing in the plugin, but doesn’t seem good since it repeats code.
class My_Shortcode {
function handle_shortcode( $atts, $content="" ) {
/* simply enqueue or print the scripts/styles in the shortcode itself */
?>
<style type="text/css">
</style>
<?php
return "$content";
}
}
add_shortcode( 'myshortcode', array( 'My_Shortcode', 'handle_shortcode' ) );
Method 2: Use class for enqueueing scripts or styles conditionally
class My_Shortcode {
static $add_script;
static function init() {
add_shortcode('myshortcode', array(__CLASS__, 'handle_shortcode'));
add_action('init', array(__CLASS__, 'register_script'));
add_action('wp_footer', array(__CLASS__, 'print_script'));
}
static function handle_shortcode($atts) {
self::$add_script = true;
// shortcode handling here
}
static function register_script() {
wp_register_script('my-script', plugins_url('my-script.js', __FILE__), array('jquery'), '1.0', true);
}
static function print_script() {
if ( ! self::$add_script )
return;
wp_print_scripts('my-script');
}
}
My_Shortcode::init();
Method 3: Using get_shortcode_regex();
function your_prefix_detect_shortcode() {
global $wp_query;
$posts = $wp_query->posts;
$pattern = get_shortcode_regex();
foreach ($posts as $post){
if ( preg_match_all( "https://wordpress.stackexchange.com/". $pattern .'/s', $post->post_content, $matches )
&& array_key_exists( 2, $matches )
&& in_array( 'myshortcode', $matches[2] ) )
{
// css/js
break;
}
}
}
add_action( 'wp', 'your_prefix_detect_shortcode' );
Method 4: Using has_shortcode();
function custom_shortcode_scripts() {
global $post;
if( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'myshortcode') ) {
wp_enqueue_script( 'my-script');
}
}
add_action( 'wp_enqueue_scripts', 'custom_shortcode_scripts');
I found an other way that works well for me:
-
When initializing the plugin, do not enqueue your scripts and styles, but register them with
wp_register_style
andwp_register_script
. -
Next you can load the script/style on demand. For example when you render a shortcode with
wp_enqueue_style("your_style")
andwp_enqueue_script("your_script")
.
Here is an example plugin using this method that lets you use get_avatar in a shortcode. The stylesheet is only enqueued when the shortcode is present.
Usage (id defaults to current user):
[get_avatar id="" size="32" default="mystery" alt="Profile Photo" class="round"]
function wpse_165754_avatar_shortcode_wp_enqueue_scripts() {
wp_register_style( 'get-avatar-style', plugins_url( '/css/style.css', __FILE__ ), array(), '1.0.0', 'all' );
}
add_action( 'wp_enqueue_scripts', 'wpse_165754_avatar_shortcode_wp_enqueue_scripts' );
if ( function_exists( 'get_avatar' ) ) {
function wpse_165754_user_avatar_shortcode( $attributes ) {
global $current_user;
get_currentuserinfo();
extract( shortcode_atts(
array(
"id" => $current_user->ID,
"size" => 32,
"default" => 'mystery',
"alt" => '',
"class" => '',
), $attributes, 'get_avatar' ) );
$get_avatar = get_avatar( $id, $size, $default, $alt );
wp_enqueue_style( 'get-avatar-style' );
return '<span class="get_avatar ' . $class . '">' . $get_avatar . '</span>';
}
add_shortcode( 'get_avatar', wpse_165754_user_avatar_shortcode' );
}