Info

To better encapsulate local and global variables, ctr has a custom variable schema. The idea is quite similar to variables in a CSS preprocessor, just tailored to fit the ctr paradigm. Unlike preprocessor variables, ctr variables are built with a logical variable declaration structure that adds safety precautions. To better understand why ctr variables are my best friend, and will soon become yours too, let us look at the problem they solve.

The Problem

It’s commonplace to have a centralized variable file in a Stylus, Sass, Less, or PostCss project. This file is typically comprised of mission-critical variables such as primary colors, font styles, and everything else in between. However, there is a big catch: all the variable declarations are global. This is fine for a small project, but as a project grows it becomes increasingly unruly due to the inherent limitations of a single namespace. From cryptic variable names to the ever-looming knowledge that someone can come along at any point and overwrite a variable unknowingly, global variables are simply dangerous. Unless you live on the edge and BASE jump while smoking cigarettes on the weekends, I would advise you shy away.

The Solution

The solution comes in the form of a specialized namespace to facilitate both local and global variables. Like everything in ctr, the variable namespace is an Object whose properties and values are defined in key-value pair fashion to go hand in hand with the data structure of ctr. Defined key-value pair variable values can then be used in any ctr instance or class.

The global variable namespace is a single namespace which is shared among all ctr instances and classes. It’s comparable to a centralized CSS preprocessor variable file. On the other hand, the local variable namespace is a private namespace that can only be used within its defined ctr instance or class.

ctr variable scope

The global and local variable namespace allows you to create next-level DRY styles while leveraging the benefits of variable encapsulation. However, the best part about ctr variables is the default level of safety they offer by not allowing you to overwrite previously defined variables.

Syntax

Description: A ctr variable is defined as a local or global variable that can be used in a ctr instance or class.

ctr('<#selector>', {
// local variables
$$: {
one: <value:one>
two: <value:two>
obj: {
three: <value:three>
}
}
<property:one>: '$one$'
<property:two>: '$two$'
<property:three>: '$[obj.three]$'
})
<#selector>:
# local variables
$$:
one: <value:one>
two: <value:two>
obj:
three: <value:three>
<property:one>: $one$
<property:two>: $two$
<property:three>: $[obj.three]$
<#selector> {
<property:one>: <value:one>;
<property:two>: <value:two>;
<property:three>: <value:three>;
}
// global variables
ctrSetVariable({
one: <value:one>
two: <value:two>
obj: {
three: <value:three>
}
})
ctr('<#selector>', {
<property:one>: '$one$'
<property:two>: '$two$'
<property:three>: '$[obj.three]$'
})
# global variables
ctr:::SetVariable:
one: <value:one>
two: <value:two>
obj:
three: <value:three>
<#selector>:
<property:one>: $one$
<property:two>: $two$
<property:three>: $[obj.three]$
<#selector> {
<property:one>: <value:one>;
<property:two>: <value:two>;
<property:three>: <value:three>;
}

Notes

Local

Description: Local variables are defined in the root of the ctr instance or class through an Object key of $$. Variables in the $$ Object are declared in key-value pair fashion and their value can be a String, Object, List, or a Literal. To reference a local variable, the absolute variable path relative to the $$ Object is specified as a String wrapped in dollar signs as such: '$<path>.<to>.<varible>$'.

Edit
ctr('.test', {
$$: {
width: 200px
color: red
fontSize: 1em
pretty-cool: 300px
}
width: '$width$'
font-size: '$fontSize$'
component-span: {
color: '$color$'
// alternative syntax
height: '$[pretty-cool]$'
}
})
.test:
$$:
width: 200px
color: red
fontSize: 1em
pretty-cool: 300px
width: $width$
font-size: $fontSize$
component-span:
color: $color$
# alternative syntax
height: $[pretty-cool]$
.test {
width: 200px;
font-size: 1em;
}
.test > span {
color: #f00;
height: 300px;
}
ctr('.test', {
  $$: {
    width: 200px
    color: red
    fontSize: 1em
    pretty-cool: 300px
  }
  width: '$width$'
  font-size: '$fontSize$'
  component-span: {
    color: '$color$'
    // alternative syntax
    height: '$[pretty-cool]$'
  }
})
.test {
  width: 200px;
  font-size: 1em;
}
.test > span {
  color: #f00;
  height: 300px;
}
.test:
  $$:
    width: 200px
    color: red
    fontSize: 1em
    pretty-cool: 300px
  width: $width$
  font-size: $fontSize$
  component-span:
    color: $color$
    # alternative syntax
    height: $[pretty-cool]$

