准备工作
首先创建一个react项目,执行npx create-react-app react-css
然后再创建一个components,文件夹,在本篇中以一个例子会在components下创建一个组件来进行演示。
第一种用法: 行内css
js
export default function StyleCssComponent() {
return (
<button
style={{
outline: "none",
border: "none",
borderRadius: "5px",
backgroundColor: "#409EFF",
fontSize: "14px",
color: "#fff",
padding: "6px 12px",
}}
>
按钮
</button>
);
}
行内css 书写注意点:
- 要写在一个对象里面
- 两个单词的属性需要采用驼峰写法
行内样式的优缺点:
优点: 可以动态计算,所以行内css 的使用场景一般是需要进行动态计算的时候才会用到,比如说动态获取窗口变化来计算当前盒子的宽高
缺点: 行内样式写多了会使代码的结构看上去非常乱,且不好维护,也不好重用
第二种写法: 普通css 文件导入
1. 静态类名写法
ClassCssComponent.css
css
.btn-primary {
outline: none;
border: none;
border-radius: 5px;
background-color: #409EFF;
font-size: 14px;
color: #fff;
padding: 6px 12px;
}
组件里面进行导入使用:
js
import "../assets/css/ClassCssComponent.css";
export default function ClassCssComponent() {
return <button className="btn-primary">按钮</button>;
}
采用css文件导入的写法的注意点: 标签上使用className 进行使用,而不是class
需要根据条件来写class 的写法,比如说button 按钮上默认有一个class 类名,另一个class 类名需要更根据条件进行添加怎么写呢?
2. 第一种动态类名写法
ClassCssComponent.css
css
.btn {
outline: none;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 14px;
color: #ccc;
padding: 6px 12px;
}
.btn-primary {
background-color: #409EFF;
color: #fff;
}
ClassCssComponent.js
js
import "../assets/css/ClassCssComponent.css";
export default function ClassCssComponent() {
const type = "primary";
return <button className={"btn " + (type ? "btn-primary" : "")}>按钮</button>;
}
这种写法只有一种情况的判断的的时候看上去没太大问题,但是如果有多种情况,比如说还有btn-success, btn-info,btn-warning, btn-danger,那么这个三元表表达式就会变得很复杂,会使代码阅读变得非常困难。
3. 第二种动态类名写法
ClassCssComponent.css
css
.btn {
outline: none;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 14px;
color: #333;
padding: 6px 12px;
background-color: #fff;
}
.btn-primary {
background-color: #409EFF;
color: #fff;
}
.btn-success {
background-color: #67C23A;
color: #fff;
}
.btn-info {
background-color: #909399;
color: #fff;
}
.btn-warning {
background-color: #E6A23C;
color: #fff;
}
.btn-danger {
background-color: #409EFF;
color: #F56C6C;
}
js
import "../assets/css/ClassCssComponent.css";
export default function ClassCssComponent() {
const type = "primary";
let btnTypeClass = "";
if (type === "primary") {
btnTypeClass = "btn-primary";
} else if (type === "success") {
btnTypeClass = "btn-success";
} else if (type === "info") {
btnTypeClass = "btn-info";
} else if (type === "warning") {
btnTypeClass = "btn-warning";
} else if ("danger") {
btnTypeClass = "btn-danger";
}
return <button className={"btn " + btnTypeClass}>按钮</button>;
}
这种情况相对于第一种解决方案,在有多种条件来判断class类名的添加的时候,相对会好一些,但是这也不是太完美的一种写法。再想想有没有一种写法可想以和Vue 那样,写成一个对象,键名是class 类名称,值的真假来决定这个class 类名要不要显示呢?其实是有办法的,可以借助第三方库来实现。
4. 第三种动态类名写法(借助classNames)
安装 classnames
npm i classnames
使用:
js
import "../assets/css/ClassCssComponent.css";
import classnames from "classnames";
export default function ClassCssComponent() {
const type = "primary";
const btnTypeClass = classnames("btn", {
"btn-primary": type === "primary",
"btn-success:": type === "success",
"btn-info": type === "info",
"btn-warning": type === "warning",
"btn-danger": type === "danger",
});
return <button className={btnTypeClass}>按钮</button>;
}
这样同样能达到前面的效果,写法比之前好看多了。
classname 也支持数组形式的写法:
js
import "../assets/css/ClassCssComponent.css";
import classnames from "classnames";
export default function ClassCssComponent() {
const type = "primary";
const btnTypeClass = classnames([
"btn",
{
"btn-primary": type === "primary",
"btn-success:": type === "success",
"btn-info": type === "info",
"btn-warning": type === "warning",
"btn-danger": type === "danger",
},
]);
return <button className={btnTypeClass}>按钮</button>;
}
classnames还支持很多种写法,更多写法可以查看官方文档 github.com/JedWatson/c...
三、模块化css
到这里class 的写法已接近完美了,但其实还是存在一些问题,组件之间的样式会相互影响。
来看个案例,现在有两个组件,一个BoxComponent1.js,一个BoxComponent2.js,BoxComponent1.js导入一个BoxComponent1.css, 一个BoxComponent2.js导入BoxComponent2.css
BoxComponent1.js
js
import "../assets/css/BoxComponent1.css";
export default function BoxComponent1() {
return <div className="box">box1</div>;
}
BoxComponent1.css
css
.box {
width: 100px;
height: 100px;
background: #f00;
color: #fff;
font-size: 40px;
margin: 20px;
display: flex;
justify-content: center;
align-items: center;
}
BoxComponent2.js
js
import "../assets/css/BoxComponent2.css";
export default function BoxComponent2() {
return <div className="box">box2</div>;
}
BoxComponent2.css
css
.box {
width: 200px;
height: 200px;
background: greenyellow;
color: #fff;
font-size: 40px;
margin: 20px;
display: flex;
justify-content: center;
align-items: center;
}
按照我们的想法这两个样式应该是不一样的,box1是红色,box2是绿色,box1宽高是100px,box2宽高是200px。但是当你打开浏览器的时候你会惊奇的发现,两个样式显示居然是一样的,都采用了box2的样式。如下图:

这显然不是我们想要的效果。为什么会出现这种情况呢,因为 create-react-app 创建的项目是单页面应用,虽然我们把css 写在了不同的文件,但是打包之后css都会打包到一个文件里面。来执行下打包命令 npm run build
看下是不是这样的.
可以看到box1和box2的都合并到了一个里面。这就是造成样式互相影响的原因,在开发环境是直接将css 全部都放入到了页面的style中。

这样同样都会相互影响。那这个问题怎么解决呢?这个时候就需要用到css模块化了。npx create-react-app 创建的项目 已经自带css 模块化了,不需要再去安装依赖。来看下具体的使用。
- 首先需要将BoxComponent1.css改成 BoxComponent1.module.css
- 修改BoxComponent1.js中修改导入路径为: import box1Css from "../assets/css/BoxComponent1.module.css";
- 使用类名由 className="box"改为className={box1Css.box}
修改后的BoxComponent1.js如下
js
import box2Css from "../assets/css/BoxComponent2.module.css";
export default function BoxComponent2() {
return <div className={box2Css.box}>box2</div>;
}
BoxComponent2 的修改方式和BoxComponent1一样。
修改完成之后,查看效果:

可以看到,现在就使用了各自的样式了。css 模块化这怎么做到样式隔离的呢,css模块会在编译后会给我们的类名加一个前缀和后缀,前缀为组件名称,后缀是随机字符串。

这样我们就很好的解决了样式隔离问题。
今天就分享到这里了,感谢收看,本篇收录到React 知识储备专栏,欢迎关注后续更新