Permalink
Find file Copy path
74e50ca Dec 27, 2018
1 contributor

Users who have contributed to this file

450 lines (310 sloc) 11 KB

JavaScript API

Access the global JSS instance

There is a global Jss instance which is the default export of the package. You can also create your own local Jss instance.

import jss from 'jss'

Quick setup with preset

import preset from 'jss-preset-default'
import jss from 'jss'

jss.setup(preset())

Create an own JSS instance

jss.create([options])

Use an own instance if the component you build should be reusable within a different project with a probably different JSS setup.

See jss.setup() below for options object description.

import {create} from 'jss'
import camelCase from 'jss-plugin-camel-case'
import somePlugin from 'jss-some-plugin'

const jss = create()
jss.use(camelCase(), somePlugin())
jss.createStyleSheet(/* ... */)

export default jss

Note: jss.create(options) is the same as jss.create().setup(options).

Setup JSS instance

jss.setup(options)

Options:

  • createGenerateId - a function which returns a function which generates unique class names.
  • plugins - an array of functions, will be passed to jss.use.
  • virtual - if true, JSS will use VirtualRenderer.
  • insertionPoint - string value of a DOM comment node which marks the start of sheets or a rendered DOM node. Sheets rendered by this Jss instance are inserted after this point sequentially.

Note: Each jss.setup() call will perform a shallow merge with the old options except for plugins. Passed plugins will get added to the existing plugins.

See setup examples.

Add a plugin

jss.use(plugin)

import global from 'jss-plugin-global'
import jss from 'jss'

jss.use(global())

Create Style Sheet

jss.createStyleSheet([styles], [options])

Classes get always generated by default.

Options:

  • media - media query - attribute of style element.
  • meta - meta-information about this style - attribute of style element, e.g., you could pass component name for easier debugging.
  • link - link jss Rule instances with DOM CSSRule instances so that styles, can be modified dynamically, false by default because it has some performance cost.
  • element - style element otherwise will create one by default.
  • index - 0 by default - determines DOM rendering order, higher number = higher specificity (inserted after).
  • generateId - a function that generates a unique class name.
  • classNamePrefix - a string, which gets added at the beginning of the class name.
import jss from 'jss'

const sheet = jss
  .createStyleSheet(
    {
      // "button" is a rule name; a class gets generated.
      button: {
        width: 100,
        height: 100
      }
    },
    {media: 'print'}
  )
  .attach()

console.log(sheet.classes.button) // button-d4f43g
<style media="print">
  .button-0 {
    width: 100px;
    height: 100px;
  }
</style>

Create a Style Sheet with global selectors

You need to have the jss-plugin-global plugin installed.

Style Sheets registry

SheetsRegistry

When rendering on the server, you will need to get all rendered styles as a CSS string. The SheetsRegistry class allows you to manually aggregate and stringify them. Read more about SSR.

import jss, {SheetsRegistry} from 'jss'

const sheets = new SheetsRegistry()
const sheet = jss.createStyleSheet()
sheets.add(sheet)
sheets.toString() // Returns CSS of all attached Style Sheets together.

Style Sheets Manager

SheetsManager

Counts how many elements use the same Style Sheet and automatically attach or detach it. It also acts similar to a WeakMap, because one can use an object as a key. React-JSS is using a theme object as a key to identify a sheet by a theme.

import jss, {SheetsManager} from 'jss'

const manager = new SheetsManager()
console.log(manager.size) // 0
const sheet = jss.createStyleSheet()
const key = {}

manager.add(key, sheet) // index
console.log(manager.size) // 1
manager.get(key) // sheet

// Will attach the sheet and count refs.
manager.manage(key) // sheet
// Will detach the sheet if refs count is 0.
manager.unmanage(key)

Remove a Style Sheet

jss.removeStyleSheet(sheet)

Detach the Style Sheet and remove it from the registry.

Attach Style Sheet

sheet.attach()

Insert Style Sheet into the render tree. Call it to make your Style Sheet visible for the layout.

Detach Style Sheet

sheet.detach()

Detaching unused Style Sheets will speed up every DOM node insertion and manipulation as the browser will have to do fewer lookups for CSS rules, which could potentially apply to the element.

Attach Style Sheets in a specific order

Sheet 1 has a higher index (priority), and as such will come after sheet 2 in the resulting DOM.

import jss from 'jss'

const sheet1 = jss.createStyleSheet({}, {index: 5, meta: 'sheet-1'}).attach()
const sheet2 = jss.createStyleSheet({}, {index: 1, meta: 'sheet-2'}).attach()
<style data-meta="sheet-2"></style>
<style data-meta="sheet-1"></style>

Add a rule to an existing Style Sheet

sheet.addRule([name], style, [options])

