Dynamic style sheets for web components.
![Gitter](https://badges.gitter.im/Join Chat.svg)
JSS is a very thin layer which compiles JSON structures to CSS.
Why do we need transpilers like sass or stylus when we can use javascript to do the same and much more?
By leveraging namespaces we can solve the cascading problem better than bem and make our components truly reusable and composable.
Access css declarations and values from js without DOM round trip.
Smaller footprint because of code reuse and no vendor specific declarations
Take a look at examples directory.
Syntactic differences compared to CSS
Jss styles are just plain javascript objects. They map 1:1 to css rules, except of those modified by plugins.
{
'.carousel-caption': {
'position': 'absolute',
'z-index': '10',
},
'hr': {
'border': '0',
'border-top': '1px solid #eee'
},
'@media (min-width: 768px)': {
'.modal-dialog': {
'width': '600px',
'margin': '30px auto'
},
'.modal-content': {
'box-shadow': '0 5px 15px rgba(0, 0, 0, .5)'
},
'.modal-sm': {
'width': '300px'
}
}
}
Multiple declarations with identical property names
I recommend to not to use this if you use jss on the client. Instead you should write a function, which makes a test for this feature support and generates just one final declaration.
In case you are using jss as a server side precompiler, you might want to have more than one property with identical name. This is not possible in js, but you can use an array.
{
'.container': {
background: [
'red',
'-moz-linear-gradient(left, red 0%, green 100%)',
'-webkit-linear-gradient(left, red 0%, green 100%)',
'-o-linear-gradient(left, red 0%, green 100%)',
'-ms-linear-gradient(left, red 0%, green 100%)',
'linear-gradient(to right, red 0%, green 100%)'
]
}
}
.container {
background: red;
background: -moz-linear-gradient(left, red 0%, green 100%);
background: -webkit-linear-gradient(left, red 0%, green 100%);
background: -o-linear-gradient(left, red 0%, green 100%);
background: -ms-linear-gradient(left, red 0%, green 100%);
background: linear-gradient(to right, red 0%, green 100%);
}
API
Access the jss namespace
var jss = window.jss
var jss = require('jss')
Create style sheet
jss.createStyleSheet([rules], [named], [options])
Options:
media
style element attributetitle
style element attributetype
style element attributenamed
if true - keys are names, selectors will be generatedlink
link jss Rule
instances with DOM `CSSRule instances so that styles, can be modified dynamically, false by default because it has some performance cost.
var sheet = jss.createStyleSheet({
'.selector': {
width: '100px'
}
}, {media: 'print'}).attach()
<style media="print">
.selector {
width: 100px;
}
</style>
Create namespaced style sheet.
Create a style sheet with namespaced rules. For this set second parameter to true
.
var sheet = jss.createStyleSheet({
myButton: {
width: '100px',
height: '100px'
}
}, true).attach()
console.log(sheet.classes.myButton)
<style>
.jss-0 {
width: 100px;
height: 100px;
}
</style>
Attach style sheet
sheet.attach()
Insert style sheet into the render tree. You need to call it in order to make your style sheet visible for the layout.
Detach style sheet
sheet.detach()
Detaching unsused style sheets will speedup every DOM node insertion and manipulation as the browser will have to do less lookups for css rules potentially to be applied to the element.
Add a rule
sheet.addRule([selector], rule)
Returns an array of rules, because you might have a nested rule in your style.
You might want to add rules dynamically.
var rules = sheet.addRule('.my-button', {
padding: '20px',
background: 'blue'
})
Add rule with generated class name.
var rules = sheet.addRule({
padding: '20px',
background: 'blue'
})
document.body.innerHTML = '<button class="' + rules[0].className + '">Button</button>'
Get a rule.
sheet.getRule(selector)
Access a rule within sheet by selector or name.
var rule = sheet.getRule('.my-button')
var rule = sheet.getRule('myButton')
Add multiple rules.
sheet.addRules(rules)
In case you want to add rules to the sheet separately or even at runtime.
sheet.addRules({
'.my-button': {
float: 'left',
},
'.something': {
display: 'none'
}
})
Create a rule without a style sheet.
jss.createRule([selector], rule)
In order to apply styles directly to the element butt still be able to use jss plugins.
var rule = jss.createRule({
padding: '20px',
background: 'blue'
})
rule.applyTo(element)
Apply a rule to an element inline.
rule.applyTo(element)
This is equivalent to element.style.background = 'blue'
except of that you could use a rule from sheet which is already defined and can apply plugins to it. Example.
jss.createRule({
background: 'blue'
}).applyTo(element)
Set or get a rule property dynamically.
rule.prop(name, [value])
When option link
is true, after stylesheet is attached, linker saves references to CSSRule
instances so that you are able to set rules properties at any time. Example.
var sheet = jss.createStyleSheet({
a: {
color: 'red'
}
}, {link: true})
sheet.getRule('a').prop('color')
sheet.getRule('a').prop('color', 'green')
Register plugin.
jss.use(fn)
Passed function will be invoked with Rule instance. Take a look at plugins like extend
, nested
or vendorPrefixer
.
jss.use(function(rule) {
})
Convert to CSS
sheet.toString()
If you want to get a pure CSS string from jss e.g. for preprocessing jss on the server.
var jss = require('jss')
var sheet = jss.createStyleSheet({
'.my-button': {
float: 'left',
}
})
console.log(sheet.toString())
.my-button {
float: left;
}
Plugins
Things you know from stylus like @extend, nested selectors, vendor prefixer are separate plugins.
Full list of available plugins
Install
npm install jss
bower install jsstyles
Convert CSS to JSS
jss
jss source.css -p > source.jss
Benchmarks
-
How fast would bootstrap css lib render?
I have converted bootstraps css to jss. In bench/bootstrap
folder you will find jss and css files. You need to try more than once to have some average value.
On my machine overhead is about 10-15ms.
-
Rendering jss vs. css (same styles) jsperf bench.
Run tests
Locally
npm i
open test/local.html
From github
Tests
License
MIT