styled-components is the result of wondering how we could enhance CSS for styling React component systems. By focusing on a single use case we managed to optimize the experience for developers as well as the output for end users.
Apart from the improved experience for developers, styled-components provides:
- Automatic critical CSS: styled-components keeps track of which components are rendered on a page and injects their styles and nothing else, fully automatically. Combined with code splitting, this means your users load the least amount of code necessary.
- No class name bugs: styled-components generates unique class names for your styles. You never have to worry about duplication, overlap or misspellings.
- Easier deletion of CSS: it can be hard to know whether a class name is used somewhere in your codebase. styled-components makes it obvious, as every bit of styling is tied to a specific component. If the component is unused (which tooling can detect) and gets deleted, all its styles get deleted with it.
- Simple dynamic styling: adapting the styling of a component based on its props or a global theme is simple and intuitive without having to manually manage dozens of classes.
- Painless maintenance: you never have to hunt across different files to find the styling affecting your component, so maintenance is a piece of cake no matter how big your codebase is.
- Automatic vendor prefixing: write your CSS to the current standard and let styled-components handle the rest.
You get all of these benefits while still writing the CSS you know and love, just bound to individual components.
Installing styled-components only takes a single command and you're ready to roll:
npm install --save styled-components
NOTE
It's highly recommended (but not required) to also use the Babel plugin. It offers many benefits like more legible class names, server-side rendering compatibility, smaller bundles, and more.
If you're not using a module bundler or package manager we also have a global ("UMD") build hosted on the unpkg CDN. Simply add the following <script>
tag to the bottom of your HTML file:
<script src="https://unpkg.com/styled-components/dist/styled-components.min.js"></script>
Once you've added styled-components
you will have access to the global window.styled
variable.
const Component = window.styled.div`
color: red;
`
NOTE
This style of usage requires the react CDN bundles and the react-is
CDN bundle to be on the page as well (before the styled-components script.)
styled components
utilises tagged template literals to style your components.
It removes the mapping between components and styles. This means that when you're defining your styles, you're actually creating a normal React component, that has your styles attached to it.
This example creates two simple components, a wrapper and a title, with some styles attached to it:
// Create a Title component that'll render an <h1> tag with some styles
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;
// Create a Wrapper component that'll render a
<section> tag with some styles
const Wrapper = styled.section`
padding: 4em;
background: papayawhip;
`;
// Use Title and Wrapper like any other React
component – except they're styled!
render(
<Wrapper>
<Title>
Hello World!
</Title>
</Wrapper>
);
Hello World!
This is a live editor, so play around with the code to get a feel for what it's like to work with styled-components!
NOTE
The CSS rules are automatically vendor prefixed, styled-components takes care of that for you!
You can pass a function ("interpolations") to a styled component's template literal to adapt it based on its props.
This button component has a primary state that changes its color. When setting the primary
prop to true, we are swapping out its background and text color.
const Button = styled.button`
/* Adapt the colors based on primary prop */
background: ${props => props.primary ?
"palevioletred" : "white"};
color: ${props => props.primary ? "white" :
"palevioletred"};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
render(
<div>
<Button>Normal</Button>
<Button primary>Primary</Button>
</div>
);
Quite frequently you might want to use a component, but change it slightly for a single case. Now, you could pass in an interpolated function and change them based on some props, but that's quite a lot of effort for overriding the styles once.
To easily make a new component that inherits the styling of another, just wrap it in the styled()
constructor. Here we use the button from the last section and create a special one, extending it with some color-related styling:
// The Button from the last section without the
interpolations
const Button = styled.button`
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
// A new component based on Button, but with some
override styles
const TomatoButton = styled(Button)`
color: tomato;
border-color: tomato;
`;
render(
<div>
<Button>Normal Button</Button>
<TomatoButton>Tomato Button</TomatoButton>
</div>
);
We can see that the new TomatoButton
still resembles Button
, while we have only added two new rules.
In some cases you might want to change which tag or component a styled component renders. This is common when building a navigation bar for example, where there are a mix of anchor links and buttons but they should be styled identically.
For this situation, we have an escape hatch. You can use the "as" polymorphic prop
to dynamically swap out the element that receives the styles you wrote:
const Button = styled.button`
display: inline-block;
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
display: block;
`;
const TomatoButton = styled(Button)`
color: tomato;
border-color: tomato;
`;
render(
<div>
<Button>Normal Button</Button>
<Button as="a" href="/">Link with Button
styles</Button>
<TomatoButton as="a" href="/">Link with
Tomato Button styles</TomatoButton>
</div>
);
This works perfectly fine with custom components too!
const Button = styled.button`
display: inline-block;
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
display: block;
`;
const ReversedButton = props => <Button
{...props} children=
{props.children.split('').reverse()} />
render(
<div>
<Button>Normal Button</Button>
<Button as={ReversedButton}>Custom Button
with Normal Button styles</Button>
</div>
);
NOTE
If you are still on an older version than v4, you can use the .withComponent
or .extend
API's to achieve the same result as with the "as" prop
, but note that this is discouraged as with v4 .extend
was removed and .withComponent
was marked as a candidate for future deprecation.