Generating a WordPress rtl.css with Gulp

Generating a rtl.css files is something I don’t enjoy doing. I think it’s really important that they are created since a large proportion of the world uses rtl (right to left) languages. But they are a bit of a pain to create and maintain. In fact I tend to create the file for the theme release, and then not update it (mostly because I forget). As such I have been looking for a way to automate the process for quite some time.

I now have a method that works and I am happily using it in 6 themes, and plan to add more of them as I go.

Big Gulp

The biggest benefit of using this Gulp system is that my themes will stay up to date. I can update/ improve the theme styles and then the build process makes sure the rtl.css stays up to date.

The Problem

Gulp has a number of plugin that flip css styles – however what this does is generate a css file that contains all of the css rules your site uses, with right switched to left (and vice versa). But that’s not what WordPress uses.

A WordPress rtl.css file should just be the flipped rules – not all of the rules. WordPress includes the rtl.css in addition to the style.css file – so you want it to be small and efficient. So my problem was that I wanted to replicate the WordPress behaviour.

Warning: It’s Messy

Looking at the code now – I can say that this probably isn’t efficient – and it’s definitely not pretty! But it works for me so I don’t care.

One thing I noticed (that I had forgotten about) when writing this article is that I am using CSSComb, CSSNano, and Autoprefixer. They do very similar things and there’s probably some crossover. In fact I could potentially refactor the code to remove at least one of these plugins. But since it all works, I’ll save that for another day.

The Codes

Gulp plugins

First we need to install some Gulp plugins. I am using: Gulp (naturally), Gulp Util, Gulp CSS Flipper, Gulp Change, Gulp CSSComb, Gulp CSSNano, Gulp Autoprefixer, and Gulp Rename.

The following commands will make sure they are all installed in your project (using npm – more on that here):

npm install --save-dev gulp
npm install gulp-util --save-dev
npm install gulp-css-flipper --save-dev
npm install gulp-change--save-dev
npm install gulp-csscomb--save-dev
npm install gulp-cssnano--save-dev
npm install --save-dev gulp-autoprefixer
npm install gulp-rename --save-dev

The Gulp Task

So let’s start with the Gulp task, and run through the difference commands being executed.

We start with getting the selected theme from the command line parameter. I explained this in the previous article about creating a Text Domain checker.

We then set start the task proper.

  1. First select the themes style.css file as the task source.
  2. Next we flip it using CSS Flipper. This is a wrapper based on Twitters CSS Flip library. On it’s own it flips the style.css file so that everything is mirrored.
  3. Next we use the change plugin to tidy the css. This just adds some line breaks to make things easier to manipulate in the next function. (BTW – I think the change plugin is awesome – I use it a lot).
  4. The change plugin again – this time executing the custom rtl function. I’ll go through this in the minute but basically it strips out any css that doesn’t change between languages.
  5. Next we autoprefix. The rtl function we just used doesn’t support browser prefixes so this adds them back.
  6. CSSNano now to minify the css. The important part of CSSNano is that it deletes empty selectors – something the custom rtl function will have created.
  7. CSSComb to reduce and tidy the css used. I could potentially use CSSNano for this but I don’t like how it prettifies the CSS. Note that you will need a CSSComb settings file to ensure the css is output as you like – I used this.
  8. Rename the output file to rtl.css – otherwise the style.css file would be overwritten.
  9. Then set the destination location (the theme directory).


This is the function that does the most complex bits. It took me a while to work out how it would work. At times I was considering finding some sort of CSS parsing library, or something else I could reuse to save me time. Eventually I hit upon the idea of using the ‘change’ plugin, and simply dropping any css properties that are not appropriate.

So, I grabbed the list of css properties from the CSS Flip docs and turned it into a javascript list. I then split the transformed rtl file into an array (based upon line endings), and looped through all the lines. I then create a new array storing only the css selectors, and the properties that have changed. This does end up with some empty selectors being left – but that’s what I use CSSNano to clean up.

You’ll notice at the end there are a few string replacements done. This is to get rid of properties like text-align: center; that don’t need to be mirrored whilst keeping text-align: left; and text-align: right;.

Things to Keep in Mind

This whole thing is working really well for me, but there are a few things I need to keep in mind when developing.

The biggest thing is how I structure css. I have to make sure that any time I use margin-left I include margin-right, or I use a full margin declaration. The reason for this is that the CSS flipper will flip margin-left to margin-right (what we want) but since rtl.css is added on top of style.css the original rule will still exist. So we have to declare both rules, even if they are inherited from the defaults, so that the opposite value is reset accordingly.

In addition – you will find times when you don’t want to flip a rule, or when you want to replace a rule with something else (for instance arrow images in a slider that should change direction). CSS Flip has you covered here– simply add a special comment before the rule you want to change (or not change) and CSS Flip will make the relevant changes when flipping.

Finally – for testing, I use the RTL Tester plugin to make sure everything is flipped as expected.


In my experience using this, and the Gulp Task above, I can get a new RTL file working in a half an hour or so per theme. And, as I mentioned before, once I’ve done it once it will continue updating. So as I tweak and improve the CSS in the LTR version of the theme, the updated RTL files remain up to date.

Was it good/ useful/ a load of old rubbish? Let me know on Mastodon, or BlueSky (or Twitter X if you must).

Link to this page

Thanks for reading. I'd really appreciate it if you'd link to this page if you mention it in your newsletter or on your blog.

WordPress News

The latest WordPress updates from the WPBriefs Podcast.

Related Posts

04 Nov 2016

Automating WordPress Development with Gulp, Bash, and PHP

When I wrote about the things I had learned from releasing 20 WordPress themes, I mentioned that I had automated as much as I could. One of the things I automated was the build and deployment process for my themes...
01 Apr 2015

The State of WordPress Themes #wcldn

I recently spoke on a panel at WordCamp London 2015e. Lance – who used to be the Theme Team lead at – asked me if I wanted to speak on a panel with him at WordCamp London 2015. I’ve...
13 Oct 2016

Lessons Learned from 20 Theme Releases on

In 2007 I partnered with Darren Hoyt to release Mimbo Pro, one of the earliest premium WordPress themes. In 2012 Mimbo Pro was published on Last week – on October 5th 2016 to be precise – my 20th theme...
27 May 2013

WordPress: 10 Years Young, What Does The Future Hold?

WordPress is now 10 years old. I started using wordpress 9 years ago – which means I joined the WordPress community early on. The reason I chose WordPress is simply because of the fabled 5 minute install process – I...
28 Sep 2021

Creating Generative Art with PHP

These last few weeks I’ve been experimenting with Generative Art, using PHP. You can see the evolution of my latest series on Twitter. Generative Art is creating artworks through programming. Generative art has a few different names, Procedural art and...