How CSS works in React.

Since React itself has no special support or processing for CSS, you can use regular inline styles or class selectors used in normal HTML when writing CSS in React, or you can use various community solutions such as CSS Modules, CSS in JS, etc. This article briefly introduces the various options.

1. Inline styles

Just like writing inline styles in normal HTML, add a style attribute. But the difference is that in HTML the value of the style attribute is a string, while in JSX it is an object:

<!-- HTML -->
<h1 style="color: red">Heading 1</h1>
// JSX
<h1 style={{ color: 'red' }}>Heading 1</h1>

In addition, the properties of the style object in JSX are named in lower camel case, such as the need to be written as. It is generally not recommended to use this method extensively in a project.background-color backgroundcolor

2. class selector

When using the class selector in JSX, you need to write the value as a string, and use spaces to separate multiple classes.classclassName

<h1 className="h1 text-center">Heading 1</h1>

In React 16 and above, it can be written as, but to avoid confusion with the keyword, it is recommended to write it as .classNameclassclassclassName When there are multiple classes and dynamic changes are required, classnames can be used to simplify the code. As for the processing of CSS files, it can be directly introduced in HTML. For example, when using bootstrap, a CDN address can be directly introduced in HTML; when using CSS files written by yourself, it is recommended to split the CSS files corresponding to React components and put them in the Use in the component file to import, and then configure CSS-loader in webpack for processing.import

src
 |-- components
          |-- Header
                |-- index.jsx
                |-- index.css
          |-- Footer
                |-- index.jsx
                |-- index.css
// src/components/Header/index.jsx
import React from 'react';
import './index.css';

const Header = () => {
  return (
    <h1 className="header">Heading 1</h1>
  );
};

export default Header;
/* src/components/Header/index.css */
.header {
  color: #333;
}

It should be noted here that component splitting does not equal style isolation. When multiple components are referenced on a page at the same time, the CSS files of these components will be referenced at the same time. Because native CSS has no concept of scope, all classes are globally valid, so these CSSs may conflict; When switching, there may also be style conflicts between multiple pages, because a single-page application is essentially just one page. When switching from page A to page B, the CSS file of page B is loaded, but the CSS of page A is not destroyed. , the two coexist. To solve the problem of style scoping, naming conventions such as BEM can be used to avoid naming duplication as much as possible, but this does not solve the problem fundamentally. CSS Modules was born to solve this problem.

3. CSS Modules

CSS Modules are built to implement CSS scoping effects. The principle is very simple, that is, to modify the class name and animation-name according to certain rules, so that the class name is globally unique, so as to avoid the problem of naming conflicts.

/* App.css */


.home {
  color: #333;
}

.App_home__T45xz {
  color: #333;
}

It is also very simple to use. Take webpack as an example, just add a to. There is also a little change when used in the code:modules: true

import React from 'react';
import styles from './App.css';

const App = () => {
  return (
    <div className={styles.home}>App</div>
  );
};

export default App;

The imported is an object, which is the mapping between the original class name and the compiled class name, such as .styles{ home: 'App_home__T45xz' } In addition to modifying the class name, CSS Modules also have advanced functions such as class combination, and importing classes in other files, and you can customize the naming rules through the configuration items of CSS-loader. For details, please refer to the documentation of css-loader. Whether it is importing a CSS file or using CSS Modules, it does not conflict with Less, Sass, etc. Just add a corresponding loader before the CSS-loader in the webpack configuration.

4. CSS in JS

The previous methods are relatively conventional, and none of them deviate from the conventional HTML + CSS mental model.

In web development in the jQuery era, we focused on "separation of concerns" - separating HTML, CSS, and JavaScript from each other. But React combines HTML and JavaScript through JSX and pays more attention to componentization. Is there any solution to writing CSS in JS way to achieve All in JS?

CSS in JS is a general term for solutions to write CSS through JS, not a specific solution. Due to a large number of schemes, this article only introduces two.

4-1. styled-components

