CSS In React

CSS 困境

  • 命名混乱
  • 全局污染,复杂权重,!important 滥用~~

BEM (Block__Element — Modifier)

<body class="scenery">
  <section class="scenery__sky">
    <div class="sky [sky--dusk / sky--daytime] [sky--foggy]">
      <div class="sky__clouds"></div>
      <div class="sky__sun"></div>
    </div>
  </section>
  <section class="scenery__ground"></section>
  <section class="scenery__people"></section>
</body>
// Block
.scenery {
   //Elements
  &__sky {
    fill: screen;
  }
  &__ground {
    float: bottom; 
  }
  &__people {
    float: center;
  }
}

//Block
.sky {
  background: dusk;
  
  // Elements
  
  &__clouds {
    type: distant;
  }
  
  &__sun {
    strength: .025;
  }
  
  // Modifiers
  &--dusk {
    background: dusk;
    .sky__clouds {
      type: distant;
    }
    .sky__sun {
      strength: .025;
    }
  }
  
  &--daytime {
    background: daylight;
    .sky__clouds {
      type: fluffy;
      float: center;
    }
    .sky__sun {
      strength: .7;
      align: center;
      float: top;
    }
  }
}

Pros:

  • Adds scopes to CSS
  • Provides rules and structure
  • Removes nesting
  • Gives possibility to reuse some pieces of markup
  • Makes HTML and CSS self-descriptive

Cons:

  • Classname selection became a tedious task
  • Markup became bloated with all those long class names
  • You needed to explicitly extend every ui component whenever you wanted to reuse
  • Markup became unnecessarily semantic

CSS Module

/* style.css */
.className {
  color: green;
}
import styles from "./style.css";
// import { className } from "./style.css";

element.innerHTML = '<div class="' + styles.className + '">';
/* :local 和 :global */
.normal {
  color: green;
}

/* 以上与下面等价 */
:local(.normal) {
  color: green; 
}

/* 定义全局样式 */
:global(.btn) {
  color: red;
}

/* 定义多个全局样式 */
:global {
  .link {
    color: green;
  }
  .box {
    color: yellow;
  }
}
/* composes 组合(可以不需要 Sass 了) */
/* components/Button.css */
.base { /* 所有通用的样式 */ }

.normal {
  composes: base;
  /* normal 其它样式 */
}

.disabled {
  composes: base;
  /* disabled 其它样式 */
}
  • 所有样式都是 local 的,解决了命名冲突和全局污染问题
  • class 名生成规则配置灵活,可以此来压缩 class 名
  • 只需引用组件的 JS 就能搞定组件所有的 JS 和 CSS
  • 依然是 CSS,几乎 0 学习成本

react-css-modules(babel-plugin-react-css-modules)

Problem of CSS-Module

  • 必须使用 camelCase 形式的类名

  • 当引用一个 className 时必须使用 styles对象

  • 混合 CSS Modules 和全局样式类很麻烦

  • 没有警告的情况下引用未定义的 CSS 模块会解析为 undefined。

<div className='global-css' styleName='local-module'></div>
  • You are not forced to use the camelCase naming convention.
  • You do not need to refer to the styles object every time you use a CSS Module.
  • There is clear distinction between global CSS and CSS modules, e.g.

Styled Components to blend css in JS (fully)

styled-components is a library for React and React Native that allows you to use component-level styles in your application that are written with a mixture of JavaScript and CSS.

import styled from 'styled-components';

const Title = styled.h1`
  font-size: 1.5em;
  color: purple;
`;

<Title>Hello World</Title>
// <div className="title">Hello World</div>
import styled from "styled-components"

const Sky = styled.section`
  padding: 0.5rem 0;
  margin: 0.5rem 1rem;

  ${props => props.dusk && 'background-color: dusk' }
  ${props => props.day && 'background-color: white' }
  ${props => props.night && 'background-color: black' }
`;

// You can use it like so:
<Sky dusk />
<Sky day />
<Sky night />
const Wrapper = styled.div`
    font-size: 1.2em;
 
    .content1 {
        color: red;
    }
 
    .content2 {
        color: green;
    }
`;

<Wrapper>
    <div>You'd better don't do that like so:</div>
    <div className="content1">I am red</div>
    <div className="content2">I am green</div>
</Wrapper>

styled components一种全新的控制样式的编程方式,它能解决CSS全局作用域的问题,而且移除了样式和组件间的映射关系。传统的web开发推崇HTML、CSS、Javascript都分离,styled components则有点“离经叛道”的味道——在JS上编写CSS,什么东西都在JS里写感觉是近几年前端开发的趋势,React就是一个活生生的例子。究竟这是不是一个好趋势,现在还不好判断,但是实践和时间总会给我们一个答案。


参考链接:

  1. BEM I (finally) understand
  2. CSS Modules 详解及 React 中实践
  3. 💅 styled components 💅 — Production Patterns
  4. CSS Modules vs Styled Components
  5. CSS Evolution: From CSS, SASS, BEM, CSS Modules to Styled Components
  6. babel-plugin-react-css-modules