How to late enqueue inline CSS in WordPress

So you are building a super duper cool plugin™ that, say, does something with widgets or shortcodes and you need to apply some CSS conditionally. No worries, that’s what wp_add_inline_style() is there for. But can you actually use it?

The problem

There are a few problems however. For starters, wp_add_inline_style() requires the handle of a registered style (via wp_register_style() or wp_enqueue_style()) as its first parameter. And that handle’s stylesheet, must not have been already printed. Now, assuming you are enqueuing your styles properly, the printing takes place during the wp_head action hook, which is a lot earlier than that place in the widgets that you hooked in.

You could perhaps force your style to print on the footer, but there is no such parameter in wp_register_style(). The only way you can do it is enqueuing after the during or after the wp_head action, but that means you are not properly enqueuing your stylesheets.

Or even worse, you might now have a stylesheet to load in the first place. Perhaps all your CSS is dynamic in nature, and a .css file just won’t cut it. Depending on the theme’s main stylesheet file (i.e. style.css) isn’t happening either, as each theme names its handle differently.

So, what do you do?

The solution

There’s a little-known workaround that we’ve used while building our MaxSlider plugin, where we needed to enqueue some generated CSS styles from within a shortcode, however all stylesheets were printed in the header. Without further ado, this is the gist of the workaround:

add_action( 'some_hook', 'maxslider_enqueue_slider_css' );
function maxslider_enqueue_slider_css() {
	$css = '';

	// ...

	if ( true === $something ) {
		$css = 'body { background-color: ' . $color . '; }';

	// ...

	wp_register_style( 'maxslider-footer', false );
	wp_enqueue_style( 'maxslider-footer' );
	wp_add_inline_style( 'maxslider-footer', $css );

The last three lines are the most important.

First, we register a new style handle as usual, but without a file path or URL. This is perfectly valid and will be further explained later. Then, we enqueue that same empty style, and we finally provide it with some CSS to print. These last two lines can swap positions and it will still work just fine.

But how can you enqueue a stylesheet without a path?“, you ask.

The theory is simple:
The wp_*_style() functions use an instance of the WP_Styles class, which extends the WP_Dependencies class. Similarly, the wp_*_script() functions use an instance of the WP_Scripts class, which extends (you guessed it!) the WP_Dependencies class.

Why does it matter? Well, you can pretty much do the same things with both styles and scripts. Take a look at this specific WordPress source code:

$scripts->add( 'jquery', false, array( 'jquery-core', 'jquery-migrate' ), '1.12.4' );

That’s what really happens when you enqueue ‘jquery’. It’s not a real script file, but rather an alias/group that depends upon jquery-core and jquery-migrate. Scripts (and therefore, styles) don’t need a source file, as long as they have some kind of dependency attached to them, be it another script/style, or inline css/js code.

I hope you found the above information useful. Let me know in the comments section below if, where and how it helped you!

Subscribe to our newsletter.

Get a 20% discount code instantly!


  1. Pete says:

    Complete waste of time, you should never have CSS inline, end of story.

    1. Anastis Sourgoutsidis says:

      The method described above is adding a <style> tag, as opposed to the style="" attribute which should be indeed avoided.

  2. Pete says:

    I meant what I said, all CSS should be in external files

    1. Anastis Sourgoutsidis says:

      Unfortunately this isn’t always possible, as CSS must sometimes be generated on the fly. For those cases, wp_add_inline_style() is the way to go.

  3. Pete says:

    Not true at all, if you can include it inline you can add a reference to an external file and do it properly.

Leave a Reply

Your email address will not be published. Required fields are marked *