Write Your CSS with JavaScript

By  on  

Sometimes programming is just using the right tool. This may be a framework, library or as it happens in my case CSS preprocessor. You probably don't realize it, but LESS or SASS have a lot of constraints. I managed to change that by writing my own CSS preprocessor. I stopped writing CSS and moved everything into the JavaScript world. This article is about AbsurdJS: a small Node.js module, which changed my workflow completely.

The Concept

Write your CSS with JavaScript

If you write a lot of CSS you probably use preprocessor. There are two popular - LESS and SASS. Both tools accept something, which looks like CSS, do some magic and export normal, pure CSS. What I did is just to replace the instrument and the input format. I didn't want to invent a new language or syntax, because this is connected with a lot of things like parsing and compiling. Thankfully, Node.js is here and I decided to use it. Also, I had a lot of LESS type projects, which means that I already use Node.js to compile my styles. It was much easier to replace a module instead of adding something completely new.

\

The Input

Write your CSS with JavaScript

I think that the closest thing to the CSS format is JSON -- that's what AbsurdJS accepts. Of course there are some cons of this transformation. You have to put some properties in quotes and of course the values. This needs a little bit more time during the writing, but as you will see below it's worth it.

In the Beginning was ... a JavaScript File

Here is how a simple LESS file looks like:

.main-nav {
    background: #333;
    color: #000;
    font-weight: bold;
    p {
        font-size: 20px;
    }
}

And here is its AbsurdJS equivalent. It's a simple Node.js module:

module.exports = function(api) {
    api.add({
        ".main-nav": {
            background: "#333",
            color: "#000",
            "font-weight": "bold",
            p: {
                "font-size": "20px"
            }
        }
    })
}

You should assign a function to module.exports. It accepts a reference to the API, which has several methods, but the most important one is add. Simply pass a JSON object and it will be converted to CSS.

To compile the less file we need install LESS's compiler via npm install -g less and run

lessc .\css.less > styles.less.css

It's the almost the same with AbsurdJS. Installation is again via node package manager - npm install -g absurd.

absurd -s css.js -o styles.absurd.css

It accepts source and output; the result is the same.

The Truth

You may have really beautiful and nice-looking LESS or SASS files, but what matters is the final compiled CSS. Unfortunately the result is not always the best one.

Combining

Let's get the following example:

.main-nav {
    background: #333;
}
.main-content {
    background: #333;
}

If you pass this to the current preprocessors you will get the same thing in the end. However if you use AbsurdJS like that:

module.exports = function(api) {
    api.add({
        ".main-nav": {
            background: "#333"
        },
        ".main-content": {
            background: "#333"
        }
    })
}

After the compilation you will get

.main-nav, .main-content {
    background: #333;
}

SASS has a feature called placeholders which does the same thing. However, it comes with its own problems. Placeholders can't accept parameters and you should repeat them in every selector which you want to combine. My solution just parses the rules and combine them. Let's get a little bit more complex example:

{
    ".main-nav": {
        background: "#333",
        ".logo": {
            color: "#9f0000",
            margin: 0
        }
    },
    ".main-content": {
        background: "#333"
    },
    section: {
        color: "#9f0000",
        ".box": {
            margin: 0
        }
    }
}

The result is

.main-nav, .main-content {
    background: #333;
}
.main-nav .logo, section {
    color: #9f0000;
}
.main-nav .logo, section .box {
    margin: 0;
}
section .box {
    padding: 10px;
    font-size: 24px;
}

All identical styles are combined into one single definition. I know that the browsers are really fast nowadays and this is not exactly the most important optimization, but it could decrease the file size.

Overwriting

You know that if you have two identical selectors and they contain definition of the same style the second one overwrites the first. The following code passed through LESS/SASS stays the same:

.main-nav {
   font-size: 20px;
}
.main-nav {
   font-size: 30px;
}

However I think that this leaves one more operation for the browser: it has to find out that there is another definition with the same selector and style and compute the correct value. Isn't it better to avoid this, so send that directly:

