# CSS-in-JS

By [Specter](https://paragraph.com/@specterv) · 2021-11-08

---

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可以通过生成独特的选择符，来实现作用域的效果

![](https://storage.googleapis.com/papyrus_images/739944b4b36f360ec7af81487e6137e60f1c967b3f57d697dbe4c3fbc8c72de0.png)

    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](https://github.com/emotion-js/emotion)

docs： [https://emotion.sh/docs/introduction](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://cssinjs.org/?v=v10.6.0)

阮一峰 [https://www.ruanyifeng.com/blog/2017/04/css\_in\_js.html](https://www.ruanyifeng.com/blog/2017/04/css_in_js.html) [https://polished.js.org/](https://polished.js.org/)

---

*Originally published on [Specter](https://paragraph.com/@specterv/css-in-js)*
