

Show HN: CSS Meta-Language in Javascript - KeithMajhor

This was an attempt to make css more accessible to javascript. It just happened to solve a lot of the same problems as less and sass as a side-effect. I'll start with a few examples and then break out the code and explain it...<p>Here's a generic example:<p><pre><code>    css // Begin CSS

    ( "selector1" )
    ({
        property1: value,
        property2: value,
        // ...
    })

    ( "selector2" )
    ({
        property1: value,
        property2: value,
        // ...
    })

    ; // End CSS
</code></pre>
Some less and sass features (Variables, Mixins, etc.):<p><pre><code>    // Variable
    var text_color = "black";

    // Mixin
    var dim = function( w, h ) {
        return {
            width:  w,
            height: h,
        }
    };

    css // Begin CSS

    ( "div" )( dim( "10px", "10px" ) )
    ({
        color: text_color,
    })

    ( "span" )
    ({
        color: text_color,
    })

    ; // End CSS
</code></pre>
And finally, since it's leveraging javascript this technique can modify styles dynamically (My goal):<p><pre><code>    item_color_input.onsubmit = function( )
    {
        css // Begin CSS

        ( ".item" )
        ({
            background: item_color_input.value,
        })

        ; // End CSS
    }
</code></pre>
Frameworks like jQuery provide similar functionality by acting on the DOM. This can be slow (since it has to execute the selector in javascript) and doesn't affect future elements.<p>The Code: css.js http://keithmajhor.pastebin.com/twCKCcHV<p><pre><code>    // ==============================================
    // File:   css.js
    // Author: Keith Majhor &#60;KeithMajhor@gmail.com&#62;
    // ==============================================
    window.css = function( a )
    {
        var decl = { },
            elem = { },
            rule,
            prop;

        css = function( a )
        {
            if ( typeof( a ) === "string" )
            {
                rule = a;
                if ( !decl[rule] )
                {
                    decl[rule] = { };
                    elem[rule] = document.createElement( "style" );
                    document.head.appendChild( elem[rule] );
                }
            }
            else if ( rule )
            {
                for ( prop in a )
                    decl[rule][prop] = a[prop];

                var temp = rule + "{";
                for ( prop in decl[rule] )
                    temp += prop + ":" + decl[rule][prop] + ";";
                elem[rule].innerHTML = temp + "}";
            }

            return css;
        }

        return css( a );
    }
</code></pre>
All it does is maintain a hash for each selector and update a &#60;style&#62; tag whenever it's modified. As is it's 500 bytes, minified it's below 300.<p>I hope this is useful to someone. If anyone has any insight into why this might be a really stupid thing to do, I'd love to hear it.
======
humblest_ever
This is great. How are you licensing it?

And what do you plan on for the cases where people have disabled JS?

~~~
KeithMajhor
You can use whatever license you want (MIT, BSD, etc.)

This is geared towards applications that wouldn't work without JS anyway. But
you could always degrade gracefully by providing some default css in a
<noscript> tag.

~~~
humblest_ever
That makes perfect sense. I really like that it changes the css for the entire
class. This would have good applications for a mockup website, you could add
elements, alter classes, and add more elements in a consistent manner.

~~~
KeithMajhor
That's sounds a lot like what I had in mind when I wrote it.

------
electrichead
I suppose the trade-off is having a style tag for each selector, which seems
wasteful, and I'm not sure of the effect on performance. Any benchmarks for a
large-sized stylesheet (1000 rules or so)?

~~~
KeithMajhor
Each time a declaration section is added to a selector the contents of the
corresponding tag have to be re-stringified. Having a single tag would require
the entire style sheet to be rebuilt whenever a rule was modified.

------
sharkbrainguy
<http://keithmajhor.pastebin.com/xvgVAKve>

removed the implicit global

~~~
KeithMajhor
It won't work with that. I'm replacing the (implicit) global window.css with a
closure the first time it's invoked. Your modification will cause future css
sections to create their own <style> tags even if the they reference the same
selectors.

Perhaps this is clearer: <http://keithmajhor.pastebin.com/5KA7Ecn0>

~~~
sharkbrainguy
ah, I see I was reading completely wrong

------
revorad
jQuery can act on future elements using the .live() function.

~~~
KeithMajhor
I was referencing $( "selector" ).css({ ... }) specifically.

.live works for events. I suppose you could add an event to modify the style
of each element as it was added... But then that really feeds back into the
previous point which is that it would be slow.

