5

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?

1 Answer 1

6

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');
  }
});
3
  • 1
    This is a fantastic answer, thank you. I want to quickly test both, but assume I'll accept once confirmed.
    – mrwweb
    Commented Mar 30, 2015 at 15:49
  • Switched to solution #2, but I couldn't get #1 to work at all.
    – mrwweb
    Commented Apr 13, 2015 at 23:16
  • @mrwweb It's weird indeed. Tested it just know and it worked for me.
    – gmazzap
    Commented Apr 14, 2015 at 9:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.