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 ☕

Control Directives

Control directives are triggered by CSS comments found between declarations or statements (rules and at-rules). They support processing any node type and can target one node (self-closing) or a set of nodes (block-syntax).

  • Self-closing
.code {
  • Block-syntax
.code {

Control directives are NOT triggered by comments inside selectors, at-rule parameters, or declaration values.

§Control directive defintion object

The definition of a control directive has the following attributes:

  • expect {object}

    An object hash defining the node types this directive is excpected to process, where keys are strings of node types and values are booleans.

    • atrule: At-rule node.
    • comment: Comment node.
    • decl: Declaration node.
    • rule: Rule node.
    • self: Comment node that triggred the directive.

    Find out more about node types at PostCSS API documentation.

    Note: Omitted keys are considred to have a false value.

    "expect": { "rule" : true, "self" : true }
  • begin {function}

    The begin function is responsible for processing nodes of the expected types. It is executed each time a node with the excpected type is encountered.

    'begin': function (node, metadata, context) { ... }

    The begin function must return a boolean value to indicate if it is allowed to process this node by other directives or not.

    • true: prevent further processing.
    • false: allow further processing.
  • end {function}

    The end function is responsible for cleanup and deactivation. It is executed after processing the expected node (if it was self-closing) or when the directive end statement (block-syntax) is encountred.

    'end': function (node, metadata, context) { ... }

    The end functions must return a boolean value to indicate if the directive has finished and should be deactivated or not.

    • true: deactivate.
    • false: keep active.


Here is a complete example of a control directive definition to ignore processing of one node or a set of nodes.

It can be triggered via: /*rtl:ignore*/ or /*rtl:begin:ignore*/.

'ignore': {
  // the expected node types
  'expect': { 'atrule': true, 'comment': true, 'decl': true, 'rule': true },
  // local variable to store ending node
  'endNode': null,
  // prevent processing all nodes except comments indicating the end of this directive
  'begin': function (node, metadata, context) {
    // find the ending node in case of self closing directive
    if (!this.endNode && metadata.begin && metadata.end) {
      var n = node
      while (n && n.nodes) {
        n = n.nodes[n.nodes.length - 1]
      this.endNode = n
    var prevent = true
    if (node.type === 'comment' &&
       (node.text === '!rtl:end:ignore' || node.text === 'rtl:end:ignore')) {
      prevent = false
    return prevent
  // deactivate the directive if:
  //  1. block directive and the node is comment
  //  2. self closing directive and node is endNode
  'end': function (node, metadata, context) {
    if (metadata.begin !== metadata.end && node.type === 'comment' ||
        metadata.begin && metadata.end && node === this.endNode) {
      // clear ending node
      this.endNode = null
      // deactivate 
      return true
    // keep ignoring 
    return false