# `styled()`

Utility for creating styled components.

## Introduction All Material UI components are styled with the `styled()` utility. This utility is built on top of the `styled()` module of `@mui/styled-engine` and provides additional features. ### Import path You can use the utility coming from the `@mui/system` package, or if you are using `@mui/material`, you can import it from `@mui/material/styles`. The difference is in the default `theme` that is used (if no theme is available in the React context). ```ts import { styled } from '@mui/system'; // If you are using @mui/material import { styled } from '@mui/material/styles'; ``` ### What problems does it solve? The utility can be used as a replacement for emotion's or styled-components' styled() utility. It aims to solve the same problem, but also provides the following benefits: 1. It uses a default `theme` if no theme is available in React context. 2. It supports the theme's [`styleOverrides`](/material-ui/customization/theme-components/#theme-style-overrides) and [`variants`](/material-ui/customization/theme-components/#variants) to be applied, based on the `name` applied in the options (can be skipped). 3. It adds support for the [the `sx` prop](/system/getting-started/the-sx-prop/) (can be skipped). 4. It adds by default the `shouldForwardProp` option (that can be overridden), taking into account: `ownerState`, `theme`, `sx`, and `as`. ## API ### `styled(Component, [options])(styles) => Component` #### Arguments 1. `Component`: The component that will be wrapped. 2. `options` (_object_ [optional]): - `options.shouldForwardProp` (_`(prop: string) => bool`_ [optional]): Indicates whether the `prop` should be forwarded to the `Component`. - `options.label` (_string_ [optional]): The suffix of the style sheet. Useful for debugging. - `options.name` (_string_ [optional]): The key used under `theme.components` for specifying `styleOverrides` and `variants`. Also used for generating the `label`. - `options.slot` (_string_ [optional]): If `Root`, it automatically applies the theme's `variants`. - `options.overridesResolver` (_(props: object, styles: Record) => styles_ [optional]): Function that returns styles based on the props and the `theme.components[name].styleOverrides` object. - `options.skipVariantsResolver` (_bool_): Disables the automatic resolver for the `theme.components[name].variants`. - `options.skipSx` (_bool_ [optional]): Disables the `sx` prop on the component. - The other keys are forwarded to the `options` argument of emotion's [`styled([Component], [options])`](https://emotion.sh/docs/styled). 3. `styles` (_object | `({ ...props, theme }) => object`_ [optional]): A styles object or a function returning a styles object. The function receives the theme and component's props in an object which is its single argument. #### Returns `Component`: The new component created. ## Basic usage {{"demo": "BasicUsage.js", "defaultCodeOpen": true}} ## Using the theme {{"demo": "ThemeUsage.js", "defaultCodeOpen": true}} ## Custom components This example demonstrates how you can use the `styled` API to create custom components, with the same capabilities as the core components: {{"demo": "UsingOptions.js", "defaultCodeOpen": true }} If you inspect this element with the browser DevTools in development mode, you will notice that the class of the component now ends with the `MyThemeComponent-root`, which comes from the `name` and `slot` options that were provided. browser DevTools showing the rendered component In addition to this, the `color`, `sx`, and `variant` props are not propagated to the generated `div` element. ## Removing features If you would like to remove some of the MUI System specific features, you can do it like this: ```diff const StyledComponent = styled('div', {}, { name: 'MuiStyled', slot: 'Root', - overridesResolver: (props, styles) => styles.root, // disables theme.components[name].styleOverrides + skipVariantsResolver: true, // disables theme.components[name].variants + skipSx: true, // disables the sx prop }); ``` ## Create custom `styled()` utility If you want to have a different default theme for the `styled()` utility, you can create your own version of it, using the `createStyled()` utility. ```js import { createStyled, createTheme } from '@mui/system'; const defaultTheme = createTheme({ // your custom theme values }); const styled = createStyled({ defaultTheme }); export default styled; ``` ## Difference with the `sx` prop The `styled` function is an extension of the `styled` utility provided by the underlying style library used – either Emotion or styled-components. It is guaranteed that it will produce the same output as the `styled` function coming from the style library for the same input. The [`sx`](/system/getting-started/the-sx-prop/) prop, on the other hand, is a new way of styling your components, focused on fast customization. `styled` is a function, while `sx` is a prop available on the components created with `styled`. Therefore, you will notice the following differences: ### `sx` provides more shortcuts than `styled` With `styled`: ```js const MyStyledButton = styled('button')({ mx: 1, // ❌ don't use this! This shortcut is only provided by the `sx` prop }); ``` With `sx`: ```js import Button from '@mui/material/Button'; const MyStyledButton = (props) => ( ); ``` ### The style definition varies slightly With `styled`: ```js const MyStyledButton = styled('button')({ padding: 1, // means "1px", NOT "theme.spacing(1)" }); ``` With `sx`: ```js import Button from '@mui/material/Button'; const MyStyledButton = (props) => ( ); ``` ### Patterns for how to use props differ With `styled`: ```js const MyStyledButton = styled('button')((props) => ({ backgroundColor: props.myBackgroundColor, })); ``` With `sx`: ```js import Button from '@mui/material/Button'; const MyStyledButton = (props) => ( ); ``` ### Parameter when using function are different for each field With `styled` (not recommended): ```js // You may find this syntax in the wild, but for code readability // we recommend using only one top-level function const MyStyledButtonPropsPerField = styled('button')({ backgroundColor: (props) => props.myBackgroundColor, }); ``` With `sx`: ```js import Button from '@mui/material/Button'; import { lighten } from 'polished'; const MyStyledButton = (props) => ( ); // Note: for direct theme access without modification, you can also use a shortcut by providing the key as a string const MyStyledButton = (props) => ( ); ``` ### How can I use the `sx` syntax with the `styled()` utility? If you prefer the `sx` syntax and want to use it in both the `sx` prop and the `styled()` utility, you can use the `unstable_sx` utility from the `theme`: {{"demo": "UsingWithSx.js", "defaultCodeOpen": true}} The overhead added by using the `unstable_sx` utility is the same as if you were to use the `sx` prop on the component. :::info Note: You can use `unstable_sx` outside of the `styled()` utility, too; for example when defining `variants` in your custom theme. ::: ## How to use components selector API If you've ever used the `styled()` API of either [`emotion`](https://emotion.sh/docs/styled#targeting-another-emotion-component) or [`styled-components`](https://styled-components.com/docs/advanced#referring-to-other-components), you should have been able to use components as selectors. ```jsx import styled from '@emotion/styled'; const Child = styled.div` color: red; `; const Parent = styled.div` ${Child} { color: green; } `; render(
Green because I am inside a Parent Red because I am not inside a Parent
, ); ``` With MUI System's `styled()` utility, you can use components as selectors, too. When using `@mui/styled-engine-sc` (`styled-components`), nothing needs to be done. When using `@mui/styled-engine` (`emotion`), the default engine, there are a few steps you should perform: First, you should install [`@emotion/babel-plugin`](https://emotion.sh/docs/@emotion/babel-plugin). ```bash npm install @emotion/babel-plugin ``` Then, configure the plugin to know about the Material UI version of the `styled()` utility: **babel.config.js** ```js module.exports = { ... plugins: [ [ "@emotion", { importMap: { "@mui/system": { styled: { canonicalImport: ["@emotion/styled", "default"], styledBaseImport: ["@mui/system", "styled"] } }, "@mui/material": { styled: { canonicalImport: ["@emotion/styled", "default"], styledBaseImport: ["@mui/material", "styled"] } }, "@mui/material/styles": { styled: { canonicalImport: ["@emotion/styled", "default"], styledBaseImport: ["@mui/material/styles", "styled"] } } } } ] ] }; ``` :::info Note: If you use [`babel-plugin-direct-import`](https://github.com/avocadowastaken/babel-plugin-direct-import), place it after `@emotion/babel-plugin` in the Babel config. ::: Now you should be able to use components as your selectors!