Notes

Global

Description: Global variables can be defined through a ctrSetVariable invocation or in the .ctrrc.yml file. Variables are declared in key-value pair fashion and their value can be a String, Object, List, or a Literal. To reference a global variable, the absolute variable path is specified as a String wrapped in dollar signs as such: '$<path>.<to>.<varible>$'.

Edit
ctrSetVariable({
width: 200px
color: red
fontSize: 1em
pretty-cool: 300px
})
ctr('.test', {
width: '$width$'
font-size: '$fontSize$'
component-span: {
color: '$color$'
// alternative syntax
height: '$[pretty-cool]$'
}
})
ctr:::setVariable:
width: 200px
color: red
fontSize: 1em
pretty-cool: 300px
.test:
width: $width$
font-size: $fontSize$
component-span:
color: $color$
# alternative syntax
height: $[pretty-cool]$
.test {
width: 200px;
font-size: 1em;
}
.test > span {
color: #f00;
height: 300px;
}
ctrSetVariable({
  width: 200px
  color: red
  fontSize: 1em
  pretty-cool: 300px
})

ctr('.test', {
  width: '$width$'
  font-size: '$fontSize$'
  component-span: {
    color: '$color$'
    // alternative syntax
    height: '$[pretty-cool]$'
  }
})
.test {
  width: 200px;
  font-size: 1em;
}
.test > span {
  color: #f00;
  height: 300px;
}
ctr:::setVariable:
  width: 200px
  color: red
  fontSize: 1em
  pretty-cool: 300px

.test:
  width: $width$
  font-size: $fontSize$
  component-span:
    color: $color$
    # alternative syntax
    height: $[pretty-cool]$

Notes

List

Description: A List value can be used with local and global variables.

Edit
ctr('.test', {
$$: {
keyList: '.easy' '#as' '.oneTwoThree'
}
width: 200px
component: {
key: '$keyList$'
font-size: 1em
}
})
.test:
$$:
keyList: [.easy, '#as', .oneTwoThree]
width: 200px
component:
key: $keyList$
font-size: 1em
.test {
width: 200px;
}
.test > .easy {
font-size: 1em;
}
.test > #as {
font-size: 1em;
}
.test > .oneTwoThree {
font-size: 1em;
}
ctr('.test', {
  $$: {
    keyList: '.easy' '#as' '.oneTwoThree'
  }
  width: 200px
  component: {
    key: '$keyList$'
    font-size: 1em
  }
})
.test {
  width: 200px;
}
.test > .easy {
  font-size: 1em;
}
.test > #as {
  font-size: 1em;
}
.test > .oneTwoThree {
  font-size: 1em;
}
.test:
  $$:
    keyList: [.easy, '#as', .oneTwoThree]
  width: 200px
  component:
    key: $keyList$
    font-size: 1em

Literal

Description: A Literal value can be used with local and global variables.

Edit
ctr('.test', {
$$: {
font-size: 12px
}
width: 200px
font-size: '$font-size$'
})
.test:
$$:
font-size: 12px
width: 200px
font-size: $font-size$
.test {
width: 200px;
font-size: 12px;
}
ctr('.test', {
  $$: {
    font-size: 12px
  }
  width: 200px
  font-size: '$font-size$'
})
.test {
  width: 200px;
  font-size: 12px;
}
.test:
  $$:
    font-size: 12px
  width: 200px
  font-size: $font-size$

Object

Description: An Object value can be used with local and global variables.

Edit
ctr('.test', {
$$: {
myHoverState: {
on: {
opacity: 1
}
non: {
opacity: 0.5
}
}
}
width: 200px
hover: '$myHoverState$'
})
.test:
$$:
myHoverState:
on:
opacity: 1
non:
opacity: 0.5
width: 200px
hover: $myHoverState$
.test {
width: 200px;
}
.test:hover {
opacity: 1;
transition-delay: 0s;
transition-duration: 0.5s;
transition-property: opacity;
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1);
}
.test:not(:hover) {
opacity: 0.5;
transition-delay: 0s;
transition-duration: 0.5s;
transition-property: opacity;
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1);
}
ctr('.test', {
  $$: {
    myHoverState: {
      on: {
        opacity: 1
      }
      non: {
        opacity: 0.5
      }
    }
  }
  width: 200px
  hover: '$myHoverState$'
})
.test {
  width: 200px;
}
.test:hover {
  opacity: 1;
  transition-delay: 0s;
  transition-duration: 0.5s;
  transition-property: opacity;
  transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1);
}
.test:not(:hover) {
  opacity: 0.5;
  transition-delay: 0s;
  transition-duration: 0.5s;
  transition-property: opacity;
  transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1);
}
.test:
  $$:
    myHoverState:
      on:
        opacity: 1
      non:
        opacity: 0.5
  width: 200px
  hover: $myHoverState$