This function will use insertRule API if your Style Sheet is already attached to the DOM. In this case you will not see this CSS Rule in the "Elements" view of the dev tools. You can always verify correct rendering by using the selector on some DOM Node and watch styles applied as well as in the "Styles" inspector.

If you use addRule() before you call attach(), styles will be rendered in one batch using textContent API which will not have the above-described side effect.

Options

  • index - index where the rule should be added, by default, rules get pushed at the end.
  • className - add a rule with a predefined class name.

Add a rule dynamically

import jss from 'jss'

const sheet = jss.createStyleSheet({})
const rule = sheet.addRule({
  padding: 20,
  background: 'blue'
})
document.body.innerHTML = `<button class="${rule.className}">Button</button>`

Delete a rule from an existing Style Sheet

sheet.deleteRule(name)

To remove a rule from the DOM, Style Sheet option link: true should be used. Returns true if the rule gets removed from the DOM.

Get a rule

sheet.getRule(name)

Access a rule within sheet by a name.

import jss from 'jss'

const sheet = jss.createStyleSheet({myButton: {}})
// Using name.
const rule = sheet.getRule('myButton')

Add multiple rules

sheet.addRules(styles)

In case you want to add rules to the sheet separately or even at runtime.

import jss from 'jss'

const sheet = jss.createStyleSheet({})
sheet.addRules({
  myButton: {
    float: 'left'
  },
  something: {
    display: 'none'
  }
})

Update function values

sheet.update(data)

If you use function values, you will want to update them with new data. This method will call all your function values, pass the data param and update the CSS Rule if needed.

import jss from 'jss'

const styles = {
  container: {
    height: 200,
    width: data => data.width
  },
  button: {
    color: data => data.button.color,
    padding: data => data.button.padding
  }
}

const sheet = jss.createStyleSheet(styles, {link: true}).attach()

sheet.update({
  width: 100,
  button: {
    color: 'red',
    padding: 20
  }
})

Create a rule without a Style Sheet

jss.createRule([name], style, [options])

Apply styles directly to the element but still be able to use JSS.

import jss from 'jss'

const rule = jss.createRule({
  padding: 20,
  background: 'blue'
})
import jss from 'jss'

const rule = jss.createRule('@media', {
  button: {
    color: 'red'
  }
})

Apply a rule to an element inline

rule.applyTo(element)

This is equivalent to element.style.background = 'blue' except that you could use a rule from a sheet which is already defined. It uses rule.toJSON() internally, so same limitations are applied. Example.

import jss from 'jss'

const element = document.getElementById('element')
jss
  .createRule({
    background: 'blue'
  })
  .applyTo(element)

Set or get a rule property dynamically

rule.prop(name, [value])

When the link option is true, after Style Sheet is attached, linker saves references to CSSRule instances so that you can set rule properties at any time. Example.

import jss from 'jss'

const sheet = jss.createStyleSheet(
  {
    a: {
      color: 'red'
    }
  },
  {link: true}
)

// Get the color.
console.log(sheet.getRule('a').prop('color')) // red

// Set the color.
sheet.getRule('a').prop('color', 'green')

Convert a rule to JSON

rule.toJSON()

It returns a JSON representation of a rule. Supports only regular rules, no nested, conditionals, keyframes or fallbacks.

The result of toJSON call can be used later to apply styles inline to the element. It is used by rule.applyTo().

Convert to CSS

sheet.toString()

To get a pure CSS string from JSS, e.g. when preprocessing server side.

import jss from 'jss'

const sheet = jss.createStyleSheet({
  button: {
    float: 'left'
  }
})

console.log(sheet.toString())
.button-0 {
  float: left;
}

Generate your class names

createGenerateId

Option createGenerateId allows you to specify a function which returns a class name generator function generateId(rule, sheet). This pattern is used to allow JSS to reset the counter upon factory invocation when needed. For example, it is used in React-JSS to reset the counter on each request for server-side rendering.

By default class names generator uses a simple counter to ensure uniqueness of the class names. It consists of classNamePrefix Style Sheet option + rule name + counter. Note: in production (NODE_ENV=production) it uses just the c + rules counter.

import jss from 'jss'

const createGenerateId = () => {
  let counter = 0

  return (rule, sheet) => `pizza--${rule.key}-${counter++}`
}

jss.setup({createGenerateId})

const sheet = jss.createStyleSheet({
  button: {
    float: 'left'
  }
})

console.log(sheet.toString())
.pizza--button-1 {
  float: left;
}

Extract dynamic styles

getDynamicStyles(styles)

Extracts a styles object with only props that contain function values. Useful when you want to share a static part between different elements and render only the dynamic styles separate for each element.

import {getDynamicStyles} from 'jss'

const dynamicStyles = getDynamicStyles({
  button: {
    fontSize: 12,
    color: data => data.color
  }
})

console.log(dynamicStyles)
// {
//   button: {
//     color: data => data.color
//   }
// }

Plugins

See plugins documentation.