# CSS in JS

Material-UI aims to provide strong foundations for building dynamic UIs.
For the sake of simplicity, **we expose the internal 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)

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 very cautious when using `dangerouslyUseGlobalCSS`.**
We provide this option as an escape hatch for quick prototyping,
but you should avoid relying on it for code running in production
as it's very hard to keep track of class name API changes.
Global CSS is inherently fragile.

## 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.
jss.options.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.
jss.options.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.
jss.options.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 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 an 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/plugins/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.

#### 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, .30)',
  },
});

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`:
```
const Styled = createStyled(theme => ({
  root: {
    backgroundColor: theme.palette.background.paper,
  },
}));
```

### 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, .30)',
});

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`:
```
const MyButton = styled(Button)(theme => ({
  backgroundColor: theme.palette.background.paper,
}));
```
