界面样式
在大型企业级前端项目中,一套严谨、可扩展的 CSS 架构体系是保障工程化质量的核心要素,直接影响代码的可维护性、多主题扩展能力以及团队协作效率。基于这一认知,iBiz前端团队采用 BEM 命名规范(Block-Element-Modifier)作为原子化 CSS 组织的基础,结合 Sass 预处理器的变量、混入和模块化特性,并引入 ITCSS(Inverted Triangle CSS)分层架构 实现样式文件的层级化管控。
这一技术组合的优势在于:
可维护性:通过 BEM 的严格命名约定消除样式冲突,ITCSS 的分层依赖管理(从泛用到具体)确保样式可预测;
扩展性:Sass 的变量与函数机制支持动态主题切换,ITCSS 的抽象层(如 settings、tools)便于复用;
开发效率:明确的架构规范降低认知成本,开发者可专注于业务逻辑而非样式污染问题。
该方案在多人协作、长期迭代的场景中提供了稳定的样式管理基础设施。
BEM
BEM 是一种命名约定,通过将类名分为 Block(块)、Element(元素)和 Modifier(修饰符)三部分,使样式更具模块化和可读性。SCSS 的嵌套语法与 BEM 结合,可以进一步简化代码结构,可以编写出结构清晰、易于维护的 CSS 代码。
Sass预处理器
Sass(Syntactically Awesome Style Sheets) 是CSS的元语言(metalanguage)和预处理器,它通过扩展CSS语法提供了现代化的样式开发能力:
核心特性包括:
- 变量系统:支持类型化变量(数字、字符串、颜色等),实现设计变量管理
- 嵌套规则:符合DOM结构的嵌套语法,通过
&父选择器实现BEM等模式 - 混合宏(Mixins):可参数化的样式复用单元,支持默认参数和条件逻辑
- 模块系统:基于
@use的依赖管理,解决全局命名空间污染问题 - 函数式特性:内置100+工具函数,支持自定义函数实现动态样式计算
ITCSS分层架构
ITCSS (Inverted Triangle CSS) 是一种可扩展的 CSS 架构方法论,通过分层管理样式特异性(specificity)和影响范围,实现样式代码的科学管理。
Settings // 全局变量配置
Tools // 预处理器函数/混合
Generic // 重置和标准化
Elements // 原生HTML元素样式
Objects // 设计模式抽象
Components // 具体UI组件
Trumps // 工具类覆盖- 采用倒三角特异性控制模型
- 每层严格定义职责边界
- 通过@import依赖管理确保层叠顺序
TIP
Settings和Tools的封装在@ibiz-template/theme基础包中,而平台相关的主题实现则按端侧进行隔离——Web端主题通过@ibiz-template/web-theme包实现,移动端主题则由@ibiz-template/mob-theme包实现。
样式功能集
主题样式功能主要在@ibiz-template/theme包中,它基于Sass预处理器中的变量、函数、混合,提供了bem命名体系的基础变量与函数实现。
基础变量
| 变量 | 值 | 说明 |
|---|---|---|
| $namespace | ibiz | 所有变量基础字符 |
| $common-separator | - | bem块分割符 |
| $element-separator | __ | bem元素分割符 |
| $modifier-separator | -- | bem修饰符分隔符 |
| $state-prefix | is- | 状态分隔符 |
Sass函数
| 名称 | 说明 |
|---|---|
| getCssVarName | 获取css变量名称 |
| getCssVar | 获取css变量值 |
| bem | 根据输入值拼接为bem格式 |
| rem | 输出rem值,默认根字体大小为16px做转换 |
Sass混合
| 名称 | 说明 |
|---|---|
| b | 将输入值根据bem规范拼接 |
| e | 将输入值根据bem规范拼接 |
| m | 将输入值根据bem规范拼接 |
| when | 将输入值拼接状态修饰符 |
在 ts 中使用 BEM
import { useNamespace } from '@ibiz-template/vue3-util';
const ns = useNamespace('layout');
// bem class 命名
ns.b() => 'ibiz-layout'
ns.b('header') => 'ibiz-layout-header'
ns.e('header') => 'ibiz-layout__header'
ns.m('hover') => 'ibiz-layout--hover'
ns.be('header', 'title') => 'ibiz-layout-header__title'
ns.em('title', 'hover') => 'ibiz-layout__title--hover'
ns.bm('header', 'hover') => 'ibiz-layout-header--hover'
ns.bem('header', 'title', 'hover') => 'ibiz-layout-header__title--hover'
// 状态 class 样式命名
ns.is('loading', false) => ''
ns.is('loading', true) => 'is-loading'
// css 变量 style 对象
ns.cssVar({ 'color': 'red' }) => { '--ibiz-color': 'red' }
ns.cssVarBlock({ 'color': 'red' }) => { '--ibiz-layout-color': 'red' }
// css var 变量名称拼接
ns.cssVarName('color') => '--ibiz-color'
ns.cssVarBlockName('color') => '--ibiz-layout-color'在 scss 中使用 BEM
/**
.ibiz-layout { font-size: 14px; }
*/
@include b('layout') {
font-size: 14px;
}
/**
.ibiz-layout { font-size: 14px; }
.ibiz-layout__header { font-size: 14px; }
*/
@include b('layout') {
font-size: 14px;
@include e('header') {
font-size: 14px;
}
}
/**
.ibiz-layout { font-size: 14px; }
.ibiz-layout__header { font-size: 14px; }
.ibiz-layout__header--hover { color: red; }
*/
@include b('layout') {
font-size: 14px;
@include e('header') {
font-size: 14px;
@include m('hover') {
color: red;
}
}
}
/**
.ibiz-layout .is-loading { display: block; }
*/
@include b('layout') {
@include when('loading') {
display: block;
}
}