[React Series] CSS in React

This article is from the #React tutorial series: https://mp.weixin.qq.com/mp/appmsgalbum?__biz=Mzg5MDAzNzkwNA==&action=getalbum&album_id=1566025152667107329 )

1. CSS solution in React

1.1. css in react

In fact, CSS has always been a pain point for React, and it is also a point that many developers complain about and criticize.

Choosing the right CSS solution in componentization should meet the following criteria:

  • You can write local CSS: CSS has its own scope and will not pollute the native content in other components at will;
  • You can write dynamic css: you can get some status of the current component and generate different css styles according to the changes in the status;
  • Supports all CSS features: pseudo-classes, animations, media queries, etc.;
  • It is simple and convenient to write, and it is best to conform to the consistent CSS style characteristics;
  • etc…

At this point, Vue does far better than React:

  • Vue writes its own styles by .vuewriting tags in files ;<style><style>
  • Determine whether the written style is globally valid or locally valid by adding the scoped attribute;
  • Use the lang attribute to set your favorite preprocessors such as less and sass;
  • Set and change css according to the latest status through inline styles;
  • etc…

Although Vue cannot be called perfect in CSS, it is simple, natural and convenient enough. At least the unified style will not cause multiple developers and multiple projects to adopt different styles.

In comparison, React officially does not provide a unified style in React:

  • From this, there are dozens of different solutions and hundreds of different libraries, from ordinary css, to css modules, to css in js;
  • Everyone is looking for the best or most suitable CSS solution, but so far there is no unified solution;

In this article, I will introduce four selected solutions:

  • Option 1: How to write inline styles;
  • Option 2: Ordinary CSS writing method;
  • Option 3: css modules;
  • Option 4: css in js (styled-components);

1.2. Common solutions

1.2.1. Inline styles

Inline style is an officially recommended way of writing CSS styles:

  • styleAccepts a JavaScript object using camelCase named properties instead of CSS strings;
  • And you can reference statethe state in it to set related styles;
export default class App extends PureComponent {
    
    
  constructor(props) {
    
    
    super(props);

    this.state = {
    
    
      titleColor: "red"
    }
  }

  render() {
    
    
    return (
      <div>
        <h2 style={
    
    {
    
    color: this.state.titleColor, fontSize: "20px"}}>我是App标题</h2>
        <p style={
    
    {
    
    color: "green", textDecoration: "underline"}}>我是一段文字描述</p>
      </div>
    )
  }
}

Advantages of inline styles:

  1. Inline styles, there will be no conflict between styles

  2. You can dynamically obtain the current statestatus

Disadvantages of inline styles:

  1. You need to use camel case in writing.

  2. Some styles have no hints

  3. Lots of styles, confusing code

  4. Some styles cannot be written (such as pseudo-classes/pseudo-elements)

Therefore, the official still hopes to combine appropriate inline writing with ordinary css;

1.2.2. Ordinary css

Ordinary css is usually written to a separate file.

App.jsWrite React logic code in:

import React, {
    
     PureComponent } from 'react';

import Home from './Home';

import './App.css';

export default class App extends PureComponent {
    
    
  render() {
    
    
    return (
      <div className="app">
        <h2 className="title">我是App的标题</h2>
        <p className="desc">我是App中的一段文字描述</p>
        <Home/>
      </div>
    )
  }
}

App.cssWrite React style code in:

.title {
    
    
  color: red;
  font-size: 20px;
}

.desc {
    
    
  color: green;
  text-decoration: underline;
}

This writing method is consistent with the writing method in ordinary web development:

  • If we write according to ordinary web standards, then there won’t be much of a problem;
  • However, in component development, we always hope that the component is an independent module. Even the style only takes effect within itself and does not affect each other;
  • But ordinary css is global css, and styles will affect each other;

For example, Home.jsthe logic code written:

import React, {
    
     PureComponent } from 'react';

import './Home.css';

export default class Home extends PureComponent {
    
    
  render() {
    
    
    return (
      <div className="home">
        <h2 className="title">我是Home标题</h2>
        <span className="desc">我是Home中的span段落</span>
      </div>
    )
  }
}

I also wrote Home.cssthe style code:

.title {
    
    
  color: orange;
}

