Styling Components in React
By Syncfusion®, Inc. · Last updated
CSS in React: importing CSS files, className, multiple classes, inline styles, dynamic and conditional styling, and CSS Modules with scoped class names.
CSS in React
React apps use normal CSS. The browser does not care that the page was made with React. It still reads CSS rules and paints the page.
What changes is where you add the styles. In React, you style the elements that your components return. You can use a CSS file, a style object, or a CSS Module. This lesson shows all three.
Real-World Example
A bookshop app has a Button component used on 15 pages. Its styles are in Button.module.css, so the class .primary gets a unique name and cannot clash with another file's .primary.
When a book is out of stock, the card adds the class soldOut with className={book.stock === 0 ? styles.soldOut : ""}, and the card turns grey.
A CSS file is imported once, its classes are used with className, and the browser paints the styled page
styles.css .card { ... }
App.tsx import "./styles.css"
Page class="card" import className
Import the file once. Then any component can use its class names.
Importing CSS Files
Write your styles in a .css file. Then import that file in a component with one line:
import "./styles.css";
This line has no name before from. It does not give you a value. It only tells the build tool to add the CSS to the page. The rules then work for the whole page, not only for that component.
Open the styles.css tab below, change the colour, and click Run.
ClassName Usage
In HTML you write class="card". In React you write className="card".
The reason is simple. TSX is turned into JavaScript, and class is a keyword in JavaScript (it creates classes). So React uses className for the CSS class. React puts it on the page as a normal class.
<div className="card">...</div>
If you write class instead of className, React prints a warning in the console. Always use className in TSX.
Applying Multiple Classes
An element can have more than one class. Put the names in one string, with a space between them:
<div className="card featured">
Here card gives the basic box. featured adds a gold border on top. Each class adds its own styles.
Three classes on one element: card gives the box, featured adds a border, sale adds a red price className="card featured sale"
card white box, padding
featured gold border
sale red price
all three together
Classes are joined with spaces. Each one adds its own styles.
Sometimes one class is needed only in some cases. Build the string from parts. In the code below, this line adds sale only for books on sale:
const classes = ["card", book.onSale ? "sale" : ""].join(" ");
.join(" ") joins the list with spaces, so the result is "card sale" or "card ". An extra space does no harm.
Inline Styling
You can also put styles right on an element with the style prop. In React, style takes a JavaScript object, not a text string.
<p style={{ color: "green", fontSize: 18 }}>In stock</p>
The outer { } means "here comes JavaScript". The inner { } is the object. Notice two more things:
- CSS names with a dash become camelCase:
font-sizebecomesfontSize, andbackground-colorbecomesbackgroundColor. - A plain number means pixels.
fontSize: 18is the same as"18px".
To type a style object in TypeScript, use CSSProperties from React:
Use a CSS file for most styles. Use inline styles for small values that are worked out while the app runs, such as a width from a number. Inline styles cannot do :hover or media queries.
Dynamic and Conditional Styling
Dynamic styling means the style changes when the data changes. Because styles are written in your component, you can use state and props to choose them.
There are two common ways:
- Change the class.
className={isSelected ? "book selected" : "book"}adds theselectedclass only whenisSelectedis true. - Change an inline value.
style={{ width: percent + "%" }}sets the width from a number.
Dynamic styling: when state changes, the class name changes, so the look changes
isSelected true or false
className "book selected"
The Alchemist
Change the data, and React updates the class for you.
Click a book below. selectedId changes, so the class changes, so the colour changes. The stock bar uses an inline width, and turns red when stock is low.
CSS Modules
What are CSS Modules
A normal CSS file is global. If two files both have a .title class, the rules mix, and the last one wins. In a big app, this causes surprise bugs.
A CSS Module is a CSS file whose name ends with .module.css, such as Card.module.css. You import it with a name:
import styles from "./Card.module.css";
styles is an object. Each class in the file becomes a key. You use it like this: className={styles.title}.
CSS Modules give each file its own class names, so two .title classes never clash
Card.module.css .title
Header.module.css .title
_title_Card_x7k2
_title_Header_9fq1 different names on the page, so no clash
You write a short name. The build tool turns it into a unique name.
Scoped Styling in CSS Modules
Scoped means "works only in one place". The build tool renames every class in a module to a unique name, such as _title_Card_x7k2. Only the component that imports the module knows that name. So .title in Card.module.css can never touch .title in Header.module.css.
Below, both files use .title, but each title keeps its own colour. The console prints the real class names.
To use two module classes on one element, join them the same way as before: className={styles.card + " " + styles.featured}.
Easy Way to Remember: a plain .css file is shared by the whole page. A .module.css file belongs to one component.
Common mistakes
| Mistake | What you see | Fix |
|---|---|---|
Writing class="card" in TSX | A console warning | Use className |
Writing style="color: red" | An error: style must be an object | Use style={{ color: "red" }} |
Writing font-size in a style object | A syntax error, or the style is ignored | Use camelCase: fontSize |
Two classes as className="card" className="sale" | Only one class is used | One string: className="card sale" |
className="title" with a CSS Module | No style is applied | Use className={styles.title} |
Naming a module Card.css | Classes are global, not scoped | Name it Card.module.css |
Check Yourself
Exercises
What to Remember
- Import a CSS file with
import "./styles.css";and useclassName, notclass. - Join several classes with spaces in one string. Choose classes with conditions to change the look from state.
- Inline
styletakes an object with camelCase names. A.module.cssfile gives scoped class names throughstyles.name.
Next: Error Handling