Extending RTLCSS

Your guide on how to use and make the most out of RTLCSS

Time is Priceless, Caffeine is Not! Buy Me a Coffee ☕

Value Directives

Value directives are triggered by CSS comments found inside delcaration values and can be placed any where inside the declaration value.

They can be either named /*rtl:{name}:{value}*/ or nameless /*rtl:{value}*/.

body {
font-family:"Droid Sans", Tahoma/*rtl:prepend:"Droid Arabic Kufi",*/;

§Value directive defintion object

The definition of a value directive has the following attributes:

  • name {string}

    The directive name, which also happens to be the actual name used to trigger the directive.
    i.e /*rtl:custom*/ will trigger the directive named “custom”.

    // triggered via /*rtl:ignore*/
    "name": "ignore"
    If left empty, it will be match any comment starting with `/*rtl:...`
    // triggered via /*rtl:....*/
    "name": ""

    Value directives are matched one by one according to their order in the containing array, place the generic ones at the end.

  • action {function}

    The action function is responsible for processing the declaration value, It is executed each time a matching comment is found inside the declaration value.

    'action': function (decl, expr, context) { ... }


    • decl {node}: [PostCSS decl] node to be processed.
    • expr {RegExp}: The constructed regular expression used to match the directive, it has one capturing group matching the value of the directive.
    • context {context}: The current RTLCSS context object.


    'name': 'custom',
    'action': function (decl, expr, context) {
    //assuming raw value === "a /*rtl:custom:data*/ b"
    decl.raws.value.raw.replace(expr, function(match, value, index, string){
    //match => "/*rtl:custom:data*/"
    //value => "data"
    //index => 2
    //string => "a /*rtl:custom:data*/ b"

    It must return a boolean value to indicate if it is allowed to process this decl by other directives or not.

    • true: prevent further processing.
    • false: allow further processing.


// a value directive definition to replace the declaration value
// triggered via: /*rtl: ... */
// expected to match any comment starting with "rtl:"
'name': '',
'action': function (decl, expr, context) {
decl.raws.value.raw.replace(expr, function (match, value) {
decl.raws.value.raw = value + match
//prevent further processing of this node
return true


You might wonder why such difference exists between control and value directives. Well, This is due to:

  1. Backward compatibility, I wanted users to be able to upgrade to v2 without having to revisit their CSS files, they only need to change RTLCSS configuration.
    So, In order to support the “Replace” directive /*rtl:{value}*/, all directives names need to be known in advance.
  2. PostCSS does not treat CSS comments found inside delcaration values as nodes.