While you can use the JSS based styling solution provided by Material-UI to style your application, you can also use the one you already know and love (from plain CSS to styled-components).
+
While you can use the emotion based styling solution provided by Material-UI to style your application, you can also use the one you already know and love (from plain CSS to styled-components).
This guide aims to document the most popular alternatives,
but you should find that the principles applied here can be adapted to other libraries.
@@ -18,96 +18,143 @@ Nothing fancy, just plain CSS.
{{"demo": "pages/guides/interoperability/StyledComponents.js", "hideToolbar": true}}
-[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/plain-css-mtzri)
+[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/plain-css-fdue7)
-**PlainCssButton.css**
+**PlainCssSlider.css**
```css
-.button {
- background-color: #6772e5;
- color: #fff;
- box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
- padding: 7px 14px;
+.slider {
+ color: #20b2aa;
}
-.button:hover {
- background-color: #5469d4;
+
+.slider:hover {
+ color: #2e8b57;
}
```
-**PlainCssButton.js**
+**PlainCssSlider.js**
```jsx
import * as React from 'react';
-import Button from '@material-ui/core/Button';
-import './PlainCssButton.css';
+import Slider from '@material-ui/lab/SliderStyled';
+import './PlainCssSlider.css';
-export default function PlainCssButton() {
+export default function PlainCssSlider() {
return (
-
-
+
+
);
}
```
-### Controlling priority ⚠️
+### CSS injection order ⚠️
-**Note:** JSS injects its styles at the bottom of the ``. If you don't want to mark style attributes with **!important**, you need to change [the CSS injection order](/styles/advanced/#css-injection-order), as in the demo:
+**Note:** Most CSS-in-JS solutions inject their styles at the bottom of the HTML ``, which gives Material-UI precedence over your custom styles. To remove the need for **!important**, you need to change the CSS injection order. Here's a demo of how it can be done for the default style engine - emotion:
```jsx
-import { StylesProvider } from '@material-ui/core/styles';
+import * as React from 'react';
+import { CacheProvider } from '@emotion/core';
+import createCache from '@emotion/cache';
+
+const head = document.getElementsByTagName('head')[0];
+
+const emotionContainer = head.insertBefore(
+ document.createElement('STYLE'),
+ head.firstChild,
+);
+
+const cache = createCache({
+ container: emotionContainer,
+});
-{/* Your component tree.
- Now, you can override Material-UI's styles. */};
+export default function PlainCssPriority() {
+ return (
+
+ {/* Your component tree. Now you can override Material-UI's styles. */}
+
+ );
+}
```
### Deeper elements
-If you attempt to style a Drawer with variant permanent,
-you will likely need to affect the Drawer's child paper element.
-However, the paper is not the root element of Drawer and therefore styled-components customization as above will not work.
-You need to use the [`classes`](/styles/advanced/#overriding-styles-classes-prop) API of Material-UI.
+If you attempt to style the Slider,
+you will likely need to affect some of the Slider's child elements, for example the thumb.
+In Material-UI, all child elements have an increased specificity of 2: `.parent .child {}`. When writing overrides, you need to do the same.
-The following example overrides the `label` style of `Button` in addition to the custom styles on the button itself.
+The following examples override the slider's `thumb` style in addition to the custom styles on the slider itself.
-{{"demo": "pages/guides/interoperability/StyledComponents.js", "hideToolbar": true}}
+{{"demo": "pages/guides/interoperability/StyledComponentsDeep.js", "hideToolbar": true}}
+
+**PlainCssSliderDeep1.css**
+
+```css
+.slider {
+ color: #20b2aa;
+}
+
+.slider:hover {
+ color: #2e8b57;
+}
+
+.slider .MuiSlider-thumb {
+ border-radius: 1px;
+}
+```
-**PlainCssButtonDeep.css**
+**PlainCssSliderDeep1.js**
+
+```jsx
+import * as React from 'react';
+import Slider from '@material-ui/lab/SliderStyled';
+import './PlainCssSliderDeep1.css';
+
+export default function PlainCssSliderDeep1() {
+ return (
+
+
+
+
+ );
+}
+```
+
+The above demo relies on the [default `className` values](/styles/advanced/#with-material-ui-core), but you can provide your own class name with the `componentsProps` API.
+
+**PlainCssSliderDeep2.css**
```css
-.button {
- background-color: #6772e5;
- box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
- padding: 7px 14px;
+.slider {
+ color: #20b2aa;
}
-.button:hover {
- background-color: #5469d4;
+
+.slider:hover {
+ color: #2e8b57;
}
-.button-label {
- color: #fff;
+
+.slider .thumb {
+ border-radius: 1px;
}
```
-**PlainCssButtonDeep.js**
+**PlainCssSliderDeep2.js**
```jsx
import * as React from 'react';
-import Button from '@material-ui/core/Button';
-import './PlainCssButtonDeep.css';
+import Slider from '@material-ui/lab/SliderStyled';
+import './PlainCssSliderDeep2.css';
-export default function PlainCssButtonDeep() {
+export default function PlainCssSliderDeep2() {
return (
-
-
+
+
);
}
@@ -118,45 +165,97 @@ export default function PlainCssButtonDeep() {
Explicitly providing the class names to the component is too much effort?
[You can target the class names generated by Material-UI](/styles/advanced/#with-material-ui-core).
-[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/global-css-bir9e)
+[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/global-classnames-dho8k)
-**GlobalCssButton.css**
+**GlobalCssSlider.css**
```css
-.MuiButton-root {
- background-color: #6772e5;
- box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
- padding: 7px 14px;
+.MuiSlider-root {
+ color: #20b2aa;
}
-.MuiButton-root:hover {
- background-color: #5469d4;
+
+.MuiSlider-root:hover {
+ color: #2e8b57;
}
-.MuiButton-label {
- color: #fff;
+```
+
+**GlobalCssSlider.js**
+
+```jsx
+import * as React from 'react';
+import Slider from '@material-ui/lab/SliderStyled';
+import './GlobalCssSlider.css';
+
+export default function GlobalCssSlider() {
+ return ;
}
```
-**GlobalCssButton.js**
+### CSS injection order ⚠️
+
+**Note:** Most CSS-in-JS solutions inject their styles at the bottom of the HTML ``, which gives Material-UI precedence over your custom styles. To remove the need for **!important**, you need to change the CSS injection order. Here's a demo of how it can be done for the default style engine - emotion:
```jsx
import * as React from 'react';
-import Button from '@material-ui/core/Button';
-import './GlobalCssButton.css';
+import { CacheProvider } from '@emotion/core';
+import createCache from '@emotion/cache';
+
+const head = document.getElementsByTagName('head')[0];
-export default function GlobalCssButton() {
- return ;
+const emotionContainer = head.insertBefore(
+ document.createElement('STYLE'),
+ head.firstChild,
+);
+
+const cache = createCache({
+ container: emotionContainer,
+});
+
+export default function GlobalCssPriority() {
+ return (
+
+ {/* Your component tree. Now you can override Material-UI's styles. */}
+
+ );
}
```
-### Controlling priority ⚠️
+### Deeper elements
+
+If you attempt to style the Slider,
+you will likely need to affect some of the Slider's child elements, for example the thumb.
+In Material-UI, all child elements have an increased specificity of 2: `.parent .child {}`. When writing overrides, you need to do the same.
+
+The following example overrides the slider's `thumb` style in addition to the custom styles on the slider itself.
+
+{{"demo": "pages/guides/interoperability/StyledComponentsDeep.js", "hideToolbar": true}}
+
+**GlobalCssSliderDeep.css**
-**Note:** JSS injects its styles at the bottom of the ``. If you don't want to mark style attributes with **!important**, you need to change [the CSS injection order](/styles/advanced/#css-injection-order), as in the demo:
+```css
+.MuiSlider-root {
+ color: #20b2aa;
+}
+
+.MuiSlider-root:hover {
+ color: #2e8b57;
+}
+
+.MuiSlider-root .MuiSlider-thumb {
+ border-radius: 1px;
+}
+```
+
+**GlobalCssSliderDeep.js**
```jsx
-import { StylesProvider } from '@material-ui/core/styles';
+import * as React from 'react';
+import Slider from '@material-ui/lab/SliderStyled';
+import './GlobalCssSliderDeep.css';
-{/* Your component tree.
- Now, you can override Material-UI's styles. */};
+export default function GlobalCssSliderDeep() {
+ return ;
+}
```
## Styled Components
@@ -164,116 +263,100 @@ import { StylesProvider } from '@material-ui/core/styles';
![stars](https://img.shields.io/github/stars/styled-components/styled-components.svg?style=social&label=Star)
![npm](https://img.shields.io/npm/dm/styled-components.svg?)
-The `styled()` method works perfectly on all of the components.
+### Change the default styled engine
+
+By default, Material-UI components come with emotion as their style engine. If,
+however, you would like to use `styled-components`, you are can configure your app by following this [example project](https://github.com/mui-org/material-ui/blob/next/examples/create-react-app-with-styled-components).
+Following this approach reduces the bundle size, and removes the need to configure the CSS injection order.
+
+After the style engine is configured properly, you can use the `experimentalStyled()` utility
+from `@material-ui/core/styles` and have direct access to the theme.
{{"demo": "pages/guides/interoperability/StyledComponents.js", "hideToolbar": true}}
-[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/styled-components-r1fsr)
+[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/styled-components-interoperability-w9z9d)
```jsx
import * as React from 'react';
-import styled from 'styled-components';
-import Button from '@material-ui/core/Button';
-
-const StyledButton = styled(Button)`
- background-color: #6772e5;
- color: #fff;
- box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
- padding: 7px 14px;
- &:hover {
- background-color: #5469d4;
+import Slider from '@material-ui/lab/SliderStyled';
+import { experimentalStyled as styled } from '@material-ui/core/styles';
+
+const CustomizedSlider = styled(Slider)`
+ color: #20b2aa;
+
+ :hover {
+ color: #2e8b57;
}
`;
export default function StyledComponents() {
- return (
-
-
- Customized
-
- );
+ return ;
}
```
-### Controlling priority ⚠️
-
-**Note:** Both styled-components and JSS inject their styles at the bottom of the ``.
-The best approach to ensuring styled-components styles are loaded last is to change [the CSS injection order](/styles/advanced/#css-injection-order), as in the demo:
-
-```jsx
-import { StylesProvider } from '@material-ui/core/styles';
-
-{/* Your component tree.
- Now, you can override Material-UI's styles. */};
-```
-
-Another approach is to use the `&&` characters in styled-components to [bump up specificity](https://www.styled-components.com/docs/advanced#issues-with-specificity) by repeating the class name. Avoid the usage of `!important`.
-
### Deeper elements
-If you attempt to style a Drawer with variant permanent,
-you will likely need to affect the Drawer's child paper element.
-However, the paper is not the root element of Drawer and therefore styled-components customization as above will not work.
-You need to use the Material-UI [`classes`](/styles/advanced/#overriding-styles-classes-prop) API.
+If you attempt to style the Slider,
+you will likely need to affect some of the Slider's child elements, for example the thumb.
+In Material-UI, all child elements have an increased specificity of 2: `.parent .child {}`. When writing overrides, you need to do the same.
-The following example overrides the `label` style of `Button` in addition to the custom styles on the button itself.
-It also works around [this styled-components issue](https://github.com/styled-components/styled-components/issues/439) by "consuming" props that should not be passed on to the underlying component.
+The following examples override the slider's `thumb` style in addition to the custom styles on the slider itself.
-{{"demo": "pages/guides/interoperability/StyledComponentsDeep.js"}}
+{{"demo": "pages/guides/interoperability/StyledComponentsDeep.js", "defaultCodeOpen": false}}
```jsx
import * as React from 'react';
-import styled from 'styled-components';
-import Button from '@material-ui/core/Button';
-
-const StyledButton = styled(Button)`
- background-color: #6772e5;
- box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
- padding: 7px 14px;
- &:hover {
- background-color: #5469d4;
+import Slider from '@material-ui/lab/SliderStyled';
+import { experimentalStyled as styled } from '@material-ui/core/styles';
+
+const CustomizedSlider = styled(Slider)`
+ color: #20b2aa;
+
+ :hover {
+ color: #2e8b57;
}
- & .MuiButton-label {
- color: #fff;
+
+ & .MuiSlider-thumb {
+ border-radius: 1px;
}
`;
-export default function StyledComponentsDeep() {
+export default function StyledComponentsDeep1() {
return (
-
- Customized
+
+
);
}
```
-The above demo relies on the [default `classes` values](/styles/advanced/#with-material-ui-core) but you can provide your own class name: `.label`.
+The above demo relies on the [default `className` values](/styles/advanced/#with-material-ui-core), but you can provide your own class name with the `componentsProps` API.
```jsx
import * as React from 'react';
-import styled from 'styled-components';
-import Button from '@material-ui/core/Button';
+import { experimentalStyled as styled } from '@material-ui/core/styles';
+import Slider from '@material-ui/lab/SliderStyled';
-const StyledButton = styled(({ color, ...other }) => (
-
+const CustomizedSlider = styled((props) => (
+
))`
- background-color: #6772e5;
- box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
- padding: 7px 14px;
- &:hover {
- background-color: #5469d4;
+ color: #20b2aa;
+
+ :hover {
+ color: #2e8b57;
}
- & .label {
- color: #fff;
+
+ & .thumb {
+ border-radius: 1px;
}
`;
-export default function StyledComponentsDeep() {
+export default function StyledComponentsDeep2() {
return (
-
- Customized
+
+
);
}
@@ -281,61 +364,34 @@ export default function StyledComponentsDeep() {
### Theme
-Material-UI has a rich theme structure that you can leverage for
-the color manipulations, the transitions, the media queries, and more.
+By using the Material-UI theme provider, the theme will be available in the theme context
+of the styled engine too (emotion or styled-components, depending on your configuration).
-We encourage to share the same theme object between Material-UI and your styles.
+> ⚠️ If you are **already** using a custom theme with styled-components or emotion,
+> it might not be compatible with Material-UI's theme specification. If it's not
+> compatible, you need to render Material-UI's ThemeProvider first. This will
+> ensure the theme structures are isolated. This is ideal for the progressive adoption
+> of Material-UI's components in the codebase.
+
+You are encouraged to share the same theme object between Material-UI and the rest of your project.
```jsx
-const StyledButton = styled(Button)`
- ${({ theme }) => `
- background-color: ${theme.palette.primary.main};
- color: #fff;
- box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
- padding: 4px 10px;
- font-size: 13px;
- &:hover {
- background-color: ${darken(theme.palette.primary.main, 0.2)};
- }
- ${theme.breakpoints.up('sm')} {
- font-size: 14px;
- padding: 7px 14px;
+const CustomizedSlider = styled(Slider)(
+ ({ theme }) => `
+ color: ${theme.palette.primary.main};
+
+ :hover {
+ color: ${darken(theme.palette.primary.main, 0.2)};
}
- `}
-`;
+`,
+);
```
{{"demo": "pages/guides/interoperability/StyledComponentsTheme.js"}}
### Portals
-The [Portal](/components/portal/) provides a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.
-Because of the way styled-components scopes its CSS, you may run into issues where styling is not applied.
-
-For example, if you attempt to style the [Menu](/components/menus/) of a [Select](/components/selects/) component using the `MenuProps` prop,
-you will need to pass along the `className` prop to the element being rendered outside of it's DOM hierarchy.
-The following example shows a workaround:
-
-```jsx
-import * as React from 'react';
-import styled from 'styled-components';
-import Menu from '@material-ui/core/Menu';
-import MenuItem from '@material-ui/core/MenuItem';
-
-const StyledMenu = styled(({ className, ...props }) => (
-
-))`
- box-shadow: none;
- border: 1px solid #d3d4d5;
-
- li {
- padding-top: 8px;
- padding-bottom: 8px;
- }
-`;
-```
-
-{{"demo": "pages/guides/interoperability/StyledComponentsPortal.js"}}
+TODO: fill this section after the portal is implemented with the new styled engine.
## CSS Modules
@@ -346,91 +402,146 @@ bundling solution people are using.
{{"demo": "pages/guides/interoperability/StyledComponents.js", "hideToolbar": true}}
-[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/css-modules-3j29h)
+[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/css-modules-nuyg8)
-**CssModulesButton.css**
+**CssModulesSlider.module.css**
```css
-.button {
- background-color: #6772e5;
- color: #fff;
- box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
- padding: 7px 14px;
+.slider {
+ color: #20b2aa;
}
-.button:hover {
- background-color: #5469d4;
+
+.slider:hover {
+ color: #2e8b57;
}
```
-**CssModulesButton.js**
+**CssModulesSlider.js**
```jsx
-import * as React from 'react';
+import React from 'react';
+import Slider from '@material-ui/lab/SliderStyled';
// webpack, parcel or else will inject the CSS into the page
-import styles from './CssModulesButton.css';
-import Button from '@material-ui/core/Button';
+import styles from './CssModulesSlider.module.css';
-export default function CssModulesButton() {
+export default function CssModulesSlider() {
return (
-
-
+
+
);
}
```
-### Controlling priority ⚠️
+### CSS injection order ⚠️
-**Note:** JSS injects its styles at the bottom of the ``. If you don't want to mark style attributes with **!important**, you need to change [the CSS injection order](/styles/advanced/#css-injection-order), as in the demo:
+**Note:** Most CSS-in-JS solutions inject their styles at the bottom of the HTML ``, which gives Material-UI precedence over your custom styles. To remove the need for **!important**, you need to change the CSS injection order. Here's a demo of how it can be done for the default style engine - emotion:
```jsx
-import { StylesProvider } from '@material-ui/core/styles';
+import * as React from 'react';
+import { CacheProvider } from '@emotion/core';
+import createCache from '@emotion/cache';
-{/* Your component tree.
- Now, you can override Material-UI's styles. */};
+const head = document.getElementsByTagName('head')[0];
+
+const emotionContainer = head.insertBefore(
+ document.createElement('STYLE'),
+ head.firstChild,
+);
+
+const cache = createCache({
+ container: emotionContainer,
+});
+
+export default function CssModulesPriority() {
+ return (
+
+ {/* Your component tree. Now you can override Material-UI's styles. */}
+
+ );
+}
```
### Deeper elements
-If you attempt to style a Drawer with variant permanent,
-you will likely need to affect the Drawer's child paper element.
-However, the paper is not the root element of Drawer and therefore styled-components customization as above will not work.
-You need to use the [`classes`](/styles/advanced/#overriding-styles-classes-prop) API of Material-UI.
+If you attempt to style the Slider,
+you will likely need to affect some of the Slider's child elements, for example the thumb.
+In Material-UI, all child elements have an increased specificity of 2: `.parent .child {}`. When writing overrides, you need to do the same.
-The following example overrides the `label` style of `Button` in addition to the custom styles on the button itself.
+The following examples override the slider's `thumb` style in addition to the custom styles on the slider itself.
-{{"demo": "pages/guides/interoperability/StyledComponents.js", "hideToolbar": true}}
+{{"demo": "pages/guides/interoperability/StyledComponentsDeep.js", "hideToolbar": true}}
-**CssModulesButtonDeep.css**
+**CssModulesSliderDeep1.module.css**
```css
-.root {
- background-color: #6772e5;
- box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
- padding: 7px 14px;
+.slider {
+ color: #20b2aa;
}
-.root:hover {
- background-color: #5469d4;
+
+.slider:hover {
+ color: #2e8b57;
}
-.label {
- color: #fff;
+
+.slider .MuiSlider-thumb {
+ border-radius: 1px;
}
```
-**CssModulesButtonDeep.js**
+**CssModulesSliderDeep1.js**
```jsx
-import * as React from 'react';
+import React from 'react';
// webpack, parcel or else will inject the CSS into the page
-import styles from './CssModulesButtonDeep.css';
-import Button from '@material-ui/core/Button';
+import styles from './CssModulesSliderDeep1.module.css';
+import Slider from '@material-ui/lab/SliderStyled';
-export default function CssModulesButtonDeep() {
+export default function CssModulesSliderDeep1() {
return (
-
-
+
+
+
+ );
+}
+```
+
+The above demo relies on the [default `className` values](/styles/advanced/#with-material-ui-core), but you can provide your own class name with the `componentsProps` API.
+
+**CssModulesSliderDeep2.module.css**
+
+```css
+.slider {
+ color: #20b2aa;
+}
+
+.slider:hover {
+ color: #2e8b57;
+}
+
+.slider .thumb {
+ border-radius: 1px;
+}
+```
+
+**CssModulesSliderDeep2.js**
+
+```jsx
+import React from 'react';
+// webpack, parcel or else will inject the CSS into the page
+import styles from './CssModulesSliderDeep2.module.css';
+import Slider from '@material-ui/lab/SliderStyled';
+
+export default function CssModulesSliderDeep2() {
+ return (
+
+
+
);
}
@@ -447,75 +558,35 @@ Emotion's **css()** method works seamlessly with Material-UI.
{{"demo": "pages/guides/interoperability/EmotionCSS.js", "hideToolbar": true}}
-[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/emotion-bgfxj)
+[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/emotion-interoperability-idymy)
```jsx
/** @jsx jsx */
import { jsx, css } from '@emotion/core';
-import Button from '@material-ui/core/Button';
+import Slider from '@material-ui/lab/SliderStyled';
export default function EmotionCSS() {
return (
-
-
+
- Customized
-
+ />
);
}
```
-### Controlling priority ⚠️
-
-**Note:** JSS injects its styles at the bottom of the ``. If you don't want to mark style attributes with **!important**, you need to change [the CSS injection order](/styles/advanced/#css-injection-order), as in the demo:
-
-```jsx
-import { StylesProvider } from '@material-ui/core/styles';
-
-{/* Your component tree.
- Now, you can override Material-UI's styles. */};
-```
-
### Theme
-Material-UI has a rich theme structure that you can leverage for
-the color manipulations, the transitions, the media queries, and more.
-
-We encourage to share the same theme object between Material-UI and your styles.
-
-```jsx
-
-```
-
-{{"demo": "pages/guides/interoperability/EmotionTheme.js"}}
+It works exactly like styled components. You can [use the same guide](/guides/interoperability/#styled-components).
### The `styled()` API