In the context of JavaScript the closest thing to pure CSS syntax is JSON format. So, every valid JSON is actually valid Absurd syntax. As you can see above, there are two ways to send styles to the module. In both cases you have an access to the Absurd's API.
Absurd(function(api) {
api.add({});
});
or in an external js file
module.exports = function(api) {
api.add({});
}
The add method accepts valid JSON. This could be something like
{
body: {
marginTop: '20px',
padding: 0,
fontWeight: 'bold',
section: {
paddingTop: '20px'
}
}
}
Every object defines a selector. Every property of that object could be a property and its value or another object. For example the JSON above is compiled to:
body {
margin-top: 20px;
padding: 0;
font-weight: bold;
}
body section {
padding-top: 20px;
}
Have in mind that you don't need to quote the CSS properties. AbsurdJS converts every uppercase letter to a dash followed by the lowercase version of the letter. I.e.:
WebkitTransform -> -webkit-transform
You may send even an array of style like that
{
'.header nav': [
{ fontSize: '10px' },
{ fontSize: '20px' }
]
}
And that's compiled to
.header nav {
font-size: 20px;
}
It's similar like the example above:
a: {
textDecoration: 'none',
color: '#000',
':hover': {
textDecoration: 'underline',
color: '#999'
},
':before': {
content: '"> "'
}
}
Is compiled to:
a {
text-decoration: none;
color: #000;
}
a:hover {
text-decoration: underline;
color: #999;
}
a:before {
content: "> ";
}
It has the same meaning like in LESS.
a: {
color: '#000',
'&.sky': {
color: "blue"
}
}
Is compiled to:
a {
color: #000;
}
a.sky {
color: blue;
}
Of course you can't put everything in a single file. That's why there is .import method:
module.exports = function(api) {
api.import(__dirname + '/config/colors.js');
api.import(__dirname + '/config/sizes.js');
api.import([
__dirname + '/layout/grid.json'
]);
api.import([
__dirname + '/forms/login-form.css',
__dirname + '/forms/feedback-form.css'
]);
}
Pay attention to the type of the files. The first two are actually JavaScript files, because they need an access to the API (to define mixins, plugins etc ...). The second import statement adds the actual styling. Of course it is not necessary to use this approach, but writing pure JSON sometimes may be a better option.
There is no need to use something special. Because that's pure javascript you may write:
var brandColor = "#00F";
Absurd(function(api) {
api.add({
'.header nav': {
color: brandColor
}
})
})
However, if you want to share variables between the files you may use the API's method storage. Let's say that you have two files /css/A.js and /css/B.js and you want to share values between them.
// A.js
module.exports = function(api) {
api.storage("brandColor", "#00F");
}
// B.js
module.exports = function(api) {
api.add({
body: {
color: api.storage("brandColor")
}
})
}
In the context of Absurd mixins are actually normal javascript functions. The ability to put things inside the Absurd's storage gives you also the power to share mixins between the files. For example:
// A.js
module.exports = function(api) {
api.storage("button", function(color, thickness) {
return {
color: color,
display: "inline-block",
padding: "10px 20px",
border: "solid " + thickness + "px " + color,
fontSize: "10px"
}
});
}
// B.js
module.exports = function(api) {
api.add({
'.header-button': [
api.storage("button")("#AAA", 10),
{
color: '#F00',
fontSize: '13px'
}
]
});
}
What you do is to send array of two objects to the selector '.header-button'. The above code is compiled to:
.header-button {
color: #F00;
display: inline-block;
padding: 10px 20px;
border: solid 10px #AAA;
font-size: 13px;
}
Notice that the second object overwrites few styles passed via the mixin.
The plugins are similar like mixins, but act as property-value pair. There is an API method for registering plugins.
api.plugin('my-custom-gradient', function(api, colors) {
return {
background: 'linear-gradient(to bottom, ' + colors.join(", ") + ')'
};
});
api.plugin('brand-font-size', function(api, type) {
switch(type) {
case "small": return { fontSize: '12px'}; break;
case "medium": return { fontSize: '22px'}; break;
case "big": return { fontSize: '32px'}; break;
default: return { fontSize: '12px'}; break;
}
});
The code creates two plugins, which respond on my-custom-gradient and brand-font-size property. So, the following styles
api.add({
body: {
margin: '20px',
fontSize: '14px',
'my-custom-gradient': ['#F00', '#00F'],
p: {
'brand-font-size': 'big'
}
}
});
are compiled to:
body {
margin: 20px;
font-size: 14px;
background: linear-gradient(to bottom, #F00, #00F);
}
body p {
font-size: 32px;
}
Have in mind, that the plugin should always return an object.
The following code
api.add({
body: {
lineHeight: '20px',
'@media all (max-width: 950px)': {
lineHeight: '40px',
color: '#BADA55'
},
'@media all (min-width: 550px)': {
lineHeight: '32px'
},
p: {
margin: '10px',
padding: '4px',
'@media all (max-width: 950px)': {
padding: '12px',
'brand-color': ''
}
}
}
});
is compiled to
body {
line-height: 20px;
}
body p {
margin: 10px;
padding: 4px;
}
@media all (max-width: 950px) {
body {
line-height: 40px;
color: #BADA55;
}
body p {
color: #9fA;
padding: 12px;
}
}
@media all (min-width: 550px) {
body {
line-height: 32px;
}
}
AbsurdJS gives you ability to directly send content to the final CSS. I.e. something which is skipped by the compiler and it is directly concatenated with the processed data.
api
.add({
body: {
marginTop: "20px",
p: {
fontSize: "5px"
}
}
})
.raw('/* ' + comment + ' */')
.add({
a: {
paddingTop: "20px"
}
});
The code above is compiled to
body {
margin-top: 20px;
}
body p {
font-size: 5px;
}
/* AbsurdJS is awesome! */
a {
padding-top: 20px;
}