# CSS in JS

<p class="description">You can leverage our styling solution, even if you are not using our components.</p>

Material-UI aims to provide strong foundations for building dynamic UIs.
For the sake of simplicity, **we expose our styling solution to users**.
You can use it, but you don't have to. This styling solution is [interoperable with](/guides/interoperability/) all the other major solutions.

## Material-UI's styling solution

In previous versions, Material-UI has used LESS, then a custom inline-style solution to write the style of the
components, but these approaches have proven to be limited. Most recently, we have [moved toward](https://github.com/oliviertassinari/a-journey-toward-better-style)
a *CSS-in-JS* solution. It **unlocks many great features** (theme nesting, dynamic styles, self-support, etc.).
We think that it's the future:
- [A Unified Styling Language](https://medium.com/seek-blog/a-unified-styling-language-d0c208de2660)
- [The future of component-based styling](https://medium.freecodecamp.org/css-in-javascript-the-future-of-component-based-styling-70b161a79a32)
- [Convert SCSS (Sass) to CSS-in-JS](https://egghead.io/courses/convert-scss-sass-to-css-in-js)

So, you may have noticed in the demos what *CSS-in-JS* looks like.
We use the higher-order component created by [`withStyles`](#api)
to inject an array of styles into the DOM as CSS, using JSS. Here's an example:

{{"demo": "pages/customization/css-in-js/CssInJs.js"}}

## JSS

Material-UI's styling solution uses [JSS](https://github.com/cssinjs/jss) at its core.
It's a [high performance](https://github.com/cssinjs/jss/blob/master/docs/performance.md) JS to CSS compiler which works at runtime and server-side.
It is about 8 kB (minified and gzipped) and is extensible via a [plugins](https://github.com/cssinjs/jss/blob/master/docs/plugins.md) API.

If you end up using this styling solution in your codebase, you're going to need to *learn the API*.
The best place to start is by looking at the features that each [plugin](http://cssinjs.org/plugins/) provides. Material-UI uses [few of them](#plugins).
You can always add new plugins if needed with the [`JssProvider`](https://github.com/cssinjs/react-jss#custom-setup) helper.

If you wish to build your own instance of `jss` **and** support *rtl* make sure you also include the [jss-rtl](https://github.com/alitaheri/jss-rtl) plugin.
Check the jss-rtl [readme](https://github.com/alitaheri/jss-rtl#simple-usage) to learn how.

## Sheets registry

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 [Server Rendering](/guides/server-rendering/).

{{"demo": "pages/customization/css-in-js/JssRegistry.js", "hideEditButton": true}}

## Sheets manager

The sheets manager uses a [reference counting](https://en.wikipedia.org/wiki/Reference_counting) algorithm in order to attach and detach the style sheets only once per (styles, theme) couple.
This technique provides an important performance boost when re-rendering instances of a component.

When only rendering on the client, that's not something you need to be aware of. However, when rendering on the server you do. You can read more about [Server Rendering](/guides/server-rendering/).

## Class names

You may have noticed that the class names generated by our styling solution are **non-deterministic**,
so you can't rely on them to stay the same. The following CSS won't work:
```css
.MuiAppBar-root-12 {
  opacity: 0.6
}
```

Instead, you have to use the `classes` property of a component to override them.
On the other hand, thanks to the non-deterministic nature of our class names, we
can implement optimizations for development and production.
They are easy to debug in development and as short as possible in production:

- development: `.MuiAppBar-root-12`
- production: `.jss12`

If you don't like this default behavior, you can change it.
JSS relies on the concept of [class name generator](http://cssinjs.org/js-api/#generate-your-own-class-names).

### Global CSS

We provide a custom implementation of the class name generator for Material-UI needs:
[`createGenerateClassName()`](#creategenerateclassname-options-class-name-generator).
As well as the option to make the class names **deterministic** with the `dangerouslyUseGlobalCSS` option. When turned on, the class names will look like this:

- development: `.MuiAppBar-root`
- production: `.MuiAppBar-root`

⚠️ **Be cautious when using `dangerouslyUseGlobalCSS`.**
We provide this option as an escape hatch for quick prototyping.
Relying on it for code running in production has the following implications:
- Global CSS is inherently fragile. People use strict methodologies like [BEM](http://getbem.com/introduction/) to workaround the issue.
- It's harder to keep track of `classes` API changes.

⚠️ When using `dangerouslyUseGlobalCSS` standalone (without Material-UI), you should name your style sheets. `withStyles` has a name option for that:
```jsx
const Button = withStyles(styles, { name: 'button' })(ButtonBase)
```

## CSS injection order

The CSS injected by Material-UI to style a component has the highest specificity possible as the `<link>` is injected at the bottom of the `<head>` to ensure the components always render correctly.

You might, however, also want to override these styles, for example with styled-components.
If you are experiencing a CSS injection order issue, JSS [provides a mechanism](https://github.com/cssinjs/jss/blob/master/docs/setup.md#specify-dom-insertion-point) to handle this situation.
By adjusting the placement of the `insertionPoint` within your HTML head you can [control the order](http://cssinjs.org/js-api/#attach-style-sheets-in-a-specific-order) that the CSS rules are applied to your components.

### HTML comment

The simplest approach is to add an HTML comment that determines where JSS will inject the styles:

```jsx
<head>
  <!-- jss-insertion-point -->
  <link href="..." />
</head>
```

```jsx
import JssProvider from 'react-jss/lib/JssProvider';
import { create } from 'jss';
import { createGenerateClassName, jssPreset } from '@material-ui/core/styles';

const generateClassName = createGenerateClassName();
const jss = create({
  ...jssPreset(),
  // We define a custom insertion point that JSS will look for injecting the styles in the DOM.
  insertionPoint: 'jss-insertion-point',
});

function App() {
  return (
    <JssProvider jss={jss} generateClassName={generateClassName}>
      ...
    </JssProvider>
  );
}

export default App;
```

### Other HTML element

[Create React App](https://github.com/facebook/create-react-app) strips HTML comments when creating the production build.
To get around the issue, you can provide a DOM element (other than a comment) as the JSS insertion point.

For example, a `<noscript>` element:

```jsx
<head>
  <noscript id="jss-insertion-point"></noscript>
  <link href="..." />
</head>
```

```jsx
import JssProvider from 'react-jss/lib/JssProvider';
import { create } from 'jss';
import { createGenerateClassName, jssPreset } from '@material-ui/core/styles';

const generateClassName = createGenerateClassName();
const jss = create({
  ...jssPreset(),
  // We define a custom insertion point that JSS will look for injecting the styles in the DOM.
  insertionPoint: document.getElementById('jss-insertion-point'),
});

function App() {
  return (
    <JssProvider jss={jss} generateClassName={generateClassName}>
      ...
    </JssProvider>
  );
}

export default App;
```

### JS createComment

codesandbox.io prevents the access to the `<head>` element.
To get around the issue, you can use the JavaScript `document.createComment()` API:

```jsx
import JssProvider from 'react-jss/lib/JssProvider';
import { create } from 'jss';
import { createGenerateClassName, jssPreset } from '@material-ui/core/styles';

const styleNode = document.createComment("jss-insertion-point");
document.head.insertBefore(styleNode, document.head.firstChild);

const generateClassName = createGenerateClassName();
const jss = create({
  ...jssPreset(),
  // We define a custom insertion point that JSS will look for injecting the styles in the DOM.
  insertionPoint: 'jss-insertion-point',
});

function App() {
  return (
    <JssProvider jss={jss} generateClassName={generateClassName}>
      ...
    </JssProvider>
  );
}

export default App;
```

## JssProvider

react-jss exposes a `JssProvider` component to configure JSS for the underlying child components.
There are different use cases:
- Providing a class name generator.
- [Providing a Sheets registry.](/customization/css-in-js/#sheets-registry)
- Providing a JSS instance. You might want to support [Right-to-left](/guides/right-to-left/) or changing the [CSS injection order](/customization/css-in-js/#css-injection-order).
Read [the JSS documentation](http://cssinjs.org/js-api/) to learn more about the options available.
Here is an example:

```jsx
import JssProvider from 'react-jss/lib/JssProvider';
import { create } from 'jss';
import { createGenerateClassName, jssPreset } from '@material-ui/core/styles';

const generateClassName = createGenerateClassName();
const jss = create(jssPreset());

function App() {
  return (
    <JssProvider jss={jss} generateClassName={generateClassName}>
      ...
    </JssProvider>
  );
}

export default App;
```

## Plugins

JSS uses the concept of plugins to extend its core, allowing people to cherry-pick the features they need.
You pay the performance overhead for only what's you are using.
Given `withStyles` is our internal styling solution, all the plugins aren't available by default. We have added the following list:
- [jss-global](http://cssinjs.org/jss-global/)
- [jss-nested](http://cssinjs.org/jss-nested/)
- [jss-camel-case](http://cssinjs.org/jss-camel-case/)
- [jss-default-unit](http://cssinjs.org/jss-default-unit/)
- [jss-vendor-prefixer](http://cssinjs.org/jss-vendor-prefixer/)
- [jss-props-sort](http://cssinjs.org/jss-props-sort/)

It's a subset of [jss-preset-default](http://cssinjs.org/jss-preset-default/).
Of course, you are free to add a new plugin. We have one example for the [`jss-rtl` plugin](/guides/right-to-left/#3-jss-rtl).

## API

### `withStyles(styles, [options]) => higher-order component`

Link a style sheet with a component.
It does not modify the component passed to it; instead, it returns a new component with a `classes` property.
This `classes` object contains the name of the class names injected in the DOM.

Some implementation details that might be interesting to being aware of:
- It adds a `classes` property so you can override the injected class names from the outside.
- It adds an `innerRef` property so you can get a reference to the wrapped component. The usage of `innerRef` is identical to `ref`.
- It forwards *non React static* properties so this HOC is more "transparent".
For instance, it can be used to defined a `getInitialProps()` static method (next.js).

#### Arguments

1. `styles` (*Function | Object*): A function generating the styles or a styles object.
It will be linked to the component.
Use the function signature if you need to have access to the theme. It's provided as the first argument.
2. `options` (*Object* [optional]):
  - `options.withTheme` (*Boolean* [optional]): Defaults to `false`. Provide the `theme` object to the component as a property.
  - `options.name` (*String* [optional]): The name of the style sheet. Useful for debugging.
    If the value isn't provided, it will try to fallback to the name of the component.
  - `options.flip` (*Boolean* [optional]): When set to `false`, this sheet will opt-out the `rtl` transformation. When set to `true`, the styles are inversed. When set to `null`, it follows `theme.direction`.
  - The other keys are forwarded to the options argument of [jss.createStyleSheet([styles], [options])](http://cssinjs.org/js-api/#create-style-sheet).

#### Returns

`higher-order component`: Should be used to wrap a component.

#### Examples

```jsx
import { withStyles } from '@material-ui/core/styles';

const styles = {
  root: {
    backgroundColor: 'red',
  },
};

class MyComponent extends React.Component {
  render () {
    return <div className={this.props.classes.root} />;
  }
}

export default withStyles(styles)(MyComponent);
```

Also, you can use as [decorators](https://babeljs.io/docs/en/babel-plugin-transform-decorators/) like so:

```jsx
import { withStyles } from '@material-ui/core/styles';

const styles = {
  root: {
    backgroundColor: 'red',
  },
};

@withStyles(styles)
class MyComponent extends React.Component {
  render () {
    return <div className={this.props.classes.root} />;
  }
}

export default MyComponent
```

### `createGenerateClassName([options]) => class name generator`

A function which returns [a class name generator function](http://cssinjs.org/js-api/#generate-your-own-class-names).

#### Arguments

1. `options` (*Object* [optional]):
  - `options.dangerouslyUseGlobalCSS` (*Boolean* [optional]): Defaults to `false`. Makes the Material-UI class names deterministic.
  - `options.productionPrefix` (*String* [optional]): Defaults to `'jss'`. The string used to prefix the class names in production.
  - `options.seed` (*String* [optional]): Defaults to `''`. The string used to uniquely identify the generator. It can be used to avoid class name collisions when using multiple generators.

#### Returns

`class name generator`: The generator should be provided to JSS.

#### Examples

```jsx
import JssProvider from 'react-jss/lib/JssProvider';
import { createGenerateClassName } from '@material-ui/core/styles';

const generateClassName = createGenerateClassName({
  dangerouslyUseGlobalCSS: true,
  productionPrefix: 'c',
});

function App() {
  return (
    <JssProvider generateClassName={generateClassName}>
      ...
    </JssProvider>
  );
}

export default App;
```

## Alternative APIs

Do you think that [higher-order components are the new mixins](https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce)? Rest assured we don't, however because `withStyles()` is a higher-order component, it can be extended with just a **few lines of code** to match different patterns that are all idiomatic React. Here are a couple of examples.

### Render props API (+11 lines)

The term [“render prop”](https://reactjs.org/docs/render-props.html) refers to a simple technique for sharing code between React components using a prop whose value is a function.

```jsx
// You will find the `createStyled` implementation in the source of the demo.
const Styled = createStyled({
  root: {
    background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
    borderRadius: 3,
    border: 0,
    color: 'white',
    height: 48,
    padding: '0 30px',
    boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
  },
});

function RenderProps() {
  return (
    <Styled>
      {({ classes }) => (
        <Button className={classes.root}>
          {'Render props'}
        </Button>
      )}
    </Styled>
  );
}
```

{{"demo": "pages/customization/css-in-js/RenderProps.js"}}

You can access the theme the same way you would do it with `withStyles`:
```js
const Styled = createStyled(theme => ({
  root: {
    backgroundColor: theme.palette.background.paper,
  },
}));
```

[@jedwards1211](https://github.com/jedwards1211) Has taken the time to move this module into a package: [material-ui-render-props-styles](https://github.com/jcoreio/material-ui-render-props-styles). Feel free to use it.

### styled-components API (+15 lines)

styled-components's API removes the mapping between components and styles. Using components as a low-level styling construct can be simpler.

```jsx
// You will find the `styled` implementation in the source of the demo.
// You can even write CSS with https://github.com/cssinjs/jss-template.
const MyButton = styled(Button)({
  background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
  borderRadius: 3,
  border: 0,
  color: 'white',
  height: 48,
  padding: '0 30px',
  boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
});

function StyledComponents() {
  return <MyButton>{'Styled Components'}</MyButton>;
}
```

{{"demo": "pages/customization/css-in-js/StyledComponents.js"}}

You can access the theme the same way you would do it with `withStyles`:
```js
const MyButton = styled(Button)(theme => ({
  backgroundColor: theme.palette.background.paper,
}));
```