styled components use template string syntax to integrate CSS into React's component system, and use JS to implement some functions that CSS does not have, such as variables, loops, and functions. While these functions can be implemented through Less or Sass, these functions of styled components are implemented through JS with low or no learning cost.

It is recommended that you configure the Babel plugin before you start using it, it can provide some optimizations and SSR support, but this plugin is optional .babel-plugin-styled-components.

Basic usage

import React from 'react';
import styled from 'styled-components';

const Title = styled.h1`
  color: #333;
`;

const App = () => (
  <Title>Heading 1</Title>
);

export default App;

When you define a style, you actually generate a React component that contains the style.

Dynamic styles

Now that a React component is generated, props can be passed, the props values ​​can be read in the style, and the style can be dynamically adjusted according to the props value:

import React from 'react';
import styled from 'styled-components';

const Title = styled.h1`
  color: #333;
  font-weight: ${props => props.bold ? 700 : 400};
`;

const App = () => (
  <Title bold={true}>Heading 1</Title>
);

export default App;

Extended style

The above examples are all adding styles to an HTML tag, and you can also add styles to a component, and will override the existing styles:

import React from 'react';
import styled from 'styled-components';

const Title = styled.h1`
  color: #333;
  font-weight: ${props => props.bold ? 700 : 400};
`;

const ItalicTitle = styled(Title)`
  font-style: italic;
`;

const App = () => (
  <>
    <Title bold={true}>Heading 1</Title>
    <ItalicTitle bold={true}>Heading 1</ItalicTitle>
  </>
);

export default App;

If you don't want to modify the style, but want to modify the HTML tag, you can pass a prop, the value can be a string of HTML tags or a React component.as

<Title as={'h2'} bold={true}>Heading 1</Title>

The rendered DOM node is the h2 tag.

More detailed functions can be viewed in the official documentation of styled-components .

4-2. styled-jsx

As can be seen from the name, styled-components is to bind styles to components, while styled-jsx goes a step further and directly binds styles to JSX, with finer-grained control of the scope.

You need to add the plugin .styled-jsx/babel

Basic usage

import React from 'react';

const App = () => {
  return (
    <div>
      <h1>
        Heading 1
        <style jsx>{`
          h1 {
            color: red;
          }
        `}</style>
      </h1>
    </div>
  );
};

export default App;

Now the style of the h1 tag selector defined in the style tag only takes effect in the h1 tag that wraps it and does not take effect for the h1 tag added outside.

Dynamic styles

Since the style is written in JSX, it can read the props and state of the current component, and then dynamically adjust the style according to the state:

import React, { useState } from 'react';

const App = () => {
  const [bold, setBold] = useState(true);
  return (
    <div>
      <h1>
        Heading 1
        <style jsx>{`
          h1 {
            color: red;
            font-weight: ${bold ? 700 : 400};
          }
        `}</style>
      </h1>
      <button onClick={() => setBold(!bold)}>Toggle</button>
    </div>
  );
};

export default App;

global style

There are always cases where we need to write a global style. When we need to write a global style, we can add an attribute :global

<div>
  <style jsx global>
    body {
      margin: 0;
      padding: 0;
    }
  </style>
</div>
You can also add a class to a class , and only globalize this class. This is also used in CSS Modules::global()
<div>
  <style jsx>
    :global(.header) {
      color: #333;
    }
  </style>
</div>

For more usage and configuration, see the official documentation of styled-jsx .

5. Finally

Some people also classify CSS Modules as CSS in JS, but it does not break away from the mental model of separation of HTML and CSS, and there is no runtime after compilation, so this article will not classify it as CSS in JS.

There are many CSS in JS solutions. Although the usage is different, the basic idea is to give CSS the ability of JS. The biggest benefit is that it can dynamically adjust the style, which is especially useful in similar requirements such as switching themes and Dark Mode. Since they also have runtime after compilation, the performance will be reduced compared to the traditional solution.

Did you find this article valuable?

Support Shivashish Yadav by becoming a sponsor. Any amount is appreciated!