The simplest way to add CSS styles to your React components.
See the code
The easiest way to add CSS styles to your React components.
No configuration required.
2.2kb minified and gzippedcss prop with JSX pragmanpm install restyle
import { styled } from 'restyle'
export const Box = styled('div', {
padding: '1rem',
backgroundColor: 'peachpuff',
})
Restyle leverages React's new ability to hoist style elements by generating atomic CSS on-demand to provide a flexible and efficient styling solution for React components.
Here's a high-level overview of how it works:
import { css } from 'restyle'
const [classNames, Styles] = css({
padding: '1rem',
backgroundColor: 'peachpuff',
})
// classNames: 'x1y2 x3z4'
// Styles: <style>.x1y2{padding:1rem}.x3z4{background-color:peachpuff}</style>
import { css } from 'restyle'
const [classNames] = css({
padding: '1rem',
backgroundColor: 'tomato',
})
// Example output: 'x1y2 xfg3'
import { css } from 'restyle'
const styles = {
padding: '1rem',
backgroundColor: 'rebeccapurple',
}
const [classNames, Styles] = css(styles)
// classNames: 'x1y2 x4z1'
// Reuse class names for other elements
const buttonStyles = {
...styles,
border: '1px solid black',
}
const [buttonClassNames, ButtonStyles] = css(buttonStyles)
// buttonClassNames: 'x1y2 x4z1 x5a6'
import { css } from 'restyle'
export default function OnDemandStyles() {
const [classNames, Styles] = css({
padding: '1rem',
backgroundColor: 'papayawhip',
})
return (
<div className={classNames}>
Hello World
<Styles />
</div>
)
}
css prop via the JSX pragma, allowing colocated inline CSS styles directly on JSX elements./** @jsxImportSource restyle */
export default function MyComponent() {
return (
<div
css={{
padding: '1rem',
backgroundColor: 'peachpuff',
}}
>
Hello World
</div>
)
}
The styled utility is a higher-order function that takes an HTML element tag name or a component that accepts a className prop and a initial styles object that returns a styled component that can accept a css prop:
import Link from 'next/link'
import { styled } from 'restyle'
const StyledLink = styled(Link, {
color: 'rebeccapurple',
textDecoration: 'none',
})
The second argument to the styled utility also accepts a style resolver function that returns an object of styles based on the props passed to the component, referred to as style props. This is useful for creating components that accept dynamic styles based on props.
For example, you can create a Grid component that accepts gridTemplateColumns and gridTemplateRows props:
import { styled } from 'restyle'
interface GridStyleProps {
gridTemplateColumns: string
gridTemplateRows: string
}
const Grid = styled('div', (styleProps: GridStyleProps) => ({
display: 'grid',
gridTemplateColumns: styleProps.gridTemplateColumns,
gridTemplateRows: styleProps.gridTemplateRows,
}))
Now you can use these props to style the component:
<Grid gridTemplateColumns="repeat(3, 1fr)">
<div>1</div>
<div>2</div>
<div>3</div>
</Grid>
[!IMPORTANT] A proxy is used to differentiate between style props and those passed directly to the component. Only style props should be accessed from the first parameter of the style resolver function to ensure proper filtering.
To access the props passed to the component, you can use the second parameter of the style resolver function. This is useful for applying styles based on props that are not style props:
import { styled } from 'restyle'
interface ButtonStyleProps {
backgroundColor: string
color: string
}
const Button = styled('button', (styleProps: ButtonStyleProps, props) => ({
backgroundColor: styleProps.backgroundColor,
color: styleProps.color,
opacity: props.disabled ? 0.6 : 1,
}))
The css function returns a tuple of class names and the style tags to render. You can use the class names to apply styles to an element and the style tag to inject the styles into the head of the document:
import React from 'react'
import { css } from 'restyle'
export default function BasicUsage() {
const [classNames, Styles] = css({
padding: '1rem',
backgroundColor: 'peachpuff',
})
return (
<>
<div className={classNames}>Hello World</div>
<Styles />
</>
)
}
The css function is most useful for components. However, you can use the css prop to style elements directly. The pragma will take care of applying the class names and injecting the style tag.
First, configure the pragma in your tsconfig.json file:
{
"compilerOptions": {
"jsxImportSource": "restyle"
}
}
Now, you can use the css prop to style elements:
export default function CSSProp() {
return (
<div
css={{
padding: '1rem',
backgroundColor: 'peachpuff',
}}
>
Hello World
</div>
)
}
Alternatively, you can set the pragma at the top of the file:
/** @jsxImportSource restyle */
export default function CSSProp() {
return (
<div
css={{
padding: '1rem',
backgroundColor: 'peachpuff',
}}
>
Hello World
</div>
)
}
/** @jsxImportSource restyle */
export default function MediaQueries() {
return (
<h1
css={{
fontSize: '2rem',
'@media screen and (min-width: 40em)': {
fontSize: '3.5rem',
},
}}
>
Resize the window
</h1>
)
}
An additional media utility is available to help with creating typed media query keys from objects:
/** @jsxImportSource restyle */
import { media } from 'restyle'
export default function MediaQueries() {
return (
<h1
css={{
fontSize: '2rem',
[media({ screen: true, minWidth: '40em' })]: {
fontSize: '3.5rem',
},
}}
>
Resize the window
</h1>
)
}
Use the keyframes utility to easily create CSS animations:
import { keyframes, styled } from 'restyle'
const FadeInKeyframes = keyframes({
from: { opacity: 0 },
to: { opacity: 1 },
})
const FadeIn = styled('div', {
animation: `${FadeInKeyframes} 1s ease-in-out`,
})
export default function FadeInComponent() {
return (
<>
<FadeInKeyframes />
<FadeIn>Hello World</FadeIn>
</>
)
}
Use the GlobalStyles component to inject global styles into the document. This is useful for setting default styles for the body, headings, etc. This component accepts an object of styles and injects them into the head of the document based on their order in the object as well as when they are rendered in the react tree. Note, styles will not be removed when the component is unmounted. React makes no guarantees about when styles are removed from the document.
import { GlobalStyles } from 'restyle'
export default function Layout({ children }) {
return (
<>
<GlobalStyles>
{{
body: {
margin: 0,
padding: 0,
fontFamily: 'sans-serif',
},
}}
</GlobalStyles>
{children}
</>
)
}
The GlobalStyles component can be used to define CSS variable themes that can be used throughout your application:
import { GlobalStyles, styled } from 'restyle'
const Container = styled('div', {
backgroundColor: 'var(--background)',
color: 'var(--foreground)',
minHeight: '100vh',
display: 'grid',
placeItems: 'center',
})
const Button = styled('button', {
padding: '0.5rem 1rem',
borderRadius: '0.1rem',
backgroundColor: 'var(--button-background)',
color: 'var(--button-foreground)',
border: 'none',
cursor: 'pointer',
})
export default function App() {
return (
<>
<GlobalStyles>
{{
':root': {
'--background': '#ffffff',
'--foreground': '#000000',
'--button-background': '#007bff',
'--button-foreground': '#ffffff',
},
'@media (prefers-color-scheme: dark)': {
':root': {
'--background': '#000000',
'--foreground': '#ffffff',
'--button-background': '#1a73e8',
'--button-foreground': '#ffffff',
},
},
}}
</GlobalStyles>
<Container>
<Button>Themed Button</Button>
</Container>
</>
)
}
Variants can be achieved by using the style props pattern. For example, you can create an Alert component that accepts a variant prop that applies different styles based on the variant:
import { styled, type CSSObject } from 'restyle'
type AlertVariant = 'note' | 'success' | 'warning'
const variantStyles = {
note: {
backgroundColor: '#1b487d',
borderLeftColor: '#82aaff',
},
success: {
backgroundColor: '#2b7b3d',
borderLeftColor: '#5bc873',
},
warning: {
backgroundColor: '#b36b00',
borderLeftColor: '#ffb830',
},
} satisfies Record<AlertVariant, CSSObject>
export const Alert = styled('div', (props: { variant: AlertVariant }) => {
return {
padding: '1.5rem 2rem',
borderRadius: '0.5rem',
color: 'white',
...variantStyles[props.variant],
}
})
/** @jsxImportSource restyle */
export default function Hover() {
return (
<div
css={{
':hover': {
opacity: 0.8,
},
}}
>
Hover me
</div>
)
}
/** @jsxImportSource restyle */
export default function ChildSelectors() {
return (
<div
css={{
color: 'black',
'> a': {
color: 'tomato',
},
}}
>
Parent
<a href="#">Link</a>
</div>
)
}
This project is inspired by and builds upon the ideas and work of several other projects in the CSS-in-JS ecosystem:
css propstyled functionThank you to WebReflection for the restyle NPM package name.
In one terminal, run the following command to build the library and watch for changes:
npm install
npm run dev
In another terminal, run the following command to start the development server for the site:
cd site
npm install
npm run dev
TypeScript
90.6%
MDX
8.2%
The simplest way to add CSS styles to your React components.
See the code
The easiest way to add CSS styles to your React components.
No configuration required.
2.2kb minified and gzippedcss prop with JSX pragmanpm install restyle
import { styled } from 'restyle'
export const Box = styled('div', {
padding: '1rem',
backgroundColor: 'peachpuff',
})
Restyle leverages React's new ability to hoist style elements by generating atomic CSS on-demand to provide a flexible and efficient styling solution for React components.
Here's a high-level overview of how it works:
import { css } from 'restyle'
const [classNames, Styles] = css({
padding: '1rem',
backgroundColor: 'peachpuff',
})
// classNames: 'x1y2 x3z4'
// Styles: <style>.x1y2{padding:1rem}.x3z4{background-color:peachpuff}</style>
import { css } from 'restyle'
const [classNames] = css({
padding: '1rem',
backgroundColor: 'tomato',
})
// Example output: 'x1y2 xfg3'
import { css } from 'restyle'
const styles = {
padding: '1rem',
backgroundColor: 'rebeccapurple',
}
const [classNames, Styles] = css(styles)
// classNames: 'x1y2 x4z1'
// Reuse class names for other elements
const buttonStyles = {
...styles,
border: '1px solid black',
}
const [buttonClassNames, ButtonStyles] = css(buttonStyles)
// buttonClassNames: 'x1y2 x4z1 x5a6'
import { css } from 'restyle'
export default function OnDemandStyles() {
const [classNames, Styles] = css({
padding: '1rem',
backgroundColor: 'papayawhip',
})
return (
<div className={classNames}>
Hello World
<Styles />
</div>
)
}
css prop via the JSX pragma, allowing colocated inline CSS styles directly on JSX elements./** @jsxImportSource restyle */
export default function MyComponent() {
return (
<div
css={{
padding: '1rem',
backgroundColor: 'peachpuff',
}}
>
Hello World
</div>
)
}
The styled utility is a higher-order function that takes an HTML element tag name or a component that accepts a className prop and a initial styles object that returns a styled component that can accept a css prop:
import Link from 'next/link'
import { styled } from 'restyle'
const StyledLink = styled(Link, {
color: 'rebeccapurple',
textDecoration: 'none',
})
The second argument to the styled utility also accepts a style resolver function that returns an object of styles based on the props passed to the component, referred to as style props. This is useful for creating components that accept dynamic styles based on props.
For example, you can create a Grid component that accepts gridTemplateColumns and gridTemplateRows props:
import { styled } from 'restyle'
interface GridStyleProps {
gridTemplateColumns: string
gridTemplateRows: string
}
const Grid = styled('div', (styleProps: GridStyleProps) => ({
display: 'grid',
gridTemplateColumns: styleProps.gridTemplateColumns,
gridTemplateRows: styleProps.gridTemplateRows,
}))
Now you can use these props to style the component:
<Grid gridTemplateColumns="repeat(3, 1fr)">
<div>1</div>
<div>2</div>
<div>3</div>
</Grid>
[!IMPORTANT] A proxy is used to differentiate between style props and those passed directly to the component. Only style props should be accessed from the first parameter of the style resolver function to ensure proper filtering.
To access the props passed to the component, you can use the second parameter of the style resolver function. This is useful for applying styles based on props that are not style props:
import { styled } from 'restyle'
interface ButtonStyleProps {
backgroundColor: string
color: string
}
const Button = styled('button', (styleProps: ButtonStyleProps, props) => ({
backgroundColor: styleProps.backgroundColor,
color: styleProps.color,
opacity: props.disabled ? 0.6 : 1,
}))
The css function returns a tuple of class names and the style tags to render. You can use the class names to apply styles to an element and the style tag to inject the styles into the head of the document:
import React from 'react'
import { css } from 'restyle'
export default function BasicUsage() {
const [classNames, Styles] = css({
padding: '1rem',
backgroundColor: 'peachpuff',
})
return (
<>
<div className={classNames}>Hello World</div>
<Styles />
</>
)
}
The css function is most useful for components. However, you can use the css prop to style elements directly. The pragma will take care of applying the class names and injecting the style tag.
First, configure the pragma in your tsconfig.json file:
{
"compilerOptions": {
"jsxImportSource": "restyle"
}
}
Now, you can use the css prop to style elements:
export default function CSSProp() {
return (
<div
css={{
padding: '1rem',
backgroundColor: 'peachpuff',
}}
>
Hello World
</div>
)
}
Alternatively, you can set the pragma at the top of the file:
/** @jsxImportSource restyle */
export default function CSSProp() {
return (
<div
css={{
padding: '1rem',
backgroundColor: 'peachpuff',
}}
>
Hello World
</div>
)
}
/** @jsxImportSource restyle */
export default function MediaQueries() {
return (
<h1
css={{
fontSize: '2rem',
'@media screen and (min-width: 40em)': {
fontSize: '3.5rem',
},
}}
>
Resize the window
</h1>
)
}
An additional media utility is available to help with creating typed media query keys from objects:
/** @jsxImportSource restyle */
import { media } from 'restyle'
export default function MediaQueries() {
return (
<h1
css={{
fontSize: '2rem',
[media({ screen: true, minWidth: '40em' })]: {
fontSize: '3.5rem',
},
}}
>
Resize the window
</h1>
)
}
Use the keyframes utility to easily create CSS animations:
import { keyframes, styled } from 'restyle'
const FadeInKeyframes = keyframes({
from: { opacity: 0 },
to: { opacity: 1 },
})
const FadeIn = styled('div', {
animation: `${FadeInKeyframes} 1s ease-in-out`,
})
export default function FadeInComponent() {
return (
<>
<FadeInKeyframes />
<FadeIn>Hello World</FadeIn>
</>
)
}
Use the GlobalStyles component to inject global styles into the document. This is useful for setting default styles for the body, headings, etc. This component accepts an object of styles and injects them into the head of the document based on their order in the object as well as when they are rendered in the react tree. Note, styles will not be removed when the component is unmounted. React makes no guarantees about when styles are removed from the document.
import { GlobalStyles } from 'restyle'
export default function Layout({ children }) {
return (
<>
<GlobalStyles>
{{
body: {
margin: 0,
padding: 0,
fontFamily: 'sans-serif',
},
}}
</GlobalStyles>
{children}
</>
)
}
The GlobalStyles component can be used to define CSS variable themes that can be used throughout your application:
import { GlobalStyles, styled } from 'restyle'
const Container = styled('div', {
backgroundColor: 'var(--background)',
color: 'var(--foreground)',
minHeight: '100vh',
display: 'grid',
placeItems: 'center',
})
const Button = styled('button', {
padding: '0.5rem 1rem',
borderRadius: '0.1rem',
backgroundColor: 'var(--button-background)',
color: 'var(--button-foreground)',
border: 'none',
cursor: 'pointer',
})
export default function App() {
return (
<>
<GlobalStyles>
{{
':root': {
'--background': '#ffffff',
'--foreground': '#000000',
'--button-background': '#007bff',
'--button-foreground': '#ffffff',
},
'@media (prefers-color-scheme: dark)': {
':root': {
'--background': '#000000',
'--foreground': '#ffffff',
'--button-background': '#1a73e8',
'--button-foreground': '#ffffff',
},
},
}}
</GlobalStyles>
<Container>
<Button>Themed Button</Button>
</Container>
</>
)
}
Variants can be achieved by using the style props pattern. For example, you can create an Alert component that accepts a variant prop that applies different styles based on the variant:
import { styled, type CSSObject } from 'restyle'
type AlertVariant = 'note' | 'success' | 'warning'
const variantStyles = {
note: {
backgroundColor: '#1b487d',
borderLeftColor: '#82aaff',
},
success: {
backgroundColor: '#2b7b3d',
borderLeftColor: '#5bc873',
},
warning: {
backgroundColor: '#b36b00',
borderLeftColor: '#ffb830',
},
} satisfies Record<AlertVariant, CSSObject>
export const Alert = styled('div', (props: { variant: AlertVariant }) => {
return {
padding: '1.5rem 2rem',
borderRadius: '0.5rem',
color: 'white',
...variantStyles[props.variant],
}
})
/** @jsxImportSource restyle */
export default function Hover() {
return (
<div
css={{
':hover': {
opacity: 0.8,
},
}}
>
Hover me
</div>
)
}
/** @jsxImportSource restyle */
export default function ChildSelectors() {
return (
<div
css={{
color: 'black',
'> a': {
color: 'tomato',
},
}}
>
Parent
<a href="#">Link</a>
</div>
)
}
This project is inspired by and builds upon the ideas and work of several other projects in the CSS-in-JS ecosystem:
css propstyled functionThank you to WebReflection for the restyle NPM package name.
In one terminal, run the following command to build the library and watch for changes:
npm install
npm run dev
In another terminal, run the following command to start the development server for the site:
cd site
npm install
npm run dev
TypeScript
90.6%
MDX
8.2%