.desc {
    
    
  color: purple;
}

In the end, styles will be layered on top of each other, and only one style will take effect;

1.2.3. css modules

CSS modules are not a React-specific solution, but can be used in any environment that uses a configuration similar to webpack .

However, if it is used in other projects, then we need to configure it ourselves, such as webpack.config.jsin the configuration modules: true.

But React's scaffolding already has built-in css modulesconfiguration:

  • .css/.less/.scssetc. style files are modified to .module.css/.module.less/.module.scssetc.;
  • You can then quote and use it;

The way to use it is as follows:

Insert image description here

The class name finally generated by this way of using CSS will be globally unique:

Insert image description here

css modulesIt does solve the problem of local scope, and it is also a solution that many people like to use in React.

But this solution also has its own shortcomings:

  • The referenced class name cannot use the connector ( .home-title) and is not recognized in JavaScript;
  • All classNamemust be {style.className}written using the form ;
  • It is inconvenient to dynamically modify certain styles, so you still need to use inline styles;

If you think the above flaws are OK, then you can choose to use it in development css modules, and it is also a very popular method in React.

二. CSS in JS

2.1. Understanding CSS in JS

In fact, the official documentation also mentions the CSS in JS solution:

  • "CSS-in-JS" refers to a mode in which CSS is generated by JavaScript rather than defined in an external file;
  • Note that this functionality is not part of React, but is provided by a third-party library. React doesn’t have a clear stance on how styles are defined;

In traditional front-end development, we usually separate structure (HTML), style (CSS), and logic (JavaScript).

  • But in the previous study, we mentioned that React believes that the logic itself and the UI cannot be separated, so there is JSX syntax.
  • What about style? Style is also part of the UI;
  • In fact, the CSS-in-JS mode is a way to write styles (CSS) into JavaScript, and the state of JavaScript can be conveniently used;
  • So React is called All in JS;

Of course, this development method has also been criticized a lot:

Although there are criticisms, in our opinion many excellent CSS-in-JS libraries are still very powerful and convenient:

  • CSS-in-JS uses JavaScript to give CSS some capabilities, including style nesting, function definition, logic reuse, dynamic state modification, etc. similar to CSS preprocessors;
  • Still, the CSS preprocessor also has certain capabilities, but obtaining dynamic state is still a difficult point to handle;
  • Therefore, it can be said that CSS-in-JS is currently the most popular solution for writing CSS in React;

What are the currently popular CSS-in-JS libraries?

  • styled-components
  • emotion
  • glamorous

At present, it can be said that styled-componentsit is still the most popular CSS-in-JS library in the community, so we styled-componentsfocus on the explanation;

Install styled-components:

yarn add styled-components

2.2. styled-components

2.2.1. Label template string

ES6 adds template string syntax, which many people will use.

But there is another use of template strings: Tagged Template Literals.

Let’s take a look at a common JavaScript function:

function foo(...args) {
    
    
  console.log(args);
}

foo("Hello World");

Under normal circumstances, we all 函数名()call it through the method. In fact, there is another way to call the function:

foo`Hello World`; // [["Hello World"]]

If we insert other variables when calling:

foo`Hello ${
      
      name}`; // [["Hello ", ""], "kobe"];
  • The template string is split;
  • The first element is an array, which is a combination of strings split by the module string;
  • The following elements are the contents passed in module strings one by one;

In styled componentthis way, we parse the module string and finally generate the style we want.

2.2.2. Basic use of styled

styled-componentsThe essence is to finally create a component through function calls:

  • This component will be automatically added with a unique one class;
  • styled-componentsclassRelevant styles will be added to this ;

For example, the components we normally develop Homeare in this format:

<div>
  <h2>我是Home标题</h2>
  <ul>
    <li>我是列表1</li>
    <li>我是列表2</li>
    <li>我是列表3</li>
  </ul>
</div>

divWe want to add a special one to the outer layer classand add related styles:

Insert image description here

In addition, it supports style nesting similar to CSS preprocessors:

  • Supports direct descendant selectors or descendant selectors, and writes styles directly;
  • &The current element can be obtained through symbols;
  • Direct pseudo-class selectors, pseudo-elements, etc.;