String

Description: A String value can be used with local and global variables.

Edit
ctr('.test', {
$$: {
content: 'hacker news'
}
width: 200px
before: {
content: '$content$'
}
})
.test:
$$:
content: [hacker, news]
width: 200px
before:
content: $content$
.test {
width: 200px;
}
.test::before {
content: "hacker news";
}
ctr('.test', {
  $$: {
    content: 'hacker news'
  }
  width: 200px
  before: {
    content: '$content$'
  }
})
.test {
  width: 200px;
}
.test::before {
  content: "hacker news";
}
.test:
  $$:
    content: [hacker, news]
  width: 200px
  before:
    content: $content$

Multiple String

Description: Multiple local and global ctr variables can be used together in a String.

Edit
ctr('.test', {
$$: {
hLength: 1px
vLength: 2px
blur: 3px
spread: 4px
background: red
}
width: 200px
box-shadow: '$hLength$ $vLength$ $blur$ $spread$ $background$'
})
.test:
$$:
hLength: 1px
vLength: 2px
blur: 3px
spread: 4px
background: red
width: 200px
box-shadow: [$hLength$, $vLength$, $blur$, $spread$, $background$]
.test {
width: 200px;
box-shadow: 1px 2px 3px 4px #f00;
}
ctr('.test', {
  $$: {
    hLength: 1px
    vLength: 2px
    blur: 3px
    spread: 4px
    background: red
  }
  width: 200px
  box-shadow: '$hLength$ $vLength$ $blur$ $spread$ $background$'
})
.test {
  width: 200px;
  box-shadow: 1px 2px 3px 4px #f00;
}
.test:
  $$:
    hLength: 1px
    vLength: 2px
    blur: 3px
    spread: 4px
    background: red
  width: 200px
  box-shadow: [$hLength$, $vLength$, $blur$, $spread$, $background$]

Property Variable

Description: Object key properties can be replaced with local and global variables.

Edit
ctr('.test', {
$$: {
myProp: 'color'
}
width: 200px
$myProp$: red
})
.test:
$$:
myProp: color
width: 200px
$myProp$: red
.test {
color: #f00;
width: 200px;
}
ctr('.test', {
  $$: {
    myProp: 'color'
  }
  width: 200px
  $myProp$: red
})
.test {
  color: #f00;
  width: 200px;
}
.test:
  $$:
    myProp: color
  width: 200px
  $myProp$: red

Notes

Sibling Reference

Description: Local variables can reference previously declared siblings.

Edit
ctr('.test', {
$$: {
size: 12
type: 'rem'
font-size: 'calc($[size]$$[type]$ * ((100vw - 25rem) / 87.5))'
}
width: 200px
font-size: '$font-size$'
})
.test:
$$:
size: 12
type: rem
font-size: calc($[size]$$[type]$ * ((100vw - 25rem) / 87.5))
width: 200px
font-size: $font-size$
.test {
width: 200px;
font-size: calc(12rem * ((100vw - 25rem) / 87.5));
}
ctr('.test', {
  $$: {
    size: 12
    type: 'rem'
    font-size: 'calc($[size]$$[type]$ * ((100vw - 25rem) / 87.5))'
  }
  width: 200px
  font-size: '$font-size$'
})
.test {
  width: 200px;
  font-size: calc(12rem * ((100vw - 25rem) / 87.5));
}
.test:
  $$:
    size: 12
    type: rem
    font-size: calc($[size]$$[type]$ * ((100vw - 25rem) / 87.5))
  width: 200px
  font-size: $font-size$

Notes

Var Not Found

Description: If a local or global variable is not found, ctr will throw an error and return "$var-not-found$".

Edit
ctr('.test', {
$$: {
height: 200px
}
width: 200px
// wrong var name
height: '$not-height$'
})
.test:
$$:
height: 200px
width: 200px
# wrong var name
height: $not-height$
.test {
width: 200px;
height: "$var-not-found$";
}
ctr('.test', {
  $$: {
    height: 200px
  }
  width: 200px
  // wrong var name
  height: '$not-height$'
})
.test {
  width: 200px;
  height: "$var-not-found$";
}
.test:
  $$:
    height: 200px
  width: 200px
  # wrong var name
  height: $not-height$