Extending RTLCSS

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

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