Working with React you have a lot of choice for when it comes to handling styling using CSS-in-JS. You can learn about a lot of the available options in our CSS-in-JS Roundup.
Most libraries have a lifecycle. They rise in popularity and then they get superseded by a better solution.
One of the libraries at its popularity peak is 💅 styled-components.
The creator of styled-components is also the maintainer of react-boilerplate
, one of the most popular ways to set up a React project.
The boilerplate includes styled-components and it makes perfect sense to just use the boilerplate if you’re starting a new app from scratch.
To get started, clone the repo:
$ git clone --depth=1 https://github.com/react-boilerplate/react-boilerplate.git
…and then cd
into into it and run npm run setup
.
The boilerplate provides an example app which is very convenient to start diving into styled-components.
Jump start it with npm start
, and reach your app at http://localhost:3000.
The components in the example app are already using styled-components. See app/containers/App/index.js
for an example:
// ...other imports
import styled from 'styled-components';
const AppWrapper = styled.div`
max-width: calc(768px + 16px * 2);
/* ... */
`;
export default function App() {
return (
<AppWrapper>
{/* ... */}
</AppWrapper>
);
}
This is the Styled Component associated to the AppWrapper container, responsible for rendering the page wrapper. The outputted DOM will be a div element with the style applied.
The boilerplate uses hot reloading, so you can tweak something, save the file, and the changes apply to the page.
Try setting a custom max-width
to 500px
:
const AppWrapper = styled.div`
max-width: 500px;
/* ... */
`;
and save the file:
You just edited your first Styled Component! 🎉
As you can see, there is nothing that links the style you just edited to its container. There is no className, which you would have used in CSS to link a style to an element.
The usual workflow when building a web interface with CSS is:
This requires to keep those in sync, in case you need to change them. It also requires you to research a naming structure that can accomodate all your elements.
If you’re in a team, this usually means having naming conventions which might be hard to enforce. Not when laying out the initial structure of the project, but easy to bypass when it comes to making quick fixes. styled-components create classes on the fly for you, with unique class names for all your elements.
This guarantees that no style can leak out to other elements, like it could happen with reusing class names across the page.
Some of the existing CSS-in-JS libraries let you write CSS in JavaScript in the form of JavaScript objects. This requires some cognitive load and it’s a barrier to entry for many designers that know CSS but not JavaScript.
styled-components rely on JavaScript template literals to let you write actual CSS, which can be simply copy-pasted from your CSS files.
The only thing to note is that media queries use a “special syntax”, where you omit the selector, instead of:
@media (max-width: 700px) {
.app-wrapper {
background: white;
}
}
you write:
const AppWrapper = styled.div`
/* ... */
@media (max-width: 700px) {
background: white;
}
`;
styled-components are “just CSS”, but a slightly enhanced CSS.
It allows CSS nesting, one of the main conveniences of common CSS preprocessors. Let’s give a quick test, by flipping any image in the page:
const AppWrapper = styled.div`
max-width: calc(768px + 16px * 2);
/* ... */
img {
transform: scaleX(-1);
}
`;
It also handles vendor prefixes for you using inline-style-prefixer. In the example above, the use of transform
adds these vendor prefixes to the generated CSS:
.fpcXGq img {
-webkit-transform: scaleX(-1);
-ms-transform: scaleX(-1);
transform: scaleX(-1);
}
If you want to make the right button grey instead of blue, it’s easy to overwrite this specific CSS property. The buttons are two instances of HeaderLink, which is a Link component from react-router-dom
with some styles applied:
import { Link } from 'react-router-dom';
import styled from 'styled-components';
export default styled(Link)`
/* ... */
border: 2px solid #41ADDD;
color: #41ADDD;
/* ... */
`;
Now, if you want to create a gray button it’s pretty easy:
import styled from 'styled-components';
import HeaderLink from './HeaderLink';
const GrayHeaderLink = styled(HeaderLink)`
color: darkgray;
border: 2px solid darkgray;
`;
and now use this component in your JSX, from:
<NavBar>
<HeaderLink to="/">
{/* ...children */}
</HeaderLink>
<HeaderLink to="/features">
{/* ...children */}
</HeaderLink>
</NavBar>
to:
<NavBar>
<GrayHeaderLink to="/">
{/* ...children */}
</GrayHeaderLink>
<GrayHeaderLink to="/features">
{/* ...children */}
</GrayHeaderLink>
</NavBar>
This approach works great when you don’t own your components. In this case the Link came from the react-router-dom
package and we had no control over it.
Otherwise it’s even simpler. This is the default style of a button:
import { css } from 'styled-components';
const buttonStyles = css`
/* ... */
border: 2px solid #41addd;
color: #41addd;
/* ... */
`;
export default buttonStyles;
You’ll notice the use of the css helper, which allows the use of interpolations inside your CSS rules.
Inserting a simple prop into the template literal will allow us to have a different style in a component by selecting the color based on the prop value:
const buttonStyles = css`
/* ... */
border: 2px solid ${(props) => props.gray ? 'darkgray' : '#41addd'};
color: ${(props) => props.gray ? 'darkgray' : '#41addd'};
/* ... */
`;
The StyledButton component is then exported using a syntax like the following:
import styled from 'styled-components';
import buttonStyles from './buttonStyles';
const StyledButton = styled.button`${buttonStyles}`;
export default StyledButton;
Now you can make the button grey by just writing:
<StyledButton gray />
This is the tip of the iceberg. styled-components allow you to perform much more advanced configurations.
Learn all styled-components can provide in the official documentation.
* Note that the code snippets in this post taken from the React Boilerplate project are licensed under MIT and © 2017 Maximilian Stoiber. You can find a copy of the license here.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!