Build a Box
One of the most widely used styled component types is the coveted Box layout component. While many component libraries include a Box layout component already, you may want to create your own depending on the needs of your application. This guide will walk through creating a Multi purpose Box component and show you how you can add additional functionality using Styled System.
Import styled-components
and create a new component.
// example Box.js
import styled from 'styled-components'
const Box = styled.div({})
export default Box
Base Styles
Add some base-level styles to the component.
Use boxSizing: 'border-box'
to ensure that padding is included in width,
and use minWidth: 0
to ensure the Box can shrink below its minimum content size when used as a flex item.
const Box = styled.div({
boxSizing: 'border-box',
minWidth: 0,
})
Style Props
Next, import a few core Styled System functions to expose styles as props. As a general rule of thumb, you should only expose style props when it's something likely to change on a per-instance basis throughout your app. For styles that don't change frequently, it's generally better to extend the component.
// example Box.js
import styled from 'styled-components'
import { space, color, layout } from '@techstack/styled-system'
const Box = styled.div(
{
boxSizing: 'border-box',
minWidth: 0,
},
space,
color,
layout
)
export default Box
With the component created above, you can quickly change styling contextually throughout your application.
// example usage
<Box width={[1, 1 / 2]} p={4} mb={3} bg="tomato">
This is a tomato box, with responsive width, some padding, and margin bottom
</Box>
Flex Item Props
If you intend to use the Box component with flexbox, adding some more flexbox-specific style props can be helpful. Add the following props to the Box.
// example Box.js
import styled from 'styled-components'
import { space, color, layout, flexbox } from '@techstack/styled-system'
const Box = styled.div(
{
boxSizing: 'border-box',
minWidth: 0,
},
space,
color,
layout,
flexbox
)
export default Box
Using the pattern above, you can add as much or as little as you like to your Box component. If you find yourself writing the same Box component over-and-over again, you might want to consider using a library like @techstack/components (opens in a new tab) or publishing your own UI component library to npm for reuse.
Extending
Not every style you use in an application needs to be added to a component as a style prop. For one-off customizations, it's often easier to extend a simpler component than it is to maintain a more complex Box component.
There are primarily two ways to extend styled components with libraries like Styled Components (opens in a new tab) and Emotion (opens in a new tab):
- Using the
css
prop - Creating an extended styled component
css
prop
The css
prop is a very popular way to handle one-off styles.
If your Box component needs a small style change you can make it inline or create an extended component for reuse.
To use the css
prop, you'll need to make sure you have either
babel-plugin-styled-components
(opens in a new tab) installed,
or a Babel plugin or custom JSX pragma configured for Emotion (opens in a new tab).
export default props => (
<Box
p={2}
css={{
borderBottom: '2px solid',
}}
>
This Box is using the css prop inline
</Box>
)
To use the css
prop to extend the Box component for reuse, you can do something like the following:
// extended Box component example
import React from 'react'
export default ({ large, ...props }) => (
<Box
{...props}
p={large ? 4 : 2}
css={{
borderRadius: '4',
border: '1px solid #f6f6f6',
boxShadow: '0 2px 4px rgba(0, 0, 0, .125)',
}}
/>
)
Extending with styled
An alternative to using the css
prop is to create a completely new styled component using the styled
HOC.
You can create these components anywhere,
but it's common to colocate these in the same module that they're used in.
import React from 'react'
import styled from 'styled-components'
import Box from './Box'
// extended Box component
const Card = styled(Box)({
borderRadius: '4',
border: '1px solid #f6f6f6',
boxShadow: '0 2px 4px rgba(0, 0, 0, .125)',
})
// code for the component using the extended component below