Find file History
Latest commit cab876d Nov 22, 2016 @krasimir Version updated

README.md

CSSX - CSS in JavaScript

Generate and/or apply CSS with JavaScript.


Download

(For source maps check here)


API


How it works

CSSX is a tiny library that provides a JavaScript API for defining CSS styles. We create a stylesheet and register rules same as we do with the regular CSS files. The library generates valid CSS and injects it into head of the page as a <style> tag. Every change in the stylesheet afterwards is translated into a change in the same <style> tag.

Why is this useful?. Well, JavaScript is a rich language and it gives us more flexibility. There are parts of our applications that require different styles. In such cases we normally use different CSS classes. We add or remove them based on conditional logic. So we have to amend two different parts of our codebase - our CSS and our JavaScript. For example:

var updateStyles = function (size) {
  var stylesheet = cssx('my-styles');
  var body = stylesheet.add({ body: { 'font-size': size + 'px' } });

  body.descendant({ h1: { 'font-size': '2em' } });
  body.descendant({ small: { 'font-size': '0.8em' } });
}

updateStyles(18);

/* results in the following <style> tag:

<style id="my-styles" type="text/css">
body {
  font-size: 18px;
}
body h1 {
  font-size: 2em;
}
body small {
  font-size: 0.8em;
}
</style>

*/

Nota bene! CSSX is not meant to be used for all the styles in our pages. Of course that we need a basic styles for typography, layout, coloring etc. It's purpose is to make the dynamic parts of our CSS more flexible and easy to control.


Simple usage

<script src="cssx.min.js"></script>
<script>

  var updateStyles = function (size) {
    var stylesheet = cssx('my-styles');
    var body = stylesheet.add({ body: { 'font-size': size + 'px' } });

    body.descendant({ h1: { 'font-size': '2em' } });
    body.descendant({ small: { 'font-size': '0.8em' } });
  }

  updateStyles(18);
</script>

A demo JSBin here http://jsbin.com/memera/edit?js,output.


Installation

Drop cssx.min.js on your page or run npm i cssx in node.


API


Top level API

cssx(<id>)

  • id - an unique ID of your stylesheet. It's an optional parameter but we recommend setting it.

Creates a stylesheet object which represents a single <style> tag.

cssx.clear()

It removes all added rules from all stylesheets.

cssx.plugins(<array>)

Accepts array of functions. More about plugins here.

cssx.getStylesheets()

Returns an array with all the CSSX stylesheets.

cssx.getCSS()

Returns the CSS generated by all the stylesheets.

cssx.domChanges(<boolean>)

  • boolean - if set to false the library is not performing any DOM manipulations. Or in other words, it's NOT creating/updating a <style> tag.

cssx.minify(<boolean>)

  • boolean - if set to false the generated CSS is NOT minified.

cssx.nextTick(<boolean>)

  • boolean - CSSX library applies the CSS automatically by editing the content of a <style> tag. There is a mechanism that applies multiple changes at once. It's similar to what requestAnimationFrame is doing. It's not recommended setting it to false.

Stylesheet API

<stylesheet>.add(<styles object>)

  • styles object - JSON representation of your CSS styles

It returns a rule object that represents a single CSS rule. If we pass an object with more then one rule then it returns an array of CSS rules. For example:

var sheet = cssx();
var header = sheet.add({
  '.header': { margin: 0 }
});

header.descendant({
  h1: { 'font-size': '20px' }
});

/*
.header {
  margin: 0;
}
.header h1 {
  font-size: 20px;
}
*/

<stylesheet>.update(<styles object>)

  • <styles object> - JSON representation of your CSS styles

That's basically an alias of the above .add method. Both methods first check if the rules exists and if yes then internally calls the update method of the CSSX rule object.

Let's say that we have the following stylesheet:

var sheet = cssx();
sheet.add({
  body: {
    margin: 0,
    padding: 0
  },
  'body p': {
    'font-size': '20px'
  }
});

sheet.update({
  'body p': { 'font-size': '1em' }
});

The result will be:

body {
  margin: 0;
  padding: 0;
}
body p {
  font-size: 1em;
}

<stylesheet>.define(<prop name>, <func>)

  • prop name - string defining the custom property
  • func - function that receives the value of the property and returns a new object containing valid CSS properties.

This API is about creating custom properties. For example:

var sheet = cssx();
sheet.define('button', function (color) {
  return {
    'color': color,
    'border': 'solid 2px ' + color,
    'display': 'block',
    'padding-left': '1em'
  }
});

sheet.add({
  'section > a': {
    button: '#00FF00'
  }
});

/* produces
section > a {
  color: #00FF00;
  border: solid 2px #00FF00;
  display: block;
  padding-left: 1em;
}
*/

<stylesheet>.id()

Surprisingly, it returns the id of the stylesheet.

<stylesheet>.rules()

An array of all registered rules in a raw format.

<stylesheet>.compile()

Traverses the added rules and transforms them to CSS. At the end applies the result to the DOM. You DON'T have to call this function. It's automatically run by the library.

<stylesheet>.compileImmediate()

When nextTick is set to true (which is by default) calling compile does not update the CSS on the page immediate. It happens in the next tick. This function is helpful if we want to see the result right after the change.

<stylesheet>.clear() or <stylesheet>.destroy()

It clears the registered styles.

<stylesheet>.getCSS()

Returns the CSS based on the added rules. Under the hood calls compileImmediate.

<stylesheet>.scope(<selector>)

All the selectors inside the stylesheet are prefixed with the given <selector>.

var sheet = cssx();
sheet.scope('#component');
sheet.add({
  'p': {
    'font-size': '10px'
  },
  a: {
    margin: '10px'
  }
});

/* produces
#component p {
  font-size: 10px;
}
#component a {
  margin: 10px;
}
*/

Rule API

<rule>.descendant(<styles object>) or <rule>.d(<styles object>)

  • styles object - JSON representation of your CSS styles

Returns a rule object that represents a single CSS rule. It calls <stylesheet>.add method internally.

<rule>.nested(<styles object>) or <rule>.n(<styles object>)

  • styles object - JSON representation of your CSS styles

Returns a rule object that represents a single CSS rule. It calls <stylesheet>.add method internally..

This method produces nested rules (like media queries or @keyframes definitions)

var stylesheet = cssx();
var media = stylesheet.add({ '@media screen and (min-width: 200px)': {} });
media.nested({ p: { margin: '10px' } });

/* It produces the following CSS
@media screen and (min-width: 200px) {
  p {
    margin: 10px;
  }
}
*/

In theory it could be used for producing nested rules which doesn't make any sense right now because they are not supported by the browsers. It may be useful though for generating SASS or LESS.

var stylesheet = cssx();
var body = stylesheet.add({ 'body': { 'font-size': '20px' } });
body.nested({ 'p': { margin: '10px' } });

/* It produces the following CSS
body {
  font-size: 20px;
  p {
    margin: 10px;
  }
}
*/

<rule>.update(<properties>)

  • properties - JSON representation of your CSS properties

Where to go from here