Installation
Browser
Download the Roole script file from the home page and insert it into HTML:
<body>
<script src="/path/to/roole.js"></script>
</body>
Then either link to external Roole files using link
tag with rel="stylesheet/roole"
:
<head>
<link rel="stylesheet/roole" href="/path/to/styles.roo">
</head>
Or embed Roole code directly using style
tag with type="text/roole"
:
<head>
<style type="text/roole">
body {
$margin = 0;
margin: $margin;
}
</style>
</head>
Make sure the script file is placed after Roole files/code.
Node.js
Install with npm:
$ npm install roole -g
Then compile Roole files by running:
$ roole /path/to/style.roo
Run roole -h
to see more usage.
Nesting
Rule sets can be nested, and their selectors will be joined together.
#header {
.logo {
float: left;
}
}
#header .logo {
float: left;
}
ul {
overflow: hidden;
> li {
float: left;
}
}
ul {
overflow: hidden;
}
ul > li {
float: left;
}
#main, #sidebar {
h1, h2 {
font-weight: bold;
}
}
#main h1,
#main h2,
#sidebar h1,
#sidebar h2 {
font-weight: bold;
}
Use the &
selector to reference the selector in the outer rule set.
a {
&:hover {
text-decoration: underline;
}
}
a:hover {
text-decoration: underline;
}
img {
a & {
border: none;
}
}
a img {
border: none;
}
The &
selector also can be nested.
a {
&:hover {
text-decoration: underline;
.btn & {
text-decoration: none;
}
}
}
a:hover {
text-decoration: underline;
}
.btn a:hover {
text-decoration: none;
}
Media blocks can be nested into rule sets.
.sidebar {
@media print {
display: none;
}
}
@media print {
.sidebar {
display: none;
}
}
.container {
@media print {
.sidebar {
display: none;
}
}
}
@media print {
.container .sidebar {
display: none;
}
}
Or within one another, and their media queries will be joined together.
@media screen {
a {
color: black;
@media (color) {
color: blue;
}
}
}
@media screen {
a {
color: black;
}
}
@media screen and (color) {
a {
color: blue;
}
}
Comment
Single-line comments are removed from the generated CSS.
.box {
float: left;
margin-left: 20px;
// Fix IE6
display: inline;
}
.box {
float: left;
margin-left: 20px;
display: inline;
}
Multi-line commnets are preserved.
/*
* Navigation
*/
.nav {
float: left;
/*
* Navigation list
*/
> ul {
list-style: none;
}
}
/*
* Navigation
*/
.nav {
float: left;
}
/*
* Navigation list
*/
.nav > ul {
list-style: none;
}
/*
* Navigation
*/
.nav {
float: left;
/* Last comment in rule set */
}
/* Last comment in file */
/*
* Navigation
*/
.nav {
float: left;
}
When placed before non-CSS rules, multi-line commnets are transfered down to nestest CSS rules.
/*
* Navigation
*/
@if true {
.nav {
float: left;
}
}
/*
* Navigation
*/
.nav {
float: left;
}
/*
* Span
*/
@for $i in 1..2 {
.span-$i {
float: left;
}
}
/*
* Span
*/
.span-1 {
float: left;
}
.span-2 {
float: left;
}
Variable
Variables are case-sensitive. Their names start with $
and are defined using assignments.
$margin = 20px 0;
$MARGIN = 30px 0;
p {
margin: $margin;
}
p {
margin: 20px 0;
}
Variables are allowed where values like numbers, strings, identifiers, etc are allowed.
$tag = body;
$tag {
margin: 0;
}
body {
margin: 0;
}
$attribute = type;
$value = button;
input[$attribute=$value] {
border: none;
}
input[type=button] {
border: none;
}
$property = margin;
$value = 20px;
p {
$property: $value;
}
p {
margin: 20px;
}
$feature = max-width;
$value = 1024px;
@media ($feature: $value) {
#main {
width: 960px;
}
}
@media (max-width: 1024px) {
#main {
width: 960px;
}
}
Variable scope is covered in the Scope section
Interpolation
Variables can be interpolated into doubled-quoted strings.
$num = 12;
.heading::before {
content: "Chapter $num";
}
.heading::before {
content: "Chapter 12";
}
But not single-quoted strings.
.heading::before {
content: 'Chapter $num';
}
.heading::before {
content: 'Chapter $num';
}
Variables can also be interpolated into identifiers.
$name = star;
.icon-$name {
width: 20px;
height: 20px;
}
.icon-star {
width: 20px;
height: 20px;
}
$pos = left;
.sidebar {
float: $pos;
margin-$pos: 20px;
}
.sidebar {
float: left;
margin-left: 20px;
}
Use \$
to escape variables inside strings.
.heading::before {
content: "Chapter \$num";
}
.heading::before {
content: "Chapter \$num";
}
Wrap the variable in curly braces({}
) to seperate characters come after it, which would otherwise be part of its name.
$num = 4;
.figcaption::before {
content: "Figure {$num}-12";
}
.figcaption::before {
content: "Figure 4-12";
}
$pos = left;
.sidebar {
border-{$pos}-width: 1px;
}
.sidebar {
border-left-width: 1px;
}
Use \{
to escape it.
$num = 4;
.figcaption::before {
content: "Figure \{$num}-12";
}
.figcaption::before {
content: "Figure \{4}-12";
}
.title::before {
content: "latex \\hat\{x}";
}
.title::before {
content: "latex \\hat\{x}";
}
You can actually put arbitrary expressions (more on expressions in later sections) inside curly braced interpolations.
.figcaption::before {
content: "Figure {3 + 1}-12";
}
.figcaption::before {
content: "Figure 4-12";
}
When being assigned with an string value, variables can be directly interpolated in to selectors.
$selector = '#sidebar a';
$selector {
color: blue;
}
#sidebar a {
color: blue;
}
$tab = '.tabs .tab';
#sidebar $tab {
padding: 5px;
}
#sidebar .tabs .tab {
padding: 5px;
}
When the variable is the only thing in the selector, selector list can be interpolated.
$btns = '.submit, .reset';
$btns {
padding: 5px;
}
.submit,
.reset {
padding: 5px;
}
$tab = '.tabs .tab';
$btns = '.submit, .reset';
#sidebar $tab,
$btns {
padding: 5px;
}
#sidebar .tabs .tab,
.submit,
.reset {
padding: 5px;
}
The same goes for media queries.
$mq = '(min-width: 768px)';
@media $mq {
body {
margin: 0;
}
}
@media (min-width: 768px) {
body {
margin: 0;
}
}
$mq = '(min-width: 768px), (color)';
@media $mq {
body {
margin: 0;
}
}
@media (min-width: 768px), (color) {
body {
margin: 0;
}
}
List
Lists are one of the many basic values Roole support. They are values separated by either spaces, commas(,
) or slashes(/
).
For example, 1px 2px 3px
, sans-serif, serif
, 14px/1.2
.
Note that 14px/1.2 sans-serif
is a list with three items separated by a slash and a space.
Lists can be wrapped in square brackets([]
). When there are more than one item, the square brackets are optional.
Square brackets are useful when you need to create emtpy lists([]
), lists with only item(e.g., [1]
) or nested lists(e.g., [1px, [2px, 3px]]
).
Range
Ranges are another basic values Roole support.
They are two numberic values(e.g, 1px
, 20%
, 0
) separated by either ..
or ...
.
They denote ranges that can be used directly in some consturcts (e.g., loops, member expressions) or be converted to lists when compiled to CSS.
.box {
margin: 1px..3px;
}
.box {
margin: 1px 2px 3px;
}
When being converted a to list, the list is separated by spaces, with the left numberic value determining the unit of all items in the list. For example, 1px..3
will be converted to 1px 2px 3px
.
..
creates inclusive ranges whereas ...
creates exclusive ranges. The difference is that for exclusive ranges, the right values are excluded.
.box {
margin: 1px...3px;
}
.box {
margin: 1px 2px;
}
Ranges can be in reversed order.
.box {
margin: 3px..1px;
}
.box {
margin: 3px 2px 1px;
}
.box {
margin: 3px...1px;
}
.box {
margin: 3px 2px;
}
.box {
margin: 1px..-1px;
}
.box {
margin: 1px 0px -1px;
}
Member Expression
Items in a list can be accessed using member expressions.
$margins = 1px 2px 3px 4px;
.box {
margin-top: $margins[0];
}
.box {
margin-top: 1px;
}
Index can also be a range, which will return a sub-list.
$margins = 1px 2px 3px 4px;
.box {
margin: $margins[0..1];
}
.box {
margin: 1px 2px;
}
$margins = 1px 2px 3px 4px;
.box {
margin: $margins[1...3];
}
.box {
margin: 2px 3px;
}
When a list is being accessed with a range, the result is guaranteed to be a list, even if the range denotes only one item.
$margins = 1px 2px 3px 4px;
.box {
margin: $margins[2...3][0];
}
.box {
margin: 3px;
}
Accessing with an empty range returns an empty list.
Negative indice start from the end of the list.
$margins = 1px 2px 3px 4px;
.box {
margin-top: $margins[-1];
}
.box {
margin-top: 4px;
}
$margins = 1px 2px 3px 4px;
.box {
margin: $margins[-2..-1];
}
.box {
margin: 3px 4px;
}
Reversed ranges reverse the result list.
$margins = 1px 2px 3px 4px;
.box {
margin: $margins[2..1];
}
.box {
margin: 3px 2px;
}
$margins = 1px 2px 3px 4px;
.box {
margin: $margins[-1..-2];
}
.box {
margin: 4px 3px;
}
Ranges can be accessed as if they were lists.
$margins = 1px..4px;
.box {
margin-top: $margins[0];
}
.box {
margin-top: 1px;
}
$margins = 1px..4px;
.box {
margin: $margins[0..1];
}
.box {
margin: 1px 2px;
}
Member expressions can also be used in assignments.
$margins = 1px 2px 3px 4px;
$margins[1] = 12px;
.box {
margin: $margins;
}
.box {
margin: 1px 12px 3px 4px;
}
$margins = 1px 2px 3px 4px;
$margins[1..2] = 12px, 13px;
.box {
margin: $margins;
}
.box {
margin: 1px 12px, 13px 4px;
}
$margins = 1px 2px 3px 4px;
$margins[2..1] = 12px, 13px;
.box {
margin: $margins;
}
.box {
margin: 1px 13px, 12px 4px;
}
Assigning to an index that is outside the list automatically grows the list, and "holes" with be filled with null
s.
$margins = 1px 2px;
$margins[3] = 4px;
.box {
margin: $margins;
}
.box {
margin: 1px 2px null 4px;
}
$margins = 1px 2px;
$margins[2..3] = 3px 4px;
.box {
margin: $margins;
}
.box {
margin: 1px 2px 3px 4px;
}
Empty ranges can be used to insert items.
$margins = 1px 2px 4px;
$margins[2...2] = 3px;
.box {
margin: $margins;
}
.box {
margin: 1px 2px 3px 4px;
}
Assignming with a empty list removes items.
$margins = 1px 2px 3px;
$margins[1] = [];
.box {
margin: $margins;
}
.box {
margin: 1px 3px;
}
$margins = 1px 2px 3px 4px;
$margins[1..2] = [];
.box {
margin: $margins;
}
.box {
margin: 1px 4px;
}
Arithmetic Expressions
Arithmetic operators for doing addition(+
), substraction(-
), multiplication(*
), division(/
) and modulus(%
) are supported. Use parentheses ()
to change precedence.
$w = 250px;
$p = 20px;
$b = 1px;
.sidebar {
width: $w - ($p + $b) * 2;
padding: $p;
border: $b solid;
}
.sidebar {
width: 208px;
padding: 20px;
border: 1px solid;
}
At lease one space should exist around /
, otherwise it is recognized as a list separator
At lease one space should exist on the right side of +
and -
, or no space exists on either side, otherwise unary +
and -
is applied:
.box {
margin: 40px -20px;
}
.box {
margin: 40px -20px;
}
.box {
margin: 40px +20px;
}
.box {
margin: 40px 20px;
}
Arithmetic operations in calc()
are preserved in the generated CSS.
.box {
margin: calc(250px - 50%);
}
.box {
margin: calc(250px - 50%);
}
Unit
Directly appending a unit after a numberic value to change its unit.
.box {
margin: (32px / 16px)em;
}
.box {
margin: 2em;
}
Remember to multiply the value by 100 when converting to percentage.
.box {
width: (200px / 800px * 100)%;
}
.box {
width: 25%;
}
Conditional
Nest rules inside @if
to generate them conditionally.
$support-old-ie = false;
li {
@if $support-old-ie {
display: inline;
}
float: left;
margin-left: 10px;
}
li {
float: left;
margin-left: 10px;
}
Conditon expressions are automatically converted to booleans. Faley values include false
, null
, zero-ish numberic values(e.g, 0
, 0px
, 0%
), empty strings(e.g, ''
). All other values are truthy (including []
, '0'
).
@if
can be followed by any number of @else if
s and optionally one @else
.
$color = #000;
body {
@if $color is #fff {
background: #000;
} @else if $color is #00 {
background: #fff;
} @else {
background: url(bg.png);
}
}
body {
background: url(bg.png);
}
Many operators can be used when specifying the condition.
Like is
, which tests equalitys, isnt
tests inequality.
$size = large;
.btn {
@if $size isnt small {
border: 1px solid;
}
}
.btn {
border: 1px solid;
}
and
expects values on its both sides to be truthy. It is short-circuited, meaning the right value is not evaluated if the left value is falsey.
$size = large;
$type = split;
.btn {
@if $size is large and $type is split {
padding: 10px;
}
}
.btn {
padding: 10px;
}
or
expects values on its either sides to be truthy. It is short-circuited, meaning the right value is not evaluated if the left value is truthy.
$size = large;
.btn {
@if $size is medium or $size is large {
border: 1px solid;
}
}
.btn {
border: 1px solid;
}
<
, <=
, >
and >=
compare values.
$w = 60px;
.btn {
@if $w > 50px and $w < 90px {
border: 1px solid;
} @else {
border: none;
}
}
.btn {
border: 1px solid;
}
Loop
Loops allow rules to be generated multiple times. Ranges can be directly looped over.
@for $i in 1..3 {
.span-$i {
width: $i * 60px;
}
}
.span-1 {
width: 60px;
}
.span-2 {
width: 120px;
}
.span-3 {
width: 180px;
}
@for $i in 3..1 {
.span-$i {
width: $i * 60px;
}
}
.span-3 {
width: 180px;
}
.span-2 {
width: 120px;
}
.span-1 {
width: 60px;
}
Lists can also be looped.
@for $name in arrow star heart {
.icon-$name {
background: url("$name.png");
}
}
.icon-arrow {
background: url("arrow.png");
}
.icon-star {
background: url("star.png");
}
.icon-heart {
background: url("heart.png");
}
To specify a step other than 1, use by
.
@for $i by 2 in 1..5 {
.span-$i {
width: $i * 60px;
}
}
.span-1 {
width: 60px;
}
.span-3 {
width: 180px;
}
.span-5 {
width: 300px;
}
@for $name by 2 in arrow star heart {
.icon-$name {
background: url("$name.png");
}
}
.icon-arrow {
background: url("arrow.png");
}
.icon-heart {
background: url("heart.png");
}
If step is a negative number, the order of iteration is reversed.
@for $i by -1 in 1..2 {
.span-$i {
width: $i * 60px;
}
}
.span-2 {
width: 120px;
}
.span-1 {
width: 60px;
}
@for $name by -1 in arrow star heart {
.icon-$name {
background: url("$name.png");
}
}
.icon-heart {
background: url("heart.png");
}
.icon-star {
background: url("star.png");
}
.icon-arrow {
background: url("arrow.png");
}
To access indices, specify one more variable.
@for $name, $i in arrow star heart {
.icon-$name {
background-position: 0 $i * 20px;
}
}
.icon-arrow {
background-position: 0 0px;
}
.icon-star {
background-position: 0 20px;
}
.icon-heart {
background-position: 0 40px;
}
Function
Functions can be assigned to variables, and be used later by calling the variables.
$half = @function {
@return 100 / 2%;
};
.span-half {
width: $half();
}
.span-half {
width: 50%;
}
Functions can have parameters, which can have a default value.
$px2em = @function $px, $base = 16px {
@return $px / $base * 1em;
};
h2 {
font-size: $px2em(32px);
}
h2 {
font-size: 2em;
}
Arguments passed to a function can also be accessed dynamically using $arguments
$double = @function {
$list = [];
@for $arg, $i in $arguments {
$list[$i] = $arg * 2;
}
@return $list;
};
.box {
margin: $double(1px, 2px, 3px);
}
.box {
margin: 2px 4px 6px;
}
Use rest parameter to capture multiple arguments.
$multiply = @function $multi, ...$nums {
$list = [];
@for $num, $i in $nums {
$list[$i] = $num * $multi;
}
@return $list;
};
.box {
margin: $multiply(3, 1px, 2px, 3px);
}
.box {
margin: 3px 6px 9px;
}
Unassigned parameters have a value null
.
$retArgs = @function $a, $b {
@return $a $b;
};
.heading {
font-size: $retArgs(1px);
}
.heading {
font-size: 1px null;
}
Mixin
Functions can be mixed in when they contain rules, and are called after @mixin
.
$btn = @function $color, $bg-color {
display: inline-block;
color: $color;
background: $bg-color;
};
.submit {
@mixin $btn(#000, #fff);
}
.submit {
display: inline-block;
color: #000;
background: #fff;
}
Rule sets can be mixed in if a selector or a list of selectors are specified after @mixin
.
.btn {
display: inline-block;
}
.submit {
@mixin .btn;
}
.btn {
display: inline-block;
}
.submit {
display: inline-block;
}
@mixin
can be nested inside media blocks.
.btn.large {
padding: 10px 15px;
}
@media (min-width: 768px) {
.submit {
@mixin .btn.large;
}
}
.btn.large {
padding: 10px 15px;
}
@media (min-width: 768px) {
.submit {
padding: 10px 15px;
}
}
Void
Rule sets inside @void
are removed from the generated CSS.
@void {
.btn {
display: inline-block;
}
}
.submit {
@mixin .btn;
}
.submit {
display: inline-block;
}
This is useful for creating base styles that should not be used directly in the CSS.
Importing
Import files by specifying a string after @import
.
.btn {
display: inline-block;
}
@import './btn.roo';
.btn {
display: inline-block;
}
If the file being imported is a directory, Roole will first look for a package.json
file in that directory, which is npm's package.json. If it exists, Roole will import the file specifed in the JSON's main
property. If no such file exist, it will import index.roo
in that directory.
Extension names are not added automatically, so you need to specifiy them explicitly.
Files are not imported if their paths are specified using url()
or starting with a protocol.
@import url(./tabs);
@import url("./tabs");
@import "http://example.com/tabs";
@import url(tabs);
@import url("tabs");
@import "http://example.com/tabs";
Variables can be used in the path.
.btn {
display: inline-block;
}
$module = 'btn';
@import "./$module.roo";
.btn {
display: inline-block;
}
Regular CSS files can be imported, so you may interact with existing CSS libraries.
.btn {
display: inline-block;
}
@import "./btn.css";
.submit {
@mixin .btn;
}
.btn {
display: inline-block;
}
.submit {
display: inline-block;
}
@import
with media queries will be converted to media blocks.
.btn {
display: inline-block;
}
@import "./btn.roo" screen;
@media screen {
.btn {
display: inline-block;
}
}
Files are only imported once.
body {
margin: 0;
}
@import './reset.roo';
.btn {
display: inline-block;
}
@import './reset.roo';
.tab {
float: left;
}
@import './reset.roo';
@import './btn.roo';
@import './tabs.roo';
body {
margin: 0;
}
.btn {
display: inline-block;
}
.tab {
float: left;
}
If the path does not start with ./
, ../
or /
, then Roole will try to import it as a node module
Node modules exists in a node_modules
folder. Refer to Node.js docs on how that folder is located.
.tab {
float: left;
}
@import 'tabs.roo';
.tab {
float: left;
}
@import
can be nested inside other rules.
.sidebar {
float: left;
margin-left: 20px;
}
.sidebar {
display: inline;
}
$support-old-ie = false;
@import './sidebar.roo';
@if $support-old-ie {
@import './sidebar-old-ie.roo';
}
.sidebar {
float: left;
margin-left: 20px;
}
URL
Relative paths in Roole will be translated when compiled to CSS.
Relative paths starting ./
or ../
are relative to the current file.
.btn {
background: url(./bg.png);
}
@import './btn/btn.roo';
.btn {
background: url(btn/bg.png);
}
Relative paths does not start with ./
and ../
are relative to a base directory. For Node.js, it's the current working directory. For browsers, it's the directory of the HTML page.
.btn {
background: url(bg.png);
}
@import './btn/btn.roo';
.btn {
background: url(bg.png);
}
Absolute paths are never translated.
.btn {
background: url(/bg.png);
}
@import './btn/btn.roo';
.btn {
background: url(/bg.png);
}
Scope
Variables have to be defined before they can be used. Once defined, they are only available within the boundary of their respective rule block, which defines their scope.
$menu = @function {
$width = 200px;
width: $width;
};
.menu {
@mixin $menu();
// $width is undefined here
}
.menu {
width: 200px;
}
Variables assigned using =
assignments always "shadow" variables with the same name in an outer scope, but never overwrite them.
$width = 200px;
.mini-menu {
$width = 100px;
width: $width;
}
.menu {
width: $width;
}
.mini-menu {
width: 100px;
}
.menu {
width: 200px;
}
Use :=
assignments to overwrite variables in an outer scope.
$width = 200px;
.mini-menu {
$width := 100px;
width: $width;
}
.menu {
width: $width;
}
.mini-menu {
width: 100px;
}
.menu {
width: 100px;
}
?=
assignments will assign variables a value only if they haven't been defined.
$width = 200px;
.mini-menu {
$width ?= 100px;
width: $width;
}
.menu {
width: $width;
}
.mini-menu {
width: 200px;
}
.menu {
width: 200px;
}
Variables created by ?=
assignments are local to the current scope.
.mini-menu {
$width ?= 100px;
width: $width;
}
// $width is undefined here
.mini-menu {
width: 100px;
}
Variables defined in an imported file are exposed to the importing file.
$color = #000;
$bg-color = #fff;
@import './vars.roo';
.main {
color: $color;
background: $bg-color;
}
.main {
color: #000;
background: #fff;
}
The imported file has access to variables defined in the importing file.
.main {
color: $color;
background: $bg-color;
}
$color = #000;
$bg-color = #fff;
@import './base.roo';
.main {
color: #000;
background: #fff;
}
Functions have lexical scope.
$width = 200px;
$menu = @function {
width: $width;
};
.menu {
$width = 300px;
@mixin $menu();
}
.menu {
width: 200px;
}
Block
Blocks simply introduce a new scope.
$width ?= 200px;
.foo-module {
width: $width;
}
$width ?= 100px;
.bar-module {
width: $width;
}
@block {
$width = 300px;
@import 'foo-framework';
}
@block {
@import 'bar-framework';
}
.foo-module {
width: 300px;
}
.bar-module {
width: 100px;
}
Builtin Function
Builtin functions are global function available to all scopes. There is no need to import any file to use them.
$len($value)
Return the length of a value.
For lists and ranges, it's the number of items they contain. For strings, it's the length of characters. For other values, it returns 1
.
a {
content: $len(0 1);
content: $len(1..3);
content: $len('text');
content: $len(2px);
content: $len(null);
}
a {
content: 2;
content: 3;
content: 4;
content: 1;
content: 1;
}
$list($value, [$sep])
Convert $value
to list, optionally with $sep
being the separator (defaults to space if not provided).
a {
content: $list(1..3);
content: $list(0 1, ',');
}
a {
content: 1 2 3;
content: 0, 1;
}
$push($list, ...$vals)
Push value to the end of $list
. Return $list
.
a {
content: $push(0 1, 2);
content: $push([1, 2], 3, 4);
}
a {
content: 0 1 2;
content: 1, 2, 3, 4;
}
$pop($list)
Pop value from the end of $list
.
a {
content: $pop(0 1);
content: $pop([1, 2]);
}
a {
content: 1;
content: 2;
}
$unshift($list, ...$vals)
Unshift values to the start of $list
.
a {
content: $unshift(0 1, -1);
content: $unshift([1, 2], -1, 0);
}
a {
content: -1 0 1;
content: -1, 0, 1, 2;
}
$shift($list)
Shift a value from the start of $list
.
a {
content: $shift(0 1);
content: $shift([1, 2]);
}
a {
content: 0;
content: 1;
}
$opp($value)
Return the opposite value of a string or an identifier denoting a position.
$value
can be a list, in which case all items of it are translated.
The opposite of right
is left
, top
is bottom
and vice versa. All other values stay the same value.
a {
content: $opp(to bottom right);
}
a {
content: to top left;
}
$img-size($path)
Return the image dimension locationed at $path
. $path
is the image file path follows the same rule explained in the URL section. The returning value is a list, with the first item being the width and the second being the height.
.img {
$size = $img-size('20x10.png');
width: $size[0];
height: $size[1];
}
.img {
width: 20px;
height: 10px;
}
Prefixing
Rules are automatically prefixed with vendor names.
.box {
box-shadow: 0 1px 3px #000;
}
.box {
-webkit-box-shadow: 0 1px 3px #000;
-moz-box-shadow: 0 1px 3px #000;
box-shadow: 0 1px 3px #000;
}
Start position in linear-gradient()
is automatically translated (this is not currently perfect, as angle values are not translated and no -webkit-gradient()
generated).
.box {
background: linear-gradient(to bottom, #fff, #000);
}
.box {
background: -webkit-linear-gradient(top, #fff, #000);
background: -moz-linear-gradient(top, #fff, #000);
background: -o-linear-gradient(top, #fff, #000);
background: linear-gradient(to bottom, #fff, #000);
}
When nested rules need to be prefixed, Roole handles it correctly.
@keyframes become-round {
from {
border-radius: 0;
}
to {
border-radius: 50%;
}
}
@-webkit-keyframes become-round {
from {
-webkit-border-radius: 0;
border-radius: 0;
}
to {
-webkit-border-radius: 50%;
border-radius: 50%;
}
}
@-moz-keyframes become-round {
from {
-moz-border-radius: 0;
border-radius: 0;
}
to {
-moz-border-radius: 50%;
border-radius: 50%;
}
}
@-o-keyframes become-round {
from {
border-radius: 0;
}
to {
border-radius: 50%;
}
}
@keyframes become-round {
from {
border-radius: 0;
}
to {
border-radius: 50%;
}
}
Until the prefixing feature is revamped. You are encouraged to use Autoprefixer to prefix the generated CSS.