Originally posted on nordschool.
There are many ways to style your React components. 🤓
In this guide, we will cover ways to style React components. We will show you 5 different ways and you decide which one you prefer best! 😁
Style your component your way
These are the component-styling ways we will discuss:
We are going to replace the same styles below using different component-styling ways.
/* BeautifulButton.css */
.button {
color: #494949;
text-transform: uppercase;
text-decoration: none;
background: #ffffff;
padding: 20px;
font-size: 20px;
border: 4px solid #494949;
display: inline-block;
transition: all 0.4s ease 0s;
}
.button:hover {
color: #ffffff;
background: #f6b93b;
border-color: #f6b93b;
transition: all 0.4s ease 0s;
}
.button--primary {
color: #ffffff;
text-transform: uppercase;
text-decoration: none;
background: #f6b93b;
padding: 20px;
font-size: 20px;
border: 4px solid #f6b93b;
display: inline-block;
transition: all 0.4s ease 0s;
}
.button--primary:hover {
color: #494949;
background: #ffffff;
border-color: #494949;
transition: all 0.4s ease 0s;
}
Regular CSS
This is the easiest and most straight forward way to add styles to a React component.
import React from 'react';
import './BeautifulButton.css';
const MyBeautifulButton = props => {
return (
<div>
<button className={props.primary ? 'button--primary' : 'button'}>
Button
</button>
</div>
);
};
export default MyBeautifulButton;
Inline Styling
import React from 'react';
const MyBeautifulButton = props => {
const button = {
color: '#494949',
textTransform: 'uppercase',
textDecoration: 'none',
background: '#ffffff',
padding: '20px',
fontSize: '20px',
border: '4px solid #494949',
display: 'inline-block',
transition: 'all 0.4s ease 0s'
};
const primaryButton = {
...button,
color: '#ffffff',
background: '#f6b93b',
borderColor: '#f6b93b'
};
return (
<div>
<button style={props.primary ? primaryButton : button}>Button</button>
</div>
);
};
export default MyBeautifulButton;
Note: The camel-case is necessary for the inline-styling to work! For example, borderColor.
Inline-styling is simple and works out of the box but has many limitations.
For example, there is no straight froward way to add hover effect.
Recommendation: Use the inline-styling paradigm only with small simple components. 😇
CSS Modules
import React from 'react';
import styles from './my-beautiful-button.module.css'; // must have extension .module.css.
// my-beautiful-button.module.css has the same styles as Button.css.
const MyBeautifulButton = props => {
return (
<div>
<button
className={props.primary ? styles['button--primary'] : styles.button}
>
Button
</button>
</div>
);
};
export default MyBeautifulButton;
All styles from a CSS module get scoped within that component that imported it. That means you don't have to worry about global name-conflicts. 😌
Note: You must include the sub-extension .module in the name. Otherwise the styles will load as regular CSS and you may have name-conflicts.
Preprocessors
Using preprocessors such as SCSS, LESS or Stylus is straight forward in React.
You need to add the preprocessor loader and then in the same way as regular CSS you can import the files.
import React from 'react';
import './button.scss'; // <-- Once webpack configs have the right loader this should work like regular scss.
const MyBeautifulButton = props => {
return (
<div>
<button className={props.primary ? 'button--primary' : 'button'}>
Button
</button>
</div>
);
};
export default MyBeautifulButton;
CSS in JS
CSS in JS is a pattern where you would define all your styles inside the component. Like inline-styling but a lot more powerful.
Let's have a look at how we would write the same button styles using Styled Components and Emotion.
Styled Components
import React from 'react';
import styled from 'styled-components';
const MyBeautifulButton = props => {
const BeautifulButton = styled.button`
color: #494949;
text-transform: uppercase;
text-decoration: none;
background: #ffffff;
padding: 20px;
font-size: 20px;
border: 4px solid #494949;
display: inline-block;
transition: all 0.4s ease 0s;
&:hover {
color: #ffffff;
background: #f6b93b;
border-color: #f6b93b;
transition: all 0.4s ease 0s;
}
`;
const BeautifulPrimaryButton = styled(Button)`
color: #ffffff;
background: #f6b93b;
border-color: #f6b93b;
&:hover {
color: #494949;
background: #ffffff;
border-color: #494949;
}
`;
return (
<div>
{props.primary ? (
<BeautifulPrimaryButton>Button </BeautifulPrimaryButton>
) : (
<BeautifulButton>Button</BeautifulButton>
)}
</div>
);
};
export default MyBeautifulButton;
Emotion
Emotion has two ways of adding styles, the css API and the styled API.
Here is an example of how using the css API looks like:
// this comment tells babel to convert jsx to calls to a function called jsx instead of React.createElement
/* @jsx jsx */
import React from 'react';
import { jsx, css } from '@emotion/core';
const BeautifulButton = css`
color: #494949;
text-transform: uppercase;
text-decoration: none;
background: #ffffff;
padding: 20px;
font-size: 20px;
border: 4px solid #494949;
display: inline-block;
transition: all 0.4s ease 0s;
&:hover {
color: #ffffff;
background: #f6b93b;
border-color: #f6b93b;
transition: all 0.4s ease 0s;
}
`;
const BeautifulPrimaryButton = css`
${Button};
color: #ffffff;
background: #f6b93b;
border-color: #f6b93b;
&:hover {
color: #494949;
background: #ffffff;
border-color: #494949;
}
`;
const MyBeautifulButton = props => {
return (
<div>
<button css={props.primary ? BeautifulPrimaryButton : BeautifulButton}>Button</button>
</div>
);
};
export default MyBeautifulButton;
Emotion's styled API is very similar to Styled Components. Here is an example:
// this comment tells babel to convert jsx to calls to a function called jsx instead of React.createElement
/* @jsx jsx */
import React from 'react';
import { jsx, css } from '@emotion/core';
import styled from '@emotion/styled';
const BeautifulButton = styled.button`
color: #494949;
text-transform: uppercase;
text-decoration: none;
background: #ffffff;
padding: 20px;
font-size: 20px;
border: 4px solid #494949;
display: inline-block;
transition: all 0.4s ease 0s;
&:hover {
color: #ffffff;
background: #f6b93b;
border-color: #f6b93b;
transition: all 0.4s ease 0s;
}
`
const BeautifulPrimaryButton = styled(BeautifulButton)`
color: #ffffff;
background: #f6b93b;
border-color: #f6b93b;
&:hover {
color: #494949;
background: #ffffff;
border-color: #494949;
}
`
const MyBeautifulButton = (props) => {
return (
<div>
{props.primary ? <BeautifulPrimaryButton>Button </BeautifulPrimaryButton> : <BeautifulButton>Button</BeautifulButton>}
</div>
);
};
export default MyBeautifulButton;
Note: You can add a babel plugin to avoid writing the required file's top line.
/** @jsx jsx */
CSS in JS is a powerful pattern. It makes a lot of things easier when building large complex web applications.
There is one main difference between Styled Components and Emotion.
Styled Component offers only the styled API. But, Emotion offers two ways to add the styles: the css and the styled APIs.
Recommendation: For large applications, we would recommend using Emotion. 👌
Here are other CSS in JS libraries worth checking out:
Now you know your options when it comes to styling components! Which one do you prefer? 🤔
Support
Enjoyed the article? Share the summary thread on twitter.
Better Code Monday Newsletter
You might also like my newsletter. The idea is to share 3 web dev tips every Monday.
My goal is to improve my writing skills and share knowledge as much as possible. So far, few hundreds of developers have subscribed and seem to like it.
To get a feeling of what kind of stuff I share, Check out the previous newsletter issues and subscribe.
Top comments (2)
I've used SASS, Styled Components, pure CSS, CSS-in-JS and CSS modules, and the clear winner to me is Linaria.
linaria.now.sh/
It's very similar in syntax to Styled Components (can't tell the difference) but it's got one major benefit: instead of extracting styles on runtime, it does this when you build the production version. It puts each components styles in a separate, pure CSS stylesheet.
Here's a list of features from their website:
This gives you all the benefits of pure CSS, as well as all the benefits of CSS-in-JS, without any of the downsides.
I would highly recommend Linaria as an alternative for JSS, and no, I don't work for them. I just love using it!
I’ve been using css module for a long time
But I started to hate writing the css import every time without auto complete
Styled component got the auto complete but I don’t like css in Js
This seems to be a great option for me
Thx