.main-nav {
    font-size: 30px;
}

AbsurdJS takes care about this and produces only one definition. The input may look like that:

{
    ".main-nav": {
        "font-size": "20px"
    },
    ".main-nav": {
        "font-size": "30px"
    }
}

It also makes your debugging processes easier, because there is no so long chain of overwrites.

Flexibility

Ok, we have mixins, variables, placeholders, functions, but once you start using them to write a little bit more complex things you are stuck. Let's get the mixins. I want to create a mixin, which defines another mixin. That's currently not possible in LESS, because you can't use a mixin defined in another mixin. I guess it's a scope problem. SASS has some imperfections regarding the interpolation of the variables. Overall, it's hard to produce good architecture with less code. You have to write a lot and even then, you can't really achieve your goals. The main reason behind these problems is the fact that both, LESS and SASS, have to deal with new syntax, new rules and basically invent a new compiler. However, if we use JavaScript we don't have to think about these issues.

AbsurdJS has something called storage. It could save whatever you want and make it available in other files. For example:

// B.js
module.exports = function(api) {
    api.storage("theme", function(type) {
        switch(type) {
            case "dark": return { color: "#333", "font-size": "20px" }; break;
            case "light": return { color: "#FFF", "font-size": "22px" }; break;
            default: return { color: "#999", "font-size": "18px" };
        }
    });
}

// A.js
module.exports = function(api) {
    api
    .import(__dirname + "/B.js")
    .add({
        ".main-nav": [
            {
                "font-size": "16px",
                padding: 0,
                margin: 0
            },
            api.storage("theme")("dark")
        ]
    });
}

At the end you get:

.main-nav {
    color: #333;
    font-size: 20px;
    padding: 0;
    margin: 0;
}

Using the storage may be a little bit ugly. I mean, you need an array assigned to the selector and then call api.storage. I used that for a while, but later decided to implement something much nicer. It's a feature which I always wanted - the ability to create your own properties and save tons lines. For example, let's create a new property called theme and process its value.

// B.js - definition of the plugin 
module.exports = function(api) {
    api.plugin('theme', function(api, type) {
        switch(type) {
            case "dark": return { color: "#333", "font-size": "20px" }; break;
            case "light": return { color: "#FFF", "font-size": "22px" }; break;
            default: return { color: "#999", "font-size": "18px" };
        }
    });
}

// A.js - its usage
module.exports = function(api) {
    api
    .import(__dirname + "/B.js")
    .add({
        ".header": {
            theme: "light"
        }
    })
}

Again, the result is similar:

.header {
    color: #FFF;
    font-size: 22px;
}

Conclusion

AbsurdJS is something really simple, but avoids the usage of popular CSS preprocessors. It still has the same feature like nested selectors, media queries bubbling, file import, variables, mixins and so one. However, it brings more flexibility, because it is a pure JavaScript. It has even a GruntJS support. I'd like to get some feedback and will be happy if you take a part in the project. The official repository is available here https://github.com/krasimir/absurd.

Krasimir Tsonev

About Krasimir Tsonev

Krasimir Tsonev is a coder with over ten years of experience in web development. With a strong focus on quality and usability, he is interested in delivering cutting edge applications. Currently, with the rise of the mobile development, Krasimir is enthusiastic to work on responsive applications targeted to various devices. Living and working in Bulgaria, he graduated at the Technical University of Varna with a bachelor and master degree in computer science. If you'd like to stay up to date on his activities, refer to his blog or follow him on Twitter.

Recent Features

Incredible Demos

  • By
    Facebook Open Graph META Tags

    It's no secret that Facebook has become a major traffic driver for all types of websites.  Nowadays even large corporations steer consumers toward their Facebook pages instead of the corporate websites directly.  And of course there are Facebook "Like" and "Recommend" widgets on every website.  One...

  • By
    Using Opacity to Show Focus with MooTools

    I'm a huge fan of using subtle effects like link nudging (jQuery, MooTools) to enhance the user experience and increase the perceived dynamism of my websites. Trust me -- a lot of little things are what take websites to the next level.

