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
376 lines
9.6 KiB
Markdown
376 lines
9.6 KiB
Markdown
# Getting started with Pigment CSS
|
||
|
||
<p class="description">Learn how to get started customizing your components using Pigment CSS.</p>
|
||
|
||
:::warning
|
||
Pigment CSS is currently in the early alpha stage of development. We're actively working on improving its performance and stability. If you find any problem, please open a [GitHub issue](https://github.com/mui/pigment-css/issues).
|
||
:::
|
||
|
||
<iframe width="100%" height="400" src="https://www.youtube.com/embed/UVeDpUey5Es?si=w8OtdStXHtWWIODa" title="YouTube video player: Getting Started with Pigment CSS" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
|
||
|
||
[Pigment CSS](https://github.com/mui/pigment-css) is a zero-runtime CSS-in-JS library that pre-compiles at build time, making it compatible with React Server Components and providing you with significant performance improvements over other styling engines.
|
||
|
||
Pigment CSS is compatible with any React component library and can be used with Vite and Next.js.
|
||
|
||
Check out the [Migrating to Pigment CSS](/material-ui/migration/migrating-to-pigment-css/) guide if you have an existing Material UI project.
|
||
|
||
## Prerequisites
|
||
|
||
- Node.js
|
||
- A package manager
|
||
- A Next.js or Vite project
|
||
|
||
You can fast track your Pigment CSS installation and project creation with the following commands:
|
||
|
||
<codeblock storageKey="framework">
|
||
|
||
```bash Next.js
|
||
curl https://codeload.github.com/mui/pigment-css/tar.gz/master | tar -xz --strip=2 pigment-css-master/examples/pigment-css-nextjs-ts
|
||
cd pigment-css-nextjs-ts
|
||
```
|
||
|
||
```bash Vite
|
||
curl https://codeload.github.com/mui/pigment-css/tar.gz/master | tar -xz --strip=2 pigment-css-master/examples/pigment-css-vite-ts
|
||
cd pigment-css-vite-ts
|
||
```
|
||
|
||
</codeblock>
|
||
|
||
## Manual installation
|
||
|
||
To get started on an existing project, install Pigment CSS with the following command:
|
||
|
||
<codeblock storageKey="framework">
|
||
|
||
```bash Next.js
|
||
npm install @pigment-css/react
|
||
npm install --save-dev @pigment-css/nextjs-plugin
|
||
```
|
||
|
||
```bash Vite
|
||
npm install @pigment-css/react
|
||
npm install --save-dev @pigment-css/vite-plugin
|
||
```
|
||
|
||
</codeblock>
|
||
|
||
Next, head over to your config file and import the `withPigment` plugin:
|
||
|
||
<codeblock storageKey="framework">
|
||
|
||
```js Next.js
|
||
// next.config.js
|
||
import { withPigment } from '@pigment-css/nextjs-plugin';
|
||
|
||
export default withPigment(nextConfig);
|
||
```
|
||
|
||
```ts Vite
|
||
// main.tsx
|
||
import { pigment } from '@pigment-css/vite-plugin';
|
||
|
||
export default defineConfig({
|
||
plugins: [
|
||
pigment(),
|
||
// ... Your other plugins.
|
||
],
|
||
});
|
||
```
|
||
|
||
</codeblock>
|
||
|
||
Finally, import the Pigment CSS stylesheet in your `layout.tsx` (Next.js) or `main.tsx` (Vite) file:
|
||
|
||
```js
|
||
import '@pigment-css/react/styles.css';
|
||
```
|
||
|
||
## Usage
|
||
|
||
Pigment CSS addresses the needs of modern React development: it's compatible with React Server Components and lets you reap the benefits of CSS-in-JS—all without runtime performance costs.
|
||
|
||
With Pigment CSS, you can create locally scoped reusable styles, themes, CSS variables, and more.
|
||
|
||
### Styling
|
||
|
||
Pigment CSS simplifies the creation and definition of styles through various APIs:
|
||
|
||
- `css`: for reusable styles
|
||
- `globalCss`: for global styles
|
||
- `keyframes`: for reusable animation keyframes
|
||
- `styled`: for styled components
|
||
|
||
#### Creating reusable styles
|
||
|
||
Use the `css` API to create reusable styles:
|
||
|
||
```js
|
||
import { css } from '@pigment-css/react';
|
||
```
|
||
|
||
You can do this with either template or object syntax:
|
||
|
||
**Template syntax**
|
||
|
||
```js
|
||
const bodyBackground = css`
|
||
background-color: #000;
|
||
color: #fff;
|
||
`;
|
||
```
|
||
|
||
**Object syntax**
|
||
|
||
```js
|
||
const mainClass = css({
|
||
display: '#000',
|
||
color: '#fff',
|
||
});
|
||
```
|
||
|
||
#### Creating global styles
|
||
|
||
Use the `globalCss` API to define global styles to load across an entire app.
|
||
|
||
You should define these at the top level of your JavaScript file:
|
||
|
||
```js
|
||
import { globalCss } from '@pigment-css/react';
|
||
|
||
globalCss`
|
||
body {
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
`;
|
||
```
|
||
|
||
#### Creating styled components
|
||
|
||
Keeping styles scoped to components ensures that only the necessary CSS is loaded and leads to better modularity, readability, and maintainability.
|
||
You can apply conditional styling to your components based on props or runtime values.
|
||
|
||
Use the `styled` API to create styled components:
|
||
|
||
```js
|
||
import { styled } from '@pigment-css/react';
|
||
|
||
const Heading = styled('div')({
|
||
fontSize: '2rem',
|
||
color: '#9FADBC',
|
||
fontWeight: 'bold',
|
||
margin: '1rem',
|
||
});
|
||
```
|
||
|
||
**Styling based on props**
|
||
|
||
Use the `variants` key to define different styling options based on props.
|
||
This approach is recommended when the value of the prop is known at build time.
|
||
|
||
Each of the `variants` is an object with `props` and `style` keys:
|
||
|
||
```js
|
||
import { styled } from '@pigment-css/react';
|
||
|
||
const Heading = styled('div')({
|
||
fontSize: '2rem',
|
||
color: '#9FADBC',
|
||
fontWeight: 'bold',
|
||
margin: '1rem',
|
||
variants: [
|
||
{
|
||
props: { variant: 'success' },
|
||
style: { color: '#23AD79' },
|
||
},
|
||
{
|
||
props: { size: 'small' },
|
||
style: { fontSize: '1.5rem' },
|
||
},
|
||
],
|
||
});
|
||
```
|
||
|
||
**Styling based on runtime values**
|
||
|
||
When the value of a prop is unknown ahead of time, you can style your components based on runtime values:
|
||
|
||
```js
|
||
const Heading = styled('h1')({
|
||
color: ({ isError }) => (isError ? 'red' : 'black'),
|
||
});
|
||
```
|
||
|
||
### Themes
|
||
|
||
Pigment CSS supports theming to apply consistent styles and values across your application.
|
||
You can create themes by defining them in your config file:
|
||
|
||
```js
|
||
import { withPigment } from '@pigment-css/nextjs-plugin';
|
||
|
||
export default withPigment(nextConfig, {
|
||
theme: {
|
||
colors: {
|
||
primary: 'tomato',
|
||
secondary: 'cyan',
|
||
},
|
||
spacing: {
|
||
unit: 8,
|
||
},
|
||
typography: {
|
||
fontFamily: 'Inter, sans-serif',
|
||
},
|
||
// ...more keys and values, it's free style!
|
||
},
|
||
});
|
||
```
|
||
|
||
To access your themes, use a callback with the `styled()` and `css()` APIs:
|
||
|
||
```js
|
||
const Heading = styled('h1')(({ theme }) => ({
|
||
color: theme.colors.primary,
|
||
fontSize: theme.spacing.unit * 4,
|
||
fontFamily: theme.typography.fontFamily,
|
||
}));
|
||
```
|
||
|
||
#### CSS variables support
|
||
|
||
Pigment CSS generates CSS variables from the theme values when they're wrapped by the `extendTheme` utility, creating a `vars` object:
|
||
|
||
```js
|
||
import { withPigment, extendTheme } from '@pigment-css/nextjs-plugin';
|
||
|
||
export default withPigment(nextConfig, {
|
||
theme: extendTheme({
|
||
colors: {
|
||
primary: 'tomato',
|
||
secondary: 'cyan',
|
||
},
|
||
spacing: {
|
||
unit: 8,
|
||
},
|
||
typography: {
|
||
fontFamily: 'Inter, sans-serif',
|
||
},
|
||
}),
|
||
});
|
||
```
|
||
|
||
#### Color schemes
|
||
|
||
You can use the `colorSchemes` key within the `extendTheme` utility to assign different values based on different conditions, such as switching between dark mode and light mode:
|
||
|
||
```js
|
||
extendTheme({
|
||
colorSchemes: {
|
||
light: {
|
||
colors: {
|
||
background: '#f9f9f9',
|
||
foreground: '#121212',
|
||
},
|
||
},
|
||
dark: {
|
||
colors: {
|
||
background: '#212121',
|
||
foreground: '#fff',
|
||
},
|
||
},
|
||
},
|
||
});
|
||
```
|
||
|
||
Pigment CSS uses the `prefers-color-scheme` media query by default to switch between color schemes:
|
||
|
||
```js
|
||
const colorScheme = css`
|
||
background-color: ${({ theme }) => theme.colorSchemes.dark.colors.background};
|
||
color: ${({ theme }) => theme.colorSchemes.dark.colors.foreground};
|
||
|
||
@media (prefers-color-scheme: light) {
|
||
background-color: ${({ theme }) => theme.colorSchemes.light.colors.background};
|
||
color: ${({ theme }) => theme.colorSchemes.light.colors.foreground};
|
||
}
|
||
`;
|
||
```
|
||
|
||
You can also customize the behavior by providing a `getSelector` function:
|
||
|
||
```diff
|
||
extendTheme({
|
||
colorSchemes: {
|
||
light: { ... },
|
||
dark: { ... },
|
||
},
|
||
+ getSelector: (colorScheme) => colorScheme ? `.theme-${colorScheme}` : ':root',
|
||
});
|
||
```
|
||
|
||
### The sx prop
|
||
|
||
Pigment CSS includes [the `sx` prop](/system/getting-started/the-sx-prop/) which lets you provide one-off inline custom styles to any element.
|
||
|
||
At build time, Pigment CSS replaces the `sx` prop with `className` and `style` props.
|
||
The `sx` prop works with all Material UI components as well as HTML elements and any third-party JSX components.
|
||
|
||
```js
|
||
<div sx={{ display: 'flex', flexDirection: 'column' }}>
|
||
|
||
<AnyComponent sx={{ fontSize: 12, color: 'red' }} />;
|
||
```
|
||
|
||
If you use the `sx` prop on an HTML element, you'll need to augment the `HTMLAttributes` interface:
|
||
|
||
```ts
|
||
type Theme = {
|
||
// your theme type
|
||
};
|
||
|
||
declare global {
|
||
namespace React {
|
||
interface HTMLAttributes<T> {
|
||
sx?:
|
||
| React.CSSProperties
|
||
| ((theme: Theme) => React.CSSProperties)
|
||
| ReadonlyArray<
|
||
React.CSSProperties | ((theme: Theme) => React.CSSProperties)
|
||
>;
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### Runtime theme
|
||
|
||
:::info
|
||
|
||
**Caveat**
|
||
|
||
- Avoid using the runtime theme unless you have a compelling reason.
|
||
- The runtime theme contains [**only serializable values**](https://developer.mozilla.org/en-US/docs/Glossary/Serializable_object) (some functions still exist in `breakpoints` and `transitions` for internal logic inside components but may be removed in the future).
|
||
- The runtime theme will not change between modes (light and dark) because it is pre-compiled at build time. To render something based on the theme structure and its values, use `theme.vars.*` to refer to CSS variables instead.
|
||
|
||
:::
|
||
|
||
To access the runtime theme, use the `useTheme` hook:
|
||
|
||
```js
|
||
import { useTheme } from '@mui/material-pigment-css';
|
||
|
||
function MyComponent() {
|
||
const theme = useTheme();
|
||
|
||
return (
|
||
<div>
|
||
{Object.entries(theme.vars.palette.primary).map(([key, value]) => (
|
||
<div key={key} style={{ width: 40, height: 40, background: value }}>
|
||
{key}: {value}
|
||
</div>
|
||
))}
|
||
</div>
|
||
);
|
||
}
|
||
```
|