Better handling of RTL stylesheets in plugins and themes

Or, How I Learned To Stop Worrying and Let Core Do The Work For Me.


If you’ve ever done something like this, we should have a little chat:

if ( is_rtl() ) {
	wp_register_style( 'example', plugins_url( "css/example-rtl.css", __FILE__ ) );
} else {
	wp_register_style( 'example', plugins_url( "css/example.css", __FILE__ ) );
}
wp_enqueue_style( 'example' );

Now, don’t worry. I’ve done it too! It’s not that big of a deal. But there is a better, tidier way. Just compare the above code blurb to this:

wp_register_style( 'example', plugins_url( "css/example.css", __FILE__ ), array(), '1.0' );
wp_style_add_data( 'example', 'rtl', 'replace' );
wp_enqueue_style( 'example' );

which will output something like this in rtl locales:

<link rel='stylesheet' id='example-rtl-css' href='http://domain.com/path/to/css/example-rtl.css' type='text/css' media='all' />

Simpler, right? It reads more easily, and as an added bonus, if something is to toggle RTL after you’ve registered the path to the asset, it handles it gracefully! As it doesn’t determine which asset path to serve up until it’s actually outputting the tag.

Now, this is assuming that your rtl stylesheet is just a replacement for your normal stylesheet. Which most are — it could be automatically generated with some tool like CSSJanus or CSS-Flip. But if you’ve got an add-on css file, that you want to load in addition that just contains overrides for RTL languages, you can handle that just as easily!

wp_register_style( 'example', plugins_url( "css/example.css", __FILE__ ), array(), '1.0' );
wp_style_add_data( 'example', 'rtl', 'addon' );
wp_enqueue_style( 'example' );

which will output something like this in rtl locales:

<link rel='stylesheet' id='example-css' href='http://domain.com/path/to/css/example.css' type='text/css' media='all' />
<link rel='stylesheet' id='example-rtl-css' href='http://domain.com/path/to/css/example-rtl.css' type='text/css' media='all' />

For the curious as to how Core actually does it, read here:

https://github.com/WordPress/WordPress/blob/809baf442b/wp-includes/class.wp-styles.php#L88-L104

Detailed explanation (with bonus examples for handling minified versions of both regular and rtl css as well):

/**
 * If you're supplying a pre-minified version of the stylesheet, you'll
 * need this, and to add the `suffix` data, so that core knows to
 * replace `example-min.css` with `example-rtl-min.css` -- handling
 * the suffix properly.
 */
$min = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';

/**
 * The normal registration. You're familiar with this already.
 */
wp_register_style( 'example', plugins_url( "css/example{$min}.css", __FILE__ ), array(), '1.0' );

/**
 * I set the value to 'replace', so it will replace the normal css file if rtl,
 * but it could also be 'addon' for a css file that just gets enqueued as
 * well, rather than replacing the normal one.
 */
wp_style_add_data( 'example', 'rtl', 'replace' );

/**
 * Finally, if we are replacing the existing file, and there's some sort of
 * suffix like `-min` as mentioned earlier, we need to let core know about
 * it, so that it can keep that suffix after the added `-rtl` that it's adding to
 * the path.
 */
wp_style_add_data( 'example', 'suffix', $min );

/**
 * Then we just enqueue it as we would normally!  If it's going to always
 * be enqueued regardless, we could just call `wp_enqueue_style()` rather
 * than `wp_register_style()` above.
 */
wp_enqueue_style( 'example' );

3 thoughts on “Better handling of RTL stylesheets in plugins and themes

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s