CSS-in-JS

目录

CSS-in-JS

[toc]

CSS-in-JS是组织CSS代码的方式,代表库有styled-component和emotion

传统CSS的缺陷

1. 缺乏模块组织

传统的JS和CSS都没有模块的概念,后来在JS界陆续有了 CommonJS 和 ECMAScript Module,CSS-in-JS可以用模块化的方式组织CSS,依托于JS的模块化方案,比如:

// button1.ts
import styled from '@emotion/styled'

export const Button = styled.button`
  color: turquoise;
`
// button2.ts
import styled from '@emotion/styled'

export const Button = styled.button`
  font-size: 16px;
`
两个文件的两个同名元素的CSS不会互相影响

2. 缺乏作用域

传统的CSS只有一个全局作用域,比如说一个class可以匹配全局的任意元素。随着项目成长,CSS会变得越来越难以组织,最终导致失控。CSS-in-JS可以通过生成独特的选择符,来实现作用域的效果

img

const css = styleBlock => {
  const className = Hash(styleBlock);
  const styleEl = document.createElement('style');
  styleEl.textContent = `
    .${className} {
      ${styleBlock}
    }
  `;
  document.head.appendChild(styleEl);
  return className;
};
const className = css(`
  color: red;
  padding: 20px;
`); // 'c23j4'

3. 隐式依赖,让样式难以追踪

比如这个CSS样式:

.target .name h1 {
  color: red
}

body #container h1 {
  color: green
}
<!doctype html>
<html lang="en">
<body>
  <div id='container'>
   <div class='target'>
     <div class='name'>
       <h1>颜色?</h1>
     </div>
   </div>
  </div>
</body>
</html>

比较麻烦判断h1元素最终显式为什么颜色,DOM树越复杂越难追踪

而CSS-in-JS的方案就简单直接、易于追踪

export const Title = styled.h1`
  color: green;
`
<Title>
  颜色?
</Title>

4. 没有变量

传统的CSS规则里没有变量,但是在 CSS-in-JS 中可以方便地控制变量

const Container = styled.div(props => ({
  display: 'flex',
  flexDirection: props.column && 'column'//加入条件判断或变量计算
}))

5. CSS选择器与HTML元素耦合

.target .name h1 {
  color: red
}

body #container h1 {
  color: green
}
<!doctype html>
<html lang="en">
<body>
  <div id='container'>
   <div class='target'>
     <div class='name'>
       <h1>我是啥颜色?</h1>
     </div>
   </div>
  </div>
</body>
</html>

如果想把 h1 改成h2,必须要同时改动 CSS 和 HTML。而在CSS-in-JS中,HTML和CSS是结合在一起的,易于修改

Emotion 介绍

  • library: https://github.com/emotion-js/emotion

  • docs: https://emotion.sh/docs/introduction

emotion是一个JavaScript库,使用emotion可以用写js的方式写css代码。在react中安装emotion后,可以很方便进行css的封装,复用。使用emotion后,浏览器渲染出来的标签是会加上一个css开头的标识。

/** @jsx jsx */
import { jsx } from '@emotion/react'

render(
  <div
    css={
      backgroundColor: 'hotpink',
       '&:hover': {
        color: 'lightgreen'
      }
    }
  >
    This has a hotpink background.
  </div>
)

这种写法比起React自带的style的写法功能更强大,比如可以处理级联、伪类等style处理的不了的情况

<span style=>{keyword}</span>

JSS

https://cssinjs.org/?v=v10.6.0

  • 阮一峰 https://www.ruanyifeng.com/blog/2017/04/css_in_js.html https://polished.js.org/