Discussion

  1. Nice. But Yandex created BEM few years ago with the same functionality.

  2. AbsurdJS is more like a CSS preprocessor. BEM is a methodology, a concept like OOCSS or Atomic design.

    • Kasimir, BEM also provides a JavaScript solution for coding independent components. The idea is similar to what you present in this article. The freshest piece of info about it is the tutorial I am working on right now. Here it is https://github.com/varya/bem-js-tutorial Please, check it out, you might be interested.
      Once been finished this tutorial will be a part of bem.info web site. Although it already has one older article presenting this JavaScript solution http://bem.info/articles/bem-js-main-terms/

      I personally like developing web components as individuals, when we describe the component states in JavaScript and CSS serves for rendering this states in a proper way. Your solution looks pretty similar in its concept and that is great! Nice to see the ideas of modular web extending the world :-)

    • Varvara Stepanova

      Krasimir, I wrote here about BEM JavaScript solution twice but every time my comment disappears after a few minutes. Can it be because I try to provide a link?
      How can I write you the staff?

  3. David Chase

    This is definitely something I would like to take for a spin!

    Thank you :)

  4. Why would you ever want to use this over Stylus, LESS, SASS, or the like?

  5. @Nico: because with AbsurdJS you have the flexibility of JavaScript language. You may create complex architectures. With Stylus, LESS or SASS you are bounded to specific syntax and functionalities. As I said in the article you can’t really create/use a mixin which generates other mixins. You can’t also define your own properties. It just fits better in my workflow and projects.

    • What do you mean you can’t? with Stylus you can do all of that, and you don’t get any of the typing overhead of using JavaScript.

    • Matias Lescano

      I also like the idea of not adding another language/preprocessor to the mix. i.e. If you have an app on node, with Absurd you still only have JS/CSS.

  6. Capaj

    I would consider it only if I would have the same luxury of autocomplete as I have with LESS/CSS in Webstorm. I just hope all preprocessors will be obsolete when CSS4 hits mainstream.

  7. The more and more I read and think about css frameworks, preprocessors, etc. the more I come to the conclusion, that a lot of it is not productive. I mean css is such an easy and straight forward language. You can write some rules, use them, throw them away, write new ones. Simple, fast, productive.
    The farther you remove yourself from core css writing, the more time you spend on making decisions, which framework to use and how, learning the framework you have chosen, or even writing your own framework and preprocessor.
    You are actually not producing or contributing to a product.
    And as you mentioned, your css output might me shorter and cleaner, but who cares, if you didn’t deploy a feature, milestone, product to your customers? Don’t get me wrong, frontend performance is huge, however there are better stones to turn, if you look at time invested.
    Still, I enjoyed your post and hope you are more productive using absurdjs. cheers :)

    • I totally agree with you. Every time I created styles with Less, it usually took me more time to change something. Using mixins sometimes make code less flexible, when I have to change one thing without changing another. I end up overwriting styles.
      One case when those preprocessors might be useful, when you create something that will have many colour themes, but the same structure.
      In other cases CSS is simple enough. And text editors usually help us to write code quite fast.

    • Gus

      I’m surprised by the number of people saying that there is no use at all for CSS preprocessors or CSS in JS. I make mostly big, complex and highly interactive web apps and the advantages to preprocessors and dynamic CSS are obvious. Nested rules vs. repetitive child selectors is a no-brainer for starters.

      Storing all resources (JS, HTML templates and CSS) as JavaScript modules also seems like it could have benefits, as it allows you to use the same module system for all dependenciesm instead of having to to CSS and import HTML templates separately.

      I guess it depends on the type of things you use CSS for. On a primarily content-based site I would tend to agree with keeping CSS simple and separate from everything else, but if you have a lot of rich, self-contained, nested, interactive widgets then it makes sense to keep them isolated and all their resources bundled together, otherwise you end up having to manually load in CSS and templates for all the components you use on a page and maintain that separately, instead of just having the module system take care of it.

  8. Adam

    I like the idea of generating CSS through code (and JS is as good as any). In complex situations, being able to use computation can simplify things greatly. A couple of problems come to mind, however.

    First. You’re right that having “background-color”: “#fff333” next to width: “32px” is odd. So why not simply use the JavaScript notations? backgroundColor, fontSize and so on. The script to convert them to their proper values is actually minimal.

    Second. The terminology “plugin” could probably be “property” because that’s what you are defining. The fact that you get some number of CSS properties (or even more rules) is immaterial. It also means that all the “native” css properties are written as “plugins” and it would be trivial to have them generate browser prefixes and values as necessary.

    Third. You need to account for multiple values. Backgrounds, for example can take multiple values. However, if were to pass them all in as a string, you will end up with a lot of boiler plate value.split(‘,’) and so on (and it doesn’t work if you have gradients). Instead its probably ok to have myProperty: [‘value number 1’, ‘value number 2’]. In the inner workings, you simply call the plugin using apply() so that I get an number of arguments, rather than a single argument that has an array value one time and a single value the next. This allows me to simply iterate through all the items in arguments regardless of the number of values passed in.

    Fourth. A utility function to break a compound value into its parts (like background) would be useful. A simple string split on whitespace will not work because sometimes the whitespace is important. a simple split on whitespace could fail, for example, if the value for background included a gradient.

    Such a function could also, if you were ambitious, look for number values, color values and so on and return objects for those (so when you get a color object, you can trivially call .darken(0.54) or some other color function on it).

    Fifth. The combination of selectors without author intervention will lead to problems. The problem is that in CSS order matters. So changing the order changes the meaning of the CSS. Its not an innocuous change. You could argue that one aught to always write code that can withstand reordering. Unfortunately, that’s very difficult to do. It basically forces you to never have classes that are used on the same element at the same time that define the same properties. Colors are easy to do (Bootstrap3 eliminated all the default colors from things like buttons and labels probably for a reason like this) but for other things it becomes problematic.

    Consider the following:

    {
     '.subtitle': { 'font-size': '23px'},
     '.btn' : { 'font-size': '16px'},
     '.btn-lrg' : { 'font-size': '23px'},
    '.prose': : { 'font-size': '16px'}
    }
    

    If I understand you correctly this should result in:

     .subtitle, .btn-large: { font-size: 23px},
     .btn, .prose: { font-size: 16px},
    

    Now if we expect to see then the font size will always be 16px, not 23px as the author intended. This becomes complicated when in one place you define a shortcut property (say background) and in another you define a specific property like background-color. If your specific property gets reordered before the shortcut, the short cut always wins, even if all it did was background: url(/my-pic.png); because people always forget that omitting parts of the shortcut is explicitly defining the default. And that’s going to be a PITA to debug.

  9. Samuel Allen

    I would submit that Stylus is a JS based pre-processor that can do most, if not all of what you are achieving with AbsurdJS (though it defers to more CSSy syntax instead of JSON), and is also a Node module which allows for all kinds of advanced scripting and middleware. Not saying there isn’t room for something else, just that you shouldn’t lump Stylus in with SASS and LESS as ‘not being a JS solution’.

  10. @Adam: good points. A lot of think to think about. Thanks.
    @Samuel Allen: I agree with you

  11. Cool! Thanks for sharing!

  12. I always wondered why should we have to compile CSS? I mean, it’s supported natively and compiling it adds a useless step in our development workflow.
    Not for me I’m afraid. I use PHP and JS for a reason, because scripts are cool and fast enough for common projects. Compiling takes time I don’t have, and I do write a lot of CSS.

  13. @Simonced: compiling is necessary for serving only one minified css file. I believe that this is the core concept of the preprocessors. Beside that, you save a lot of time because you group properties in blocks and reuse them. The variables are also very useful because you make changes on only one place. Yes, I agree that compilation takes time and it’s one more thing in your ecosystem, but it’s worth it. In my case was just one more module in my Gruntjs setup.

  14. @Varya: I saw your post. https://github.com/varya/bem-js-tutorial looks really interesting. I’ll try to find some time next week to take a look.

  15. Thanks for the write up.

    While I appreciate the attempt of what it’s trying to do, its just a step too far away from EXPRESSIVELY writing CSS or SASS or LESS etc. I have to think about the architecture I’m working against before I even start writing my code. With enough practice I’m sure it wouldn’t be too painful, but even writing the css itself is verbose with quoting the CSS rule.

    I love pure SASS (not SCSS).
    That plus Jade + Coffeescript = heaven

  16. @Jeff: yep, quoting the properties is really bad idea. I’m considering changing that. I’ll follow the advice of Adam and will make shortcuts for every css property.

  17. Hi guys, there is no need to quote the CSS properties anymore (https://github.com/krasimir/absurd/commit/6a3ad356464e12b06f6a82753ba670f414553468#L1L4). AbsurdJS converts every uppercase letter to a dash followed by the lowercase version of the letter. For example: WebkitTransform -> -webkit-transformOf course this is valid only for the CSS properties.

  18. for more programming tutorial visit http://www.9code.in

  19. Troland

    There is a problem that what about the abbreviation when you type in js.I mean howto quickly type the css abbreviation when you edit the css in a js file?

  20. @Troland: can you please give an example.

  21. Zoomclub

    This is great!

    As we know the JSON format dovetails with JS and doing what your doing is in the spirit of NoSQL DB’s like Mongo, where the JSON format maps much better to the actual code than SQL does/did.

    Also, now that we are starting to see the Path Object implemented for the Canvas element AbsurdJS might be the handy way to provide CSS like styling values to the Path Contexts, very rad indeed!

    I have struggled with this whole CSS file format and pre-processor issue because I have architected so much of my app into JSON configurations. I’m certainly in favour of using a unifying file format like JSON for as much as possible. This also allows me to lockdown JSON style and layout in Firebase with their very nice security rules.

    Lets keep going with this… I write my “CSS” in JSON now, then I store the JSON on Firebase, then I load JSON from Firebase with its refURLs into the fast local cache Firebase provides, then I use AdsurdJS at runtime to apply specific cached JSON documents to app widgets or Path Objects, etc. Is there any reason this would not work?

    Other than that my choice in pre-processors is Stylus, however I want to use JSON and JS as the most universal solution possible.

  22. as a security researcher by reading the title I was shocked.
    there are plugins like no script and more that allow users to block javascript to sites that
    they don’t know. so if you rely on javascript and you have a new user, they may never come
    back to site. It’s best to to use javascript when needed.
    also if you can do the same thing with php or other sever side scripting, it’s better to do it
    that way

  23. @Zoomclub: everything sounds awesome. Please keep me informed how are the things working. If something goes wrong email me or post an issue to the girhub repo. I’ll be glad to help. I believe that the only one way to improve the module is to using it. Your use case sounds like the most complex so far and it is interesting for me to see how AbsurdJS will react.
    @soroush: AbsurdJS is a Nodejs module. It is not meant to be used client-side. It’s working at the back-end side of the things. I also recommend using it only in development mode and serve the compiled CSS in production.

  24. @Zoomclub: You my find the latest released helpful. AbsurdJS now supports importing of pure JSON. I.e. you don’t need to write JavaScript. You may send directly your .json files. https://github.com/krasimir/absurd/commit/931151acdd13d0eb55801d5ebe33245c281380c0

  25. Zoomclub

    @Krasimir: I’ll need AbsurdJS to work on the client-side for sure. Most of my use of JSON configurations is on the client where I let users hotswap them to change the way the app behaves, looks, etc. Your solution is to good for only Node.js, we Hybrid App guys want cool stuff too :-)

  26. @Zoomclub: using AbsurdJS in the client side sounds absurdly :) of course it makes sense for you and I’m sure that there is cases where you need something like this.

  27. Zoomclub

    @Krasimir: I’m not sure your saying that it is possible or not? Please do let me know. For example, something like AsyncJS runs in Node or on the client. My server side is essentially Firebase, which I use with its client-side API. Then from the client-side local cache I would use a specific JSON configuration to apply its data to a given function. Since my app must dynamically respond to user events doing this on the client is required.

    If it is not possible to use AbsurdJS on the client then CSS stays as it was, fit for its one task. Using AbsurdJS I am hoping to break that limit and extend styling to more than just HTML, to the Canvas element and beyond is where I’m looking at. Otherwise, AbsurdJS is not to much more than another pre-processor for HTML, caught up in an argument over format with other pre-processors and limiting its potential, right?

  28. @Zoomclub: I already started thinking about porting AbsurdJS for the client-side. It will be possible very soon. What will do there is the same. Accept javascript or json code, compile it to CSS and append it to the DOM. However, I think that such approach is kinda wrong, because the CSS should be one of the first things delivered to the users. Waiting to get the html and javascript, compile the CSS and then display something sounds like a bad thing. Anyway, I’m not sure exactly how you are going to use it.

  29. Zoomclub

    @Krasimir: The port to client-side is wonderful news because I see AbsurdJS as both a solution for HTML and also the Canvas.

    For HTML, In modern apps built with frameworks like AngularJS the use of HTML partials is becoming mainstream. In my app I would have these partials already downloaded to the client-side (also as keyed values in a JSON file). I would then want to generate CSS on-the-fly from values that might have been adjusted by a user and then apply that to the HTML partials, all without a trip back to a server.

    For the Canvas (which can currently not be styled by CSS), the JSON files managed by AdsurdJS would be directly applied as layout and style values for anything rendered by the 2D context of the Canvas. You could say that the JSON (without conversion to CSS) would then act as a memento or snapshot of the state of the 2D context. Such a snapshot could be used to set the 2D context differently and according to the need of each possible thing rendered on the Canvas.

    One way to use this is by fetching a given SVG glyph from a pre-loaded webfont and then applying a JSON snaphot configuration to the 2D context and then on step three drawing the glyph (which could also be scaled, etc by the snapshot too) to the Canvas.

    In this way AbsurdJS would allow the JSON to act as a new type/form of CSS for the Canvas. And with the extra step you already do, the JSON can also be converted to true CSS for use on a HTML or a SVG partial. The popular D3.js library is an example of something that produces SVG partials, in most cases these partials are produced dynamically right on the client.

  30. Artur

    JavaScript will rule us all.

    AbsurdJS joined with DOMO.js can transform the way we all construct code in the web right now.

  31. Zoomclub

    Keeping things within the JSON format is likely best, no need to invent yet more non-standard formats, JSON is what gives the edge and the push for something like AbsurdJS to thrive.

  32. By the way, AbsurdJS now supports and pure CSS. So, you may define new properties as plugins and still write the good old CSS -> https://github.com/krasimir/absurd#css

  33. Zama Khan Mohammed

    Its a great idea, but I find it not useful by enterprises and big companies, because Accessibility is a huge topic for them. And if the website doesn’t works without javascript its called unaccessable. Suppose they implement this! what a mess this would be for them, i.e. they will not only not get javascript but also css will be absent for them :(

  34. Zoomclub

    All roads have been leading to JS, eventually there will not be an off switch ;-)

  35. Frédéric Camblor

    What about code completion ?

    With CSS, we benefit from tooling, providing code completion, color sample, etc…
    Writing CSS in JS won’t allow to re-use such tooling, ever.

  36. @Zama Khan Mohammed: the idea behind AbsurdJS is to be used as a preprocessor. I.e. it’s a server-side technology. There is an idea (which will be probably realized) to move the same preprocessor to the client-side, but that’s not the main thing here.

    @Frédéric Camblor: Yes, probably your IDE will not have auto completion, but it’s worth it. I mean it could decrease the writing of CSS a lot.

  37. Just commenting to say: THIS IS ABSURD!!! ;)

  38. Hi guys, AbsurdJS is now ported for client-side usage. I made a brand new web site containing the documentation and also a very helpful try-it script. So, now you can play with AbsurdJS directly into the browser –> http://krasimir.github.io/absurd/

  39. This is Paul Krill, a reporter for InfoWorld.com. Would the developer of Absurd.js please contact me at the email address I’ve provided?

  40. Hi Paul,

    please contact me at:
    info (@) krasimirtsonev.com

  41. Håkan Save Hansson

    Hi Krasimir,

    Interesting. I use Visual Studio/C#/MVC a lot so I’ve done something similar, just using C# (and Razor) as the programming language. I wasn’t so keen on learning yet another programming language/syntax just to edit CSS in a productive way, and I didn’t want to force my colleagues to learn the same preprocessor as I’ve chosen just to maintain my code. I thought, wouldn’t it be great if we all just could use C# as we do in the rest of our code base. In C# we can basically do anything any preprocessor can, and more. And with appropriate helpers, methods etc we can get really productive.

    As you probably know Razor is a technique where you easily can mix HTML and C# and when requested from the server it’s delivered as plain HTML. My simple solution is to just use it on CSS files as well. I mix any C# code (variables, methods, helpers…) with any plain vanilla CSS and get plain CSS.

    Ok, there are some drawbacks, among them the lack of auto complete and syntax highlighting in the IDE, but there are also many advantages.

  42. @Håkan Save Hansson: I’m glad to see that there is something similar in C#.

  43. Hey guys, I wrote (finally) a more descriptive article about AbsurdJS – AbsurdJS fundamentals http://krasimirtsonev.com/blog/article/AbsurdJS-fundamentals

  44. SJ

    @Krasimir: I’ve just come across this project. I’ve got my own JavaScript CSS preprocessor “ruleSet” that I’ve been using on and off for a few years. I wrote it for many of the reasons you did. A few things I’ve learned while writing mine that may help:

    1 – DO NOT mess with the author’s rule order e.g. your combining

    api.add({
    “.main-nav”: {
    background: “lime”
    },
    “.main-area”: {
    background: “orange”
    },
    “.main-content”: {
    background: “lime”
    }
    })

    <div class=”main-content main-area”>
    This should be lime
    </div>

    2 – DO NOT mess with the author’s rules e.g. Your extend feature example on your blog creates an additional rule for .button meaning .cancel and .ok don’t fully extend .button, they are missing “color: #000;”. Also this feature beaks rule #1 above depending on what properties are passed. This could get pretty complicated and hard to debug.

    When writing mine I opted to use Arrays with objects e.g.

    rs([
    ‘.myClass’, {
    display: none,
    visibility: hidden
    },
    ‘.myClass2’, {
    paddingRight: 10,
    width: 940
    },
    ‘.myClass3’, {
    marginBottom: 0
    },

    …lots of rules later…

    ‘.myClass’, {
    fontSize: 12
    }
    ])

    If you notice the two .myClass rules, this works fine with Arrays, however you can’t do that with an Object literal. It would error/overwrite the previous rule. Have you found this to be an issue when writing/maintaining large stylesheets?

    Thanks for sharing

  45. SJ

    Why did you steal my pre tags Mr Comments?!

  46. Johan Chouquet

    Hi,

    Not sure if it’s a bug or not. I tried to do this, with 2.3 version of bootstrap, on an existing project :

    @import "bootstrap-responsive.css";
    @import "bootstrap.css";
    @import "text.css";
    /* Some more CSS */
    

    For that, I wrote :

    var cwd = __dirname,
    	    cwdArr = __dirname.split("\\"),
    	    rootCwd = cwdArr.slice(0, cwdArr.length-2).join("/");
        api.import([
            rootCwd + '/css/bootstrap-responsive.css',
            rootCwd + '/css/bootstrap.css',
            rootCwd + '/css/text.css'
        ]);
       /* more code here, well generated to css*/
    

    But in the end, I end up with lines that were reordered. It’s not written :

    @import "bootstrap-responsive.css";
    @import "bootstrap.css";
    @import "text.css";
    
    ...
    

    It preprocessed all the files to be imported, it reordered all lines, and in the end, it’s not making working fine.

    Is there a way to tell Absurd :
    1. preprocess a part of js code to generate css code, and when importing, just write the “@import” directives, and so, not preprocess them ?

    Thanks by advance.

  47. YoYo

    I like the concept, i will test absurdJs in my small project :)

  48. Absurd that people can’t program in JavaScript without a plugin…

  49. Matthew Felgate

    This project is awesome! It’s what I’ve been after. Sass (and LESS) were improvements on CSS but people are now beginning to hit the limits of what they can achieve (lookup Ben Frain’s article Breaking up with Sass). Writing CSS in JavaScript is the future. I look forward to investing this in my Gulp workflow with a BEM/OOCSS methodology to make sure that only CSS that is actually needed is delivered to the browser and there are no over-written CSS rules on any elements.

    Should I rewrite a CSS reset in AbsurdJS?

  50. Hy!

    I’ve enjoyed your way to write CSS in js but if you really want to build big application you need more than just that. Because of that I’ve created smart-css, please take a look at this lib: https://github.com/hackhat/smart-css

    I will leave you here a quick example to understand contexts and how you can name freely your components’ classes without collision with other parts of your app.

    
        // In componentA.js
        // Creates a new namespace/context with the css variable where you 
        // add the componentA's styles.
        var SmartCSS = require('smart-css');
        var css      = new SmartCSS();
        var React    = require('react');
        // You can name a style without worring about other
        // components because you are adding all the styles
        // to the componentA only.
        css.setClass('.root', {
            background: 'red'
        })
        css.setClass('.root:hover', {
            background: 'green'
        })
    
        // Your component render method will look like this:
        React.createClass({
            render: function(){
                return React.DOM.div({
                    // This will return a string with the classes that you set
                    // true.
                    className : css.getClass('root')
                })
            }
        });
    
        // In componentB.js
        // Creates a new context, only for componentB.
        var SmartCSS = require('smart-css');
        var css      = new SmartCSS();
        var React    = require('react');
        // Notice how we used the exact class name as componentA's.
        // This is the power of namespaces, you can keep the name
        // you want without worrying about conflicts with other
        // classes you defined.
        css.setClass('.root', {
            background: 'yellow'
        })
        css.setClass('.colorBlue', {
            color: 'blue'
        })
        // Here you can use pure css, so when the element with the 
        // root class is hovered the element with class link
        // will have the color set to green.
        css.setClass('.root:hover .link', {
            color: 'green'
        })
        React.createClass({
            render: function(){
                return React.DOM.li({
                    className : css.getClasses({
                        root      : true,
                        colorBlue : true,
                    })
                },
                    React.DOM.a({
                        className: css.getClass('link')
                    })
                )
            }
        });
        // Then apply all the styles, only after this command is ran
        // your styles are added to the DOM.
        SmartCSS.injectStyles();
    
  51. @HackHat that’s interesting but it looks like it is bound to React. What if I use other framework or write vanilla JavaScript.

  52. Hy, Krasimir!

    Is not bound to React, you can use without react. It just stores the css and returns you a string with the class names. After that you can use the class names in a react component or a jquery div. It’s up to you how to use it, but works very well with React architecture.

  53. I feel like combining this lib with YAML syntax could bring all kinds of sexy readability improvements!

  54. Philipp

    That is really cool but if I understood all your previews correctly I have to say: Sass can do that. Except of the optimized compiling but normally you should organize yourself good enough to write it that clear. Nobody writes …

    .box {
    background-color: black;
    }
    // some code
    .box2 {
    background-color: black;
    }
    

    In case you didnt concept your design before you should know for which usages you use these containers.

    And sass can storage code, too. Just use the if.
    For example …

    .textversion {
      @if 5 < 3 {
        color: red;
      }
      @if 1 + 1 == 2 {
        color: blue;
      }
    }
    

    If I misunderstood some parts of AbsurdJS just tell me. =)

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!