来源
前言
最近有个项目接触到了Styled-Components
觉得这是一个不错的Css-In-Js的方案,当然也有很多人提到emotion
这个方案,因为我没有深入的去接触过后者,这里就不说谁好谁坏的。
这篇文章简单记录一下以下问题:
- Styled Components覆盖修改Antd的样式的问题
- 和Css共存,如何让Css覆盖Styled Components的样式
- Styled Components使用Css Modules
- Styled Components使用Less
- Css Modules配置报错问题
环境准备
首先我们使用Create-React-App
脚手架初始化一个项目,对于开发React的人来说这个脚手架那是相当的好用。
初始化完成后执行安装以下依赖,这里主要是安装antd styled-components和定制化Create-React-App项目的两个包, 配置Antd方面的内容可以查看。npx create-react-app styled-demo
复制代码
根目录创建config-overrides.js,用customized-cra来增加babel-plugin-import配置动态引入Antd组件yarn add styled-components babel-plugin-import react-app-rewired customize-cra antd
复制代码
替换package.json中的npm scripts,这里原本的eject无需替换,react-app-rewired并不提供该功能const { override, fixBabelImports } = require('customize-cra');
module.exports = override(fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: 'css',
})
);
复制代码
精简App.js"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
复制代码
之后yarn start运行就可以看到一个Antd的蓝色按钮了import React from 'react';
import { Button } from 'antd';
import './App.css';
function App() {
return (
<div className="App">
<Button type="primary">Button 1</Button>
</div>
);
}
export default App;
复制代码
Styled Components覆盖修改Antd的样式的问题
新建src/style.js来创建一个button
App.js中增加,后再运行就可以看到两个按钮了import styled from 'styled-components';
import { Button } from 'antd';
export const StyledButton = styled(Button)`
&.ant-btn-primary {
color: red;
}
`;
复制代码
<StyledButton type="primary">Button2</StyledButton>
复制代码
简单看一下这里的结构,head标签中所有的样式都会被style标签追加进去,而我们styled-components生成的会被加载到尾部,根据Css优先级那么就不难理解我们上述覆盖Antd样式的原理了。
那么有人问了既然styled-components被放在了最后,那如果和普通引入Css的方式一起使用怎么样才能让Css中的优先级最高呢?这就引出我们的下一部分
和Css共存,如何让Css覆盖Styled Components的样式
src/App.css中添加样式
src/App.js添加div.CssDiv {
color: #ccc;
}
复制代码
可以看到我们的按钮3是红色,并没有变为<StyledDiv className="CssButton">Div</StyledDiv>
复制代码
#ccc
的颜色这是为什么呢?我们来看一下style标签的顺序,依旧是styled-components生成的排在了最后。
那我们应该如何做呢?要么调整引用顺序(用webpack不太好调整,而且我们webpack配置目前还是不可见的),要么调整Css权重的优先级;我们采取第二种方案这里有个小技巧,直接将src/App.js中的class选择器重复一遍,这里通过这种方式来提升Css优先级就让div的文字变为#ccc
实现效果了.CssDiv.CssDiv {
color: #ccc;
}
复制代码
Styled Components使用Css Modules
新建demo.module.css,这里需要注意react-rewired给我们提供了一种快速开启css modules的方式,只需要命名为xxx.module.css/less 等都可以直接开启
src/App.js中添加,既可以玉兰看到效果.ModuleText {
color: #000;
}
复制代码
<div className={style.ModuleText}>
css modules
</div>
复制代码
配置less
安装less相关依赖
修改上面的demo.module.css为demo.module.less;同时src/App.js中的引用也要修改哦 修改config-overriddes.js 保存之后重新运行yarn start即可yarn add less less-loader
复制代码
module.exports = override(fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: 'css',
}),
addLessLoader({
localIdentName: "[local]--[hash:base64:5]" // if you use CSS Modules, and custom `localIdentName`, default is '[local]--[hash:base64:5]'.
})
);
复制代码
彩蛋
各位尝试less之后有些人是不是看到了下面的错误
这是因为新的Create-React-App中引入的Css-Loader^3.0.0
有一些break Change; 类似于localIdentName这样的属性在css-loader中移动到了modules对象中了,custom-cra在调用addLessLoader方法的时候无法正确传递配置;那么怎么解决呢?yarn add customize-cra@next //更新最新的customize-cra
复制代码
重新运行之后就ok了。 想知道更多具体的原因可以参见issue,这里大家有什么想法可以写上去目前该功能还没有正式完成修改。下图是我的修改想法如果赞同点个赞,后续我也会提出pr的说不定作者就采纳了哈哈// 更新配置
addLessLoader({
cssModules: {
localIdentName: "[local]--[hash:base64:5]" // if you use CSS Modules, and custom `localIdentName`, default is '[local]--[hash:base64:5]'.
}
})
复制代码
附上2020年01月17日customize-cra next分支源码截图,这就是我们为什么要添加cssModules属性的原因