You can style your React apps and pages using a number of techniques. The easiest of which would be to download a React component library. However, even when using libraries, sooner or later you will need to add custom styles. So, what’s the best way to do it?
For small-scale projects, you can comfortably style your app using Inline styles, Modules, or by writing className specifications yourself. And for dynamic projects – like apps – it’s better to use a library that lets you implement props easily.
Alternatively, you can use a utility kit like Tailwind UI, which comes with pre-built styles. If you need to render a mockup or a presentation, React-friendly UI kits are the way to go.
Practical styling with className
In React, practical CSS styles are applied through the className property.
This is also the equivalent of using a stylesheet for your project. Since React is driven by component structure, you can import your stylesheets for specific needs only.
Let’s look at an example.
App.css
.CSS-span {
display: inline-block;
transform: rotate(-1deg);
position: relative;
color: #fff;
background-color: #dd9662;
padding: 1px 5px 1px 5px;
border-radius: 5px;
}
App.js
import './app.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
How to Style React Components with <span className="CSS-span">CSS</span>
</p>
</header>
</div>
);
}
And this would be the outcome:
It’s a completely valid vanilla technique. And, is most often used to declare global variables that you will reuse across core components.
The only caveat is that as your project grows, so does the potential for naming conflicts.
Likewise, the efficiency cost of managing hundreds of stylesheets is absurdly high.
Using JSX for Inline Styles
React lets you style DOM elements using inline styles. While the CSS logic remains the same, the style itself has to pass through JavaScript. This is also known as JSX.
Let’s look at an example:
Headline.js
function Headline(){
const headlineStyle = {
backgroundColor: "#fff",
lineHeight: "1.5",
height: "2rem",
border: "none",
color: "black"
}
return (
<div style= { headlineStyle } >
<h2>Headline title</h2>
<p>the sub-headline</p>
</div>
)
}
One thing you’ll note is that instead of writing line-height
we use lineHeight
.
The explanation for this is that, “Since JSX is closer to JavaScript than to HTML, React DOM uses camelCase
property naming convention instead of HTML attribute names.”.
Inline styles are typically used to showcase examples, but also to add dynamic styling to specific elements. Moreover, inline styles don’t support pseudo-elements or media queries, since you can only pass style. Using a stylesheet is a better alternative.
Creating local scope with CSS Modules
If you want to apply custom styles to components without naming collisions, one way to do it is through CSS Modules.
This is an approach where you can apply local scope to each component individually.
Like so:
Header.module.css
.container {
width: 1280px;
margin: 1rem auto;
padding: 1rem;
}
.header {
background-color: #ffffff;
color: #000000;
font-weight: 700;
}
Header.js
import styles from './Header.module.css';
function Header() {
return (
<div className={styles.container}>
<h2 className={styles.header}>Using CSS Modules in React</h2>
</div>
);
}
You can also do things like composition, where you call a specific style from another stylesheet – avoiding the need to rewrite the same logic twice.
.header {
composes: header from './style.css';
}
CSS in JS
Unlike frameworks like Vue and Svelte, React does not provide its own styling interface.
So, while you can write CSS for components using the aforementioned methods, the holy grail approach is to use CSS in JS libraries. Each library has its strengths and weaknesses, but generally, the benefits stay the same:
- Props for various style variations.
- Accessible theming.
- Component-based style scoping.
- Dynamic CSS variables using JavaScript functions.
The most popular solution for CSS in JS is Styled Components.
And other notable choices include Emotion and Linaria. For the sake of the demo, let’s look at how CSS is integrated into a React component using the Styled Components library.
StyledComponents.js
import styled from 'styled-components';
const HeaderWrapper = styled.section`
padding: 4em;
background: orange;
`;
const HeaderTitle = styled.h2`
font-size: 2rem;
text-align: center;
color: black;
`;
<HeaderWrapper>
<HeaderTitle>Example of creating a React component with Styled Components.</HeaderTitle>
</HeaderWrapper>
First, we create a new component called HeaderWrapper
which will render a <section>
container for our header title. Then we create another component called HeaderTitle
and pass the CSS variables to it. So, in a way, this is exactly the same as working with Web Components, only in the context of React.
Using a CSS Framework
It’s not that everything in front-end is moving towards frameworks and libraries.
It’s more to do with the fact that starting a project from nothing is inefficient. A framework like Tailwind CSS helps to alleviate the need to write all your application structures from scratch. The way Tailwind CSS works is that the framework provides utility classes that are pre-determined, letting you structure a layout without needing to write independent CSS.
TailwindCSSApp.js
function Header() {
return (
<div className="container mx-auto bg-gray-500 rounded-xl shadow border p-8 m-10">
<p className="text-3xl text-black-700 font-bold mb-5">
Tailwind CSS with React
</p>
<p className="text-black-300 text-lg">
All styling defined with utility classes
</p>
</div>
);
}
export default Header;
So, rather than defining the component style using Constants, we can directly write the style as specified by the framework. A method like this is extremely efficient, and you can for example – import UI components (such as cards) made by others.
Tailwind CSS is particularly popular because you can directly copy and paste snippets, and use them in your app design without any consequences.
Using a UI Library
The last method for styling React components is to use a UI library. Unlike a framework, a UI library follows style guidelines. So, in a lot of ways, it comes with a style that’s already pre-determined. The likes of Mantine and Material UI are some of the go-to choices.
The only “downside” is that you have to spend quite a bit of your time learning that particular library. But, the same could be said for frameworks. Despite the entry barrier, both CSS frameworks and UI libraries are the gold standard in styling React components.