Files
react-test/docs/data/system/styled/styled.md
how2ice 005cf56baf
Some checks failed
No response / noResponse (push) Has been cancelled
CI / Continuous releases (push) Has been cancelled
CI / test-dev (macos-latest) (push) Has been cancelled
CI / test-dev (ubuntu-latest) (push) Has been cancelled
CI / test-dev (windows-latest) (push) Has been cancelled
Maintenance / main (push) Has been cancelled
Scorecards supply-chain security / Scorecards analysis (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled
init project
2025-12-12 14:26:25 +09:00

307 lines
9.8 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# `styled()`
<p class="description">Utility for creating styled components.</p>
## 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<string, styles>) => 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.
<img src="/static/images/system/styled-options.png" alt="browser DevTools showing the rendered component" width="654" height="258" style="width: 327px" />
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) => (
<Button
sx={{
mx: 1, // ✔️ this shortcut is specific to the `sx` prop,
}}
>
{props.children}
</Button>
);
```
### 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) => (
<Button
sx={{
padding: 1, // means "theme.spacing(1)", NOT "1px"
}}
>
{props.children}
</Button>
);
```
### 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) => (
<Button sx={{ backgroundColor: props.myCustomColor }}>{props.children}</Button>
);
```
### 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) => (
<Button
sx={{ backgroundColor: (theme) => lighten(0.2, theme.palette.primary.main) }}
>
{props.children}
</Button>
);
// Note: for direct theme access without modification, you can also use a shortcut by providing the key as a string
const MyStyledButton = (props) => (
<Button sx={{ backgroundColor: 'primary.main' }}>{props.children}</Button>
);
```
### 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(
<div>
<Parent>
<Child>Green because I am inside a Parent</Child>
</Parent>
<Child>Red because I am not inside a Parent</Child>
</div>,
);
```
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!