const HomeWrapper = styled.div`
  color: purple;

  h2 {
    font-size: 50px;
  }

  ul > li {
    color: orange;

    &.active {
      color: red;
    }

    &:hover {
      background: #aaa;
    }

    &::after {
      content: "abc"
    }
  }
`

The final effect is as follows

Insert image description here

2.2.3. props, attrs attributes

propsCan penetrate

Define a styledcomponent:

const HYInput = styled.input`
  border-color: red;

  &:focus {
    outline-color: orange;
  }
`

Components used styled:

<HYInput type="password"/>

propscan be passed to styledcomponents

<HomeWrapper color="blue">
</HomeWrapper>

You can get the incoming data when using color:

const HomeWrapper = styled.div`
  color: ${
    
    props => props.color};
}
  • Obtaining propsrequires ${}passing in an interpolation function, which propswill be used as a parameter of the function;
  • This method can effectively solve the problem of dynamic styles;

Add attrsproperties

const HYInput = styled.input.attrs({
    
    
  placeholder: "请填写密码",
  paddingLeft: props => props.left || "5px"
})`
  border-color: red;
  padding-left: ${
      
      props => props.paddingLeft};

  &:focus {
    outline-color: orange;
  }
`

2.2.4. styled advanced features

Supports style inheritance

Write styledcomponents

const HYButton = styled.button`
  padding: 8px 30px;
  border-radius: 5px;
`

const HYWarnButton = styled(HYButton)`
  background-color: red;
  color: #fff;
`

const HYPrimaryButton = styled(HYButton)`
  background-color: green;
  color: #fff;
`

Use of buttons

<HYButton>我是普通按钮</HYButton>
<HYWarnButton>我是警告按钮</HYWarnButton>
<HYPrimaryButton>我是主要按钮</HYPrimaryButton>

styled set theme

Customize your own theme globally and Providershare it with:

import {
    
     ThemeProvider } from 'styled-components';

<ThemeProvider theme={
    
    {
    
    color: "red", fontSize: "30px"}}>
  <Home />
  <Profile />
</ThemeProvider>

styledThe content of the theme can be obtained in the component :

const ProfileWrapper = styled.div`
  color: ${
      
      props => props.theme.color};
  font-size: ${
      
      props => props.theme.fontSize};
`

2.3. classnames

Add class in vue

Adding dynamics to an element in Vue classis a very simple thing:

You can do this by passing in an object:

<div
  class="static"
  v-bind:class="{ active: isActive, 'text-danger': hasError }"
></div>

You can also pass in an array:

<div v-bind:class="[activeClass, errorClass]"></div>

Even mixing objects and arrays:

<div v-bind:class="[{ active: isActive }, errorClass]"></div>

Add class in react

React gives us developers enough flexibility in JSX. You can decide whether to add something through some logic just like writing JavaScript code class:

import React, {
    
     PureComponent } from 'react'

export default class App extends PureComponent {
    
    
  constructor(props) {
    
    
    super(props);

    this.state = {
    
    
      isActive: true
    }
  }

  render() {
    
    
    const {
    
    isActive} = this.state; 

    return (
      <div>
        <h2 className={
    
    "title " + (isActive ? "active": "")}>我是标题</h2>
        <h2 className={
    
    ["title", (isActive ? "active": "")].join(" ")}>我是标题</h2>
      </div>
    )
  }
}

At this time we can use a third-party library:classnames

  • Obviously, this is a classnameslibrary for dynamic addition.

Let’s use the most common use cases:

classNames('foo', 'bar'); // => 'foo bar'
classNames('foo', {
    
     bar: true }); // => 'foo bar'
classNames({
    
     'foo-bar': true }); // => 'foo-bar'
classNames({
    
     'foo-bar': false }); // => ''
classNames({
    
     foo: true }, {
    
     bar: true }); // => 'foo bar'
classNames({
    
     foo: true, bar: true }); // => 'foo bar'

// lots of arguments of various types
classNames('foo', {
    
     bar: true, duck: false }, 'baz', {
    
     quux: true }); // => 'foo bar baz quux'

// other falsy values are just ignored
classNames(null, false, 'bar', undefined, 0, 1, {
    
     baz: null }, ''); // => 'bar 1'

Guess you like

Origin blog.csdn.net/lyabc123456/article/details/135345828