I’ve got a plugin that makes a widget that enqueues some front-end CSS to style the widdget. I call wp_enqueue_style
from the public
widget()
method in the extended WP_Widget
class:
<?php class FPW_Widget extends WP_Widget {
// ...
public function widget( $args, $instance ) {
// enqueuing here ensure that styles only load when plugin is being displayed
wp_enqueue_style( 'fpw_styles_css', plugins_url( 'css/fpw_styles.css', dirname(__FILE__)), false, FPW_VERSION );
What I’d like is to be able to make that dequeue-able while still keeping the awesome conditional-nature of the enqueueing (i.e. CSS file only loaded when there’s an active widget).
I’ve tried wp_dequeue_style()
both on wp_enqueue_scripts
with a high priority (999
) and on widgets_init
but without any luck.
Is this possible, and, if so, how can I do it?
widget()
method is called when widget is rendered, so the style you’re enqueuing are printed in the footer (header is already printed at that time).
Even if majority of browser can render styles linked from page body, that’s invalid HTML because, according to HTML standards, unlike scrypts, styles must be placed in page <head>
. (Try to validate your markup, and you’ll see errors).
That’s also the reason why 'widgets_init'
and 'wp_enqueue_scripts'
can’t be used to remove the style: these hooks are fired before widget()
method is called, and you can’t remove a style that is not added yet.
There are 2 solutions.
Solution 1
The first solution assumes you want to keep your approach, even if not HTML standards compliant: once style is printed to footer, users may use 'wp_footer'
hook to dequeue the style.
Assuming style is added like:
public function widget( $args, $instance ) {
wp_enqueue_style('fpw_styles_css');
}
can be removed with:
add_action('wp_footer', function() {
wp_dequeue_style('fpw_styles_css');
});
Solution 2
If you want that your plugin doesn’t print invalid HTML, the solution is to use is_active_widget()
to check if the widget is active and enqueue the style if so:
add_action( 'wp_enqueue_scripts', function() {
if ( is_active_widget(false, false, $widgetid) ) {
wp_enqueue_style('fpw_styles_css');
}
}, 5); // used priority 5 to make possible dequeue using default 10 priority
Doing so, the style will be added inside <head>
, and users will be able to dequeue the style using standard approach: wp_dequeue_style()
hooked into 'wp_enqueue_scripts'
.
The only problem is that is_active_widget()
doesn’t check if the widget is actually printed to page, but only if any instance of the widget is configured in backend, in any sidebar. It means is possible that style will be added even if widget is not actually printed to page.
However, users can easily remove the style for specific pages, because conditional tags work fine when 'wp_enqueue_scripts'
is fired. Example:
add_action( 'wp_enqueue_scripts', function() {
if (! is_front_page()) { // allow widget style only in front page
wp_dequeue_style('fpw_styles_css');
}
});