Skip to main content

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:

  1. Local Scope: Automatically mangles class names to be unique, ensuring that styles are local to the component and won't leak globally.

  2. Easy to Use: If you're coming from a CSS background, the transition to CSS Modules is often easier.

  3. Explicit Dependencies: You have to explicitly import your styles into your component file, making it easier to understand dependencies.

  4. 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:

  1. Dynamic Styling: Easy to use props to change styles dynamically.

  2. Theming: Built-in theming without any additional dependencies.

  3. Ease of Use: Write plain CSS while gaining the benefits of JavaScript.

  4. Server-Side Rendering: Has built-in support for SSR, making it easier to use in projects that require it.

  5. 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>;