
Security News
Deno 2.2 Improves Dependency Management and Expands Node.js Compatibility
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
styled-system
Advanced tools
Design system utilities for styled-components, glamorous, and other css-in-js libraries
Styled System is a utility for creating consistent, responsive, and theme-based design systems in React. It provides a set of functions and utilities to style components using a system of design tokens, such as spacing, colors, and typography, making it easier to build UI components that adhere to a design system.
Responsive Styles
Styled System allows you to define responsive styles using arrays. The `p` prop sets padding, `bg` sets background color, and `width` sets the width of the component. The values in the arrays correspond to different breakpoints.
const Box = styled.div`
${space}
${color}
${layout}
`;
<Box p={[1, 2, 3]} bg={['red', 'green', 'blue']} width={[1, 1/2, 1/4]} />
Theme-based Design
Styled System integrates with a theme object to provide consistent styling across your application. The `color` and `space` utilities use the theme to apply styles.
const theme = {
colors: {
primary: 'blue',
secondary: 'green',
},
space: [0, 4, 8, 16, 32],
};
const Box = styled.div`
${color}
${space}
`;
<Box color='primary' p={2} />
Utility Functions
Styled System provides utility functions like `space`, `color`, and `layout` that can be used to style components. These functions map props to CSS properties based on the theme.
import { space, color, layout } from 'styled-system';
const Box = styled.div`
${space}
${color}
${layout}
`;
<Box m={2} p={3} bg='primary' width={1/2} />
Emotion is a library designed for writing CSS styles with JavaScript. It provides powerful and flexible styling capabilities, including support for theming and responsive styles. Compared to Styled System, Emotion offers more granular control over CSS but requires more manual setup for design systems.
Styled-components is a library for styling React components using tagged template literals. It allows for writing actual CSS to style components and supports theming and dynamic styling. While it doesn't provide the same utility functions as Styled System, it can be used in conjunction with Styled System for a more comprehensive solution.
Tailwind CSS is a utility-first CSS framework that provides low-level utility classes for building custom designs. It offers a different approach compared to Styled System by using predefined classes instead of JavaScript functions. Tailwind CSS is highly customizable and can be used to create responsive and theme-based designs.
Design system utilities for styled-components and other css-in-js libraries
npm i styled-system
"The future of css-in-js is going to look something like styled-system with its responsive values."
– Kye Hohenberger
"Fantastic set of tools that offer the ease and API of tachyons/functional CSS but, are way more customisable." – Varun Vachhar
"Coming from @tachyons_css, the styled-system utilities from @jxnblk is the missing link I’ve been looking for."
– Nathan Young
// Example uses styled-components, but styled-system works with most other css-in-js libraries as well
import styled from 'styled-components'
import { space, width, fontSize, color } from 'styled-system'
// Add styled-system functions to your component
const Box = styled.div`
${space}
${width}
${fontSize}
${color}
`
Each style function exposes its own set of props that style elements based on values defined in a theme.
// width: 50%
<Box width={1/2} />
// font-size: 20px (theme.fontSizes[4])
<Box fontSize={4} />
// margin: 16px (theme.space[2])
<Box m={2} />
// padding: 32px (theme.space[3])
<Box p={3} />
// color
<Box color='tomato' />
// color: #333 (theme.colors.gray[0])
<Box color='grays.0' />
// background color
<Box bg='tomato' />
Set responsive width, margin, padding, font-size, and other properties with a shorthand array syntax. Read more
// responsive width
<Box width={[ 1, 1/2, 1/4 ]} />
// responsive font-size
<Box fontSize={[ 2, 3, 4 ]} />
// responsive margin
<Box m={[ 1, 2, 3 ]} />
// responsive padding
<Box p={[ 1, 2, 3 ]} />
Although it's not required, styled-system works best with a theme that's tailored to your own custom styles.
Create a theme.js
file that exports an object and add a ThemeProvider
to the root of your application.
// empty theme.js
const theme = {}
export default theme
// root App component
import React from 'react'
import { ThemeProvider } from 'styled-components'
import theme from './theme'
const App = props => (
<ThemeProvider theme={theme}>
{/* ... */}
</ThemeProvider>
)
Most utility functions in styled-system will attempt to find a value from your theme first,
then fallback to a hard-coded value if it hasn't been defined in your theme.
For example, defining a colors
object can make using a common color palette across your app simpler.
// theme.js
const colors = {
text: '#024',
blue: '#07c'
}
const theme = {
colors
}
export default theme
With a component that uses the color
function from styled-system, the name of the color defined in your theme can be used as a prop.
// picks up the value `#07c` from the theme
<Box color='blue' />
When a value is passed that's not in the theme, it will be passed as a raw value.
// renders the CSS `tomato` color since it's not defined in theme
<Box color='tomato' />
It's recommended to add objects and array scales to your theme to ensure consistent, constraint-based values are used throughout your app. All theme values are optional, so use your own discretion when creating a theme. See the Default Theme section for a reference to the default fallback values.
// theme.js
// breakpoint values
// any array length works with styled-system
const breakpoints = [
'40em', '52em', '64em'
]
const colors = {
text: '#024',
blue: '#07c',
// nested objects work as well
dark: {
blue: '#058'
},
// arrays can be used for scales of colors
gray: [
'#333',
'#666',
'#999',
'#ccc',
'#eee',
'#f6f6f6',
]
}
// space is used for margin and padding scales
// it's recommended to use powers of two to ensure alignment
// when used in nested elements
// numbers are converted to px
const space = [
0, 4, 8, 16, 32, 64, 128, 256, 512
]
// typographic scale
const fontSizes = [
12, 14, 16, 20, 24, 32, 48, 64, 96, 128
]
// for any scale, either array or objects will work
const lineHeights = [
1, 1.125, 1.25, 1.5
]
const fontWeights = {
normal: 500,
bold: 700
}
const letterSpacings = {
normal: 'normal',
caps: '0.25em'
}
// border-radius
const radii = [
0, 2, 4, 8
]
const borderWidths = [
0, 1, 2
]
const shadows = [
`0 1px 2px 0 ${colors.text}`,
`0 1px 4px 0 ${colors.text}`
]
const theme = {
breakpoints,
colors,
space,
fontSizes,
lineHeights,
fontWeights,
letterSpacings,
radii,
borderWidths,
shadows,
}
export default theme
Next, create a set of UI components that provide convenient style props to the values defined in the theme. It's recommended to keep components simple and focused on doing one thing well. For UI components, it's common to separate them according to different concerns, such as layout, typography, and other styles. However, there may be some general purpose style props that you'd like to apply consistently across your entire component set, such as margin, padding, and color.
import styled from 'styled-components'
import {
space,
color,
width,
fontSize,
fontWeight,
textAlign,
lineHeight
} from 'styled-system'
// Example of a general purpose Box layout component
export const Box = styled.div`
${space}
${color}
${width}
`
// General purpose typographic component
export const Text = styled.div`
${space}
${color}
${fontSize}
${fontWeight}
${textAlign}
${lineHeight}
`
Most CSS-in-JS libraries accept functions as arguments to create dynamic styles based on props.
For example, the following sets color dynamically in styled-components based on the color
prop:
import styled from 'styled-components'
const Box = styled.div`
color: ${props => props.color};
`
Beyond just passing a dynamic value, an entire style declaration can be returned in functions like this.
import styled from 'styled-components'
const getColor = props => `color: ${props.color};`
const Box = styled.div`
${getColor}
`
Style object can also be returned, which is a much simpler way to handle dynamic values in JavaScript.
import styled from 'styled-components'
// works exactly the same as the previous function
const getColor = props => ({
color: props.color
})
const Box = styled.div`
${getColor}
`
By using style objects instead of embedded CSS strings, styled-system is compatible with other libraries, such as glamorous and emotion.
The core utilities in styled-system are built on this pattern and consist of functions that take props
as an argument
and return style objects,
while making it simpler to use values from a theme and apply styles responsively across breakpoints.
These style functions can be written on a one-off basis, but styled-system is meant to help reduce boilerplate, ensure a consistent styling API, and speed the development of React-based design systems.
Often when working on responsive layouts, it's useful to adjust styles across a singular dimension – such as font-size, margin, padding, and width. Instead of manually managing media queries and adding nested style objects throughout a code base, styled-system offers a convenient shorthand syntax for adding responsive styles with a mobile-first approach. While this syntax can seem odd at first, it can become a powerful way to manage responsive typography and layouts.
All core props accept arrays as values for mobile-first responsive styles.
<Box
width={[
1, // 100% below the smallest breakpoint
1/2, // 50% from the next breakpoint and up
1/4 // 25% from the next breakpoint and up
]}
/>
// responsive font size
<Box fontSize={[ 1, 2, 3, 4 ]} />
// responsive margin
<Box m={[ 1, 2, 3, 4 ]} />
// responsive padding
<Box p={[ 1, 2, 3, 4 ]} />
import { space } from 'styled-system'
The space utility converts shorthand margin and padding props to margin and padding CSS declarations.
theme.space
) are converted to values on the spacing scale.theme.space
array are converted to raw pixel values.Margin and padding props follow a shorthand syntax for specifying direction.
m
: marginmt
: margin-topmr
: margin-rightmb
: margin-bottomml
: margin-leftmx
: margin-left and margin-rightmy
: margin-top and margin-bottomp
: paddingpt
: padding-toppr
: padding-rightpb
: padding-bottompl
: padding-leftpx
: padding-left and padding-rightpy
: padding-top and padding-bottom// examples (margin prop)
// sets margin value of `theme.space[2]`
<Box m={2} />
// sets margin value of `-1 * theme.space[2]`
<Box m={-2} />
// sets a margin value of `16px` since it's greater than `theme.space.length`
<Box m={16} />
// sets margin `'auto'`
<Box m='auto' />
// sets margin `8px` on all viewports and `16px` from the smallest breakpoint and up
<Box m={[ 1, 2 ]} />
import { width } from 'styled-system'
The width utility parses a component's width
prop and converts it into a CSS width declaration.
// examples
// width `50%`
<Box width={1/2} />
// width `256px`
<Box width={256} />
// width `'2em'`
<Box width='2em' />
// width `100%` on all viewports and `50%` from the smallest breakpoint and up
<Box width={[ 1, 1/2 ]} />
import { fontSize } from 'styled-system'
The fontSize utility parses a component's fontSize
prop and converts it into a CSS font-size declaration.
theme.fontSizes.length
) are converted to values on the font size scale.theme.fontSizes.length
are converted to raw pixel values.// examples
// font-size of `theme.fontSizes[3]`
<Text fontSize={3} />
// font-size `32px`
<Text fontSize={32} />
// font-size `'2em'`
<Text fontSize='2em' />
// font-size `10px` on all viewports and `12px` from the smallest breakpoint and up
<Text fontSize={[ 10, 12 ]} />
import { color } from 'styled-system'
The color utility parses a component's color
and bg
props and converts them into CSS declarations.
By default the raw value of the prop is returned.
Color palettes can be configured with the ThemeProvider to use keys as prop values, with support for dot notation.
Array values are converted into responsive values.
// examples
// picks the value defined in `theme.colors['blue']`
<Box color='blue' />
// picks up a nested color value using dot notation
// `theme.colors['gray'][0]`
<Box color='gray.0' />
// raw CSS color value
<Box color='#f00' />
These functions are for adding other theme-based style props to a component. For practical reasons, some props do not accept arrays for responsive styles.
import { textAlign } from 'styled-system'
<Text align='center' />
import { lineHeight } from 'styled-system'
<Text lineHeight={1} />
// props.theme.lineHeights[1]
import { fontWeight } from 'styled-system'
<Text fontWeight='bold' />
// props.theme.fontWeights.bold
import { letterSpacing } from 'styled-system'
<Text letterSpacing={1} />
// props.theme.letterSpacings[1]
import { alignItems } from 'styled-system'
<Flex align='center' />
import { justifyContent } from 'styled-system'
<Flex justify='center' />
import { flexWrap } from 'styled-system'
<Flex wrap />
import { flexDirection } from 'styled-system'
<Flex flexDirection='column' />
import { flex } from 'styled-system'
<Box flex='none' />
import { alignSelf } from 'styled-system'
<Box alignSelf='baseline' />
import { borderRadius } from 'styled-system'
<Box borderRadius={1} />
// props.theme.radii[1]
import { borderColor } from 'styled-system'
<Box borderColor='blue' />
// props.theme.colors.blue
import { borderWidth } from 'styled-system'
<Box borderWidth={1} />
// props.theme.borderWidths
// Only apply border in one direction
<Box borderWidth={1} borderBottom />
// Or in multiple directions
<Box borderWidth={1} borderTop borderBottom />
import { boxShadow } from 'styled-system'
<Box boxShadow={1} />
// props.theme.shadows[1]
<Box boxShadow='large' />
// props.theme.shadows.large
// raw value
<Box boxShadow='1px 1px 0 black' />
Pseudo-class utility props accept style objects that can pick up certain values, such as color, from a theme.
import { hover } from 'styled-system'
<Box
hover={{
textDecoration: 'underline',
color: 'blue'
}}
/>
// props.theme.colors.blue
import { focus } from 'styled-system'
<Box focus={{ color: 'blue' }} />
// props.theme.colors.blue
import { active } from 'styled-system'
<Box active={{ color: 'navy' }} />
// props.theme.colors.navy
import { disabled } from 'styled-system'
<Box disabledStyle={{ color: 'gray' }} />
// props.theme.colors.gray
Function Name | Prop | CSS Property | Theme Field | Responsive |
---|---|---|---|---|
space | m | margin | space | yes |
space | mt | margin-top | space | yes |
space | mr | margin-right | space | yes |
space | mb | margin-bottom | space | yes |
space | ml | margin-left | space | yes |
space | p | padding | space | yes |
space | pt | padding-top | space | yes |
space | pr | padding-right | space | yes |
space | pb | padding-bottom | space | yes |
space | pl | padding-left | space | yes |
width | width w | width | none | yes |
fontSize | fontSize f | font-size | fontSizes | yes |
color | color | color | colors | yes |
color | bg | background-color | colors | yes |
textAlign | align | text-align | none | yes |
lineHeight | lineHeight | line-height | lineHeights | no |
fontWeight | fontWeight | font-weight | fontWeights | no |
letterSpacing | letterSpacing | letter-spacing | letterSpacings | no |
alignItems | align | align-items | none | yes |
justifyContent | justify | justify-content | none | yes |
flexWrap | wrap (boolean) | flex-wrap | none | yes |
flexDirection | flexDirection | flex-direction | none | yes |
flex | flex | flex (shorthand) | none | yes |
alignSelf | alignSelf | align-self | none | yes |
borderRadius | borderRadius | border-radius | radii | no |
borderColor | borderColor | border-color | colors | no |
borderWidth | borderWidth | border-width | borderWidths | no |
boxShadow | boxShadow | box-shadow | shadows | no |
The theme function is an existential getter function that can be used in any style declaration to get a value from your theme, with support for fallback values. This helps prevent errors from throwing when a theme value is missing, which can be helpful when unit testing styled-components.
theme(objectPath, fallbackValue)
import styled from 'styled-components'
import { theme } from 'styled-system'
const Box = styled.div`
border-radius: ${theme('radii.small', '4px')};
`
Prop type definitions are available for each style function to add to your component's propTypes object.
Each value in propTypes
is an object which should be assigned (or spread) to the component's propTypes
.
import styled from 'styled-components'
import { width, propTypes } from 'styled-system'
const Box = styled.div`
${width}
`
Box.propTypes = {
...propTypes.width
}
Styled-components and other libraries attempt to remove invalid HTML attributes from props using a whitelist,
but do not remove width
, fontSize
, color
, or other valid HTML attributes when used as props.
To ensure that style props are not passed on to the underlying DOM element,
even in cases where a prop is a valid HTML attribute, like width
or align
, use the cleanElement
higher order component to create a base component
that remove props defined in propTypes
.
import styled from 'styled-components'
import { textAlign, propTypes, cleanElement } from 'styled-system'
const CleanDiv = cleanElement('div')
// props that are defined as propTypes are removed
CleanDiv.propTypes = {
...propTypes.textAlign
}
const Box = styled(CleanDiv)`
${textAlign}
`
// <Box align='center' />
// `align` prop is picked up by styled-components,
// but not passed on to the HTML element
Manually omitting props
As an alternative to using the cleanElement
function, removing style props from styled-components can be done manually, with a more React-like approach.
import React from 'react'
import styled from 'styled-components'
import { width, color } from' styled-system'
const Box = styled(({
width,
color,
bg,
...props
}) => <div {...props} />)`
${width}
${color}
`
See this discussion for more information: https://github.com/styled-components/styled-components/issues/439
To create custom utilities for other CSS properties, use the following low-level utility functions.
Create a non-responsive style utility.
import styled from 'styled-components'
import { style } from 'styled-system'
const textShadow = style({
// React prop name
prop: 'shadow',
// The corresponding CSS property
cssProperty: 'textShadow',
// set a key to find values from `props.theme`
key: 'shadows'
// convert number values to pixels
numberToPx: false
})
const ShadowText = styled(Text)`
${textShadow}
`
// with a `theme.shadows` array
const App = props => (
<ShadowText shadow={0}>
Shady
</ShadowText>
)
Create a responsive style utility that accepts array-based responsive prop values.
import styled from 'styled-components'
import { responsiveStyle } from 'styled-system'
const borderRadius = responsiveStyle({
prop: 'borderRadius',
cssProperty: 'borderRadius',
// convert number values to pixels
numberToPx: true,
// set a key for values in theme
key: 'radii'
})
const RoundedBox = styled.div`
${borderRadius}
`
const App = props => (
<RoundedBox borderRadius={[ 0, 2 ]} />
)
Create a pseudo-class style utility that accepts a style object prop value.
import styled from 'styled-components'
import { pseudoStyle } from 'styled-system'
const checkedStyle = pseudoStyle('checked', 'checkedStyle')({
// keys for theme-based values
color: 'colors',
backgroundColor: 'colors',
})
const FancyCheckbox = styled.input`
/* ...base styles */
${checkedStyle}
`
FancyCheckbox.defaultProps = {
type: 'checkbox'
}
// <FancyCheckbox checkedStyle={{ backgroundColor: 'blue' }} />
For an even simpler authoring experience when using styled-system with styled-components, see system-components, which is a lightweight wrapper around the two libraries.
import system from 'system-components'
// creates a Box component with default props tied to your theme
const Box = system({
p: 2,
bg: 'blue'
})
If no theme is provided, styled-system uses smart defaults for breakpoints, the typographic scale, and the spacing scale.
// Breakpoints
const breakpoints = [ '40em', '52em', '64em' ]
// @media screen and (min-width: 40em)
// @media screen and (min-width: 52em)
// @media screen and (min-width: 64em)
// Other units work as well, but em units are recommended
// const breakpoints = [ '300px', '600px', '1200px' ]
// Typographic Scale
// numbers are converted to px values
const fontSizes = [ 12, 14, 16, 20, 24, 32, 48, 64, 72 ]
// Spacing Scale
// used for margin and padding
const space = [ 0, 8, 16, 32, 64 ]
See cleanElement
If you encounter issues while using this library alongside the prop-types
npm package,
webpack's resolve.modules
option might be misconfigured using a relative (instead of absolute) path.
This changes the way CommonJS modules work in a way that will likely cause other issues,
and it's recommended that you only use absolute paths with the resolve.modules
option.
If you're using resolve.modules
to avoid import syntax with lots of directory changes,
you might want to consider using a flatter or better organized folder structure in your app.
See https://github.com/jxnblk/grid-styled/issues/51#issuecomment-336116426
FAQs
Responsive, theme-based style props for building design systems with React
The npm package styled-system receives a total of 521,991 weekly downloads. As such, styled-system popularity was classified as popular.
We found that styled-system demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
Security News
React's CRA deprecation announcement sparked community criticism over framework recommendations, leading to quick updates acknowledging build tools like Vite as valid alternatives.
Security News
Ransomware payment rates hit an all-time low in 2024 as law enforcement crackdowns, stronger defenses, and shifting policies make attacks riskier and less profitable.