样式模块化编写
CSS 模块化的常见方案和实现思路
问题
抽离样式模块怎么写,说出思路。
解答
样式模块化的目标是解决 CSS 全局污染、命名冲突、复用困难等问题。常见方案如下:
1. BEM 命名规范
通过命名约定实现模块化,无需工具支持。
/* Block: 独立组件 */
.card {}
/* Element: 组件内部元素,用 __ 连接 */
.card__title {}
.card__content {}
.card__footer {}
/* Modifier: 状态或变体,用 -- 连接 */
.card--highlighted {}
.card__title--large {}
<div class="card card--highlighted">
<h2 class="card__title card__title--large">标题</h2>
<div class="card__content">内容</div>
</div>
2. CSS Modules
构建时自动生成唯一类名,彻底解决命名冲突。
/* Button.module.css */
.button {
padding: 8px 16px;
border-radius: 4px;
}
.primary {
background: #1890ff;
color: white;
}
.disabled {
opacity: 0.5;
cursor: not-allowed;
}
// Button.jsx
import styles from './Button.module.css';
function Button({ primary, disabled, children }) {
// 编译后类名类似: Button_button_x7d2s
const className = [
styles.button,
primary && styles.primary,
disabled && styles.disabled
].filter(Boolean).join(' ');
return <button className={className}>{children}</button>;
}
3. CSS-in-JS (styled-components)
样式与组件绑定,支持动态样式。
import styled from 'styled-components';
// 基础按钮样式
const Button = styled.button`
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
/* 根据 props 动态设置样式 */
background: ${props => props.primary ? '#1890ff' : '#fff'};
color: ${props => props.primary ? '#fff' : '#333'};
&:hover {
opacity: 0.8;
}
/* 禁用状态 */
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
`;
// 继承扩展
const LargeButton = styled(Button)`
padding: 12px 24px;
font-size: 16px;
`;
// 使用
<Button primary>主要按钮</Button>
<LargeButton>大按钮</LargeButton>
4. Sass/Less 模块化
利用预处理器的功能组织样式。
// _variables.scss - 变量
$primary-color: #1890ff;
$border-radius: 4px;
// _mixins.scss - 混入
@mixin flex-center {
display: flex;
justify-content: center;
align-items: center;
}
@mixin button-base {
padding: 8px 16px;
border: none;
border-radius: $border-radius;
cursor: pointer;
}
// _button.scss - 组件样式
@use 'variables' as *;
@use 'mixins' as *;
.button {
@include button-base;
&--primary {
background: $primary-color;
color: white;
}
&--icon {
@include flex-center;
gap: 4px;
}
}
// main.scss - 入口文件
@use 'variables';
@use 'mixins';
@use 'button';
@use 'card';
5. 原子化 CSS (Tailwind)
通过组合原子类构建样式。
// 直接使用原子类
<button className="y47b9 qpcfs gk0te s8n5u tckc3 shmje">
按钮
</button>
// 抽离为组件复用
function Button({ variant = 'primary', children }) {
const variants = {
primary: 'gk0te s8n5u shmje',
secondary: 'rbm2y ljoxq wxlt3',
};
return (
<button className={`y47b9 qpcfs tckc3 ${variants[variant]}`}>
{children}
</button>
);
}
/* 或使用 @apply 抽离 */
.btn {
@apply px-4 py-2 rounded;
}
.btn-primary {
@apply bg-blue-500 text-white hover:bg-blue-600;
}
关键点
- BEM:纯命名约定,无依赖,适合传统项目
- CSS Modules:构建时生成唯一类名,零运行时开销
- CSS-in-JS:样式与组件强绑定,支持动态样式,有运行时成本
- Sass/Less:通过变量、混入、模块化语法组织代码
- 原子化 CSS:高复用、低冗余,但类名较长,需要学习成本
目录