Styles
In JSX, you can apply styles to your components in various ways. Here are some common methods:
1. Inline Styles
You can use the style
attribute to add inline styles. The value of the style
attribute must be an object where the keys are camelCased versions of the CSS property names, and the values are the CSS values as strings.
const divStyle = {
color: 'blue',
backgroundColor: 'lightgray',
};
function App() {
return <div style={divStyle}>Hello, world!</div>;
}
2. CSS Classes
You can use CSS classes defined in an external CSS file. Use the className
attribute to specify the CSS class.
// App.css
.my-class {
color: blue;
background-color: lightgray;
}
// App.js
function App() {
return <div className="my-class">Hello, world!</div>;
}
3. CSS Modules
How it Works:
- CSS Modules are a way to have local scope CSS by default. This ensures that the classes you define in a module are scoped to the component, not global, which helps prevent styling conflicts.
- You typically name your stylesheet with a
.module.css
extension and use it in your component by importing it as a module.
Advantages:
Local Scope: Automatically mangles class names to be unique, ensuring that styles are local to the component and won't leak globally.
Easy to Use: If you're coming from a CSS background, the transition to CSS Modules is often easier.
Explicit Dependencies: You have to explicitly import your styles into your component file, making it easier to understand dependencies.
Performance: Since it's just CSS, there's no runtime overhead.
Example:
// App.module.css
.myClass {
color: blue;
background-color: lightgray;
}
// App.js
import styles from './App.module.css';
function App() {
return <div className={styles.myClass}>Hello, world!</div>;
}
4. Styled-components
How it Works:
Styled-components utilizes tagged template literals to style your components.
It removes the mapping between components and styles, meaning that when you're defining your styles, you're actually creating a normal React component that has your styles attached to it.
Advantages:
Dynamic Styling: Easy to use props to change styles dynamically.
Theming: Built-in theming without any additional dependencies.
Ease of Use: Write plain CSS while gaining the benefits of JavaScript.
Server-Side Rendering: Has built-in support for SSR, making it easier to use in projects that require it.
Automatic Vendor Prefixing: Styles are automatically vendor prefixed.
Example I:
import styled from 'styled-components';
const Wrapper = styled.div`
color: ${(props) => (props.active ? 'blue' : 'gray')};
background-color: lightgray;
`;
function App() {
return <Wrapper active>Hello, world!</Wrapper>;
}
Example II:
Let's dive into a more detailed example using Styled-components. In this example, we'll create a simple React application that has a button. The button will toggle and change its appearance.
StyledButton.js
import styled from 'styled-components';
const StyledButton = styled.button`
background-color: ${(props) => (props.active ? 'green' : 'red')};
color: white;
padding: 10px;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s ease;
&:hover {
background-color: ${(props) => (props.active ? 'darkgreen' : 'darkred')};
}
`;
export default StyledButton;
App.js
import React, { useState } from 'react';
import StyledButton from './StyledButton';
import StyledCard from './StyledCard';
function App() {
const [isActive, setIsActive] = useState(false);
const toggleActive = () => {
setIsActive(!isActive);
};
return (
<div>
<StyledButton active={isActive} onClick={toggleActive}>
Toggle Card State
</StyledButton>
</div>
);
}
export default App;
This example demonstrates the power of Styled-components in handling dynamic styles based on props, as well as its ease of use in creating complex UI elements.
Example III
You can achieve the same functionality using plain CSS and React's inline style feature. Here's how you can do it:
App.css
.button {
padding: 10px;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s ease;
color: white;
}
.button.active {
background-color: green;
}
.button.inactive {
background-color: red;
}
.button.active:hover {
background-color: darkgreen;
}
.button.inactive:hover {
background-color: darkred;
}
App.js
import React, { useState } from 'react';
import './App.css';
function App() {
const [isActive, setIsActive] = useState(false);
const toggleActive = () => {
setIsActive(!isActive);
};
return (
<div>
<button
className={`button ${isActive ? 'active' : 'inactive'}`}
onClick={toggleActive}
>
Toggle Card State
</button>
</div>
);
}
export default App;
We use React's conditional class rendering to apply the .active
or .inactive
CSS classes based on the isActive
state. This allows us to toggle the styles of the button and the card dynamically.
5. Emotion
Emotion is a performant and flexible CSS-in-JS library. It allows you to style applications quickly with string or object styles.
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react'
const style = css`
color: blue;
background-color: lightgray;
`
function App() {
return <div css={style}>Hello, world!</div>
}
6. Conditional Styling
Handling dynamic class names in React can be done in various ways, depending on your needs. Here are some common methods:
String Concatenation
You can concatenate strings to form dynamic class names.
const isActive = true;
const className = "button " + (isActive ? "button--active" : "");
return <div className={className}>Click Me</div>;
Template Literals
Using ES6 template literals, you can make the code cleaner.
const isActive = true;
const className = `button ${isActive ? "button--active" : ""}`;
return <div className={className}>Click Me</div>;
Array Join
You can push class names into an array and then join them.
const classes = ["button"];
if (isActive) {
classes.push("button--active");
}
return <div className={classes.join(" ")}>Click Me</div>;
Object Keys
You can use an object where the keys are the class names and the values are boolean expressions. Then you can filter out the false values.
const classes = {
button: true,
"button--active": isActive,
};
const className = Object.keys(classes)
.filter((key) => classes[key])
.join(" ");
return <div className={className}>Click Me</div>;
Libraries
There are also libraries like classnames
that simplify this process.
First, install the package:
npm install classnames
Then use it in your component:
import classNames from "classnames";
const className = classNames("button", { "button--active": isActive });
return <div className={className}>Click Me</div>;