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