Skip to content

Instantly share code, notes, and snippets.

@envomer
Forked from potch/README.md
Created June 30, 2018 10:27
Show Gist options
  • Save envomer/0b190fc877e3bc5d65b8a555b3e7dd4a to your computer and use it in GitHub Desktop.
Save envomer/0b190fc877e3bc5d65b8a555b3e7dd4a to your computer and use it in GitHub Desktop.
JSON Style Sheets. Because why not.

JSS: JSON Style Sheets

“Wait, what?”

Sometimes you want to include some CSS in a JavaScript file. Maybe it's a standalone widget. A big ol' string is a pain to manage, and won't minify so pretty. Especially if you want your CSS safely namespaced. For example:

.widget {
    background: #abc123;
    width: 100px;
    /* ... */
}
.widget .doodad {
    background: #abc123;
    /* ... */
}
.widget .doodad:hover {
    background: red;
}
/* and so on */

Wouldn't it be neat if you could bundle up that CSS in a slightly more JS-friendly and compact way? And maybe get a hand with all that prefixing business?

“Actually, that doesn't really come up that often.”

But it does come up sometimes, right? JSS to the rescue!

“Fine, I'll bite. How do I write it?”

The JSS for the aforementioned widget would look like the following:

var style = {
    "&": "background: #abc123; width: 100px",
    ".doodad": {
        "&": "background: #abc123",
        "&:hover": "background: red"
    }
};

Next, we pass that object to the jss function with the parameter namespace:

var css = jss(style, '.widget');

Poof! css is the re-constituted style above! That's kind-of nifty. Drop that in a <style> and you're off to the races!

“Okay, that's kind of neat.”

But wait! There's more! Let's say we had some repeated values in the above (like our background color). If we write the JSS to look like this:

var style = {
    "&": "background: {bg}; width: 100px",
    ".doodad": {
        "&": "background: {bg}",
        "&:hover": "background: red"
    }
};

...we can now pass a third optional vars object to the jss function to do basic value replacement! It looks like this:

var css = jss(style, '.widget', { "bg": "#abc123" });

We can actually replace any arbitrary string in the style rules this way:

var style = {
    "&": "{bg}; width: 100px",
    ".doodad": {
        "&": "{bg}",
        "&:hover": "background: red"
    }
};

var css = jss(style, '.widget', { "bg": "background: #abc123" });

“I think this might be useful!”

Did I mention the jss inflater is 355 bytes minified?

“You truly are one of the great men of history.”

Aw, shucks. I do what I can.

No copyright intended.

// JSS - JSON Style Sheets. Use as directed.
function jss(o, namespace, vars) {
// Normalize optional parameters
namespace = namespace || '';
vars = vars || {};
var s = '';
// Regex used for variable interpolation.
var re = /\{([^}]+)\}/g;
for (sel in o) {
if (o.hasOwnProperty(sel)) {
var val = o[sel];
// Split on commas
var split = sel.split(/\s*,\s*/);
for (var i=0; i<split.length; i++) {
// child selector or chained selector?
var sub = split[i];
split[i] = namespace + (sub[0] === '&' ? '' + sub.substr(1) : ' ' + sub);
}
if (typeof val === 'object') {
// Recurse!
s += jss(val, split.join(','), vars);
} else {
// Substitute values from `vars`.
val = val.replace(re, function(_, m) {
return vars[m] || '';
});
// Write selector block
s += split.join(',') + '{' + val + '}';
}
}
}
return s;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment