mcpField
B
bem-structure

bem-structure

github.com/rolemodel设计与 UI7190 次安装3 天前更新
代码仓库

关于 bem-structure

bem-structure 是用于编写和审查 CSS 的 Agent 技能,遵循 BEM 命名与结构规范。它还要求优先复用适用的 Optics 组件,避免创建重复区块。

主要功能

  1. 01遵循 BEM 命名规范
  2. 02组织区块、元素和修饰符
  3. 03使用显式类选择器
  4. 04考虑现有 Optics 组件
  5. 05优先采用清晰且影响较小的 CSS 改动

适用场景

  1. 01审查 CSS 的 BEM 一致性
  2. 02将样式重构为 BEM 结构
  3. 03修正含糊或不一致的类名
  4. 04判断使用 Optics 组件还是新建区块

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/rolemodel/rolemodel-skills --skill bem-structure

安装后在 Claude Code 中输入/bem-structure确认已加载。

详细介绍

概述

这项技能指导 AI 使用 BEM(Block Element Modifier)方法编写 CSS,通过清晰的命名约定和组件结构,创建易于维护、可扩展且可复用的样式表,同时判断其作用范围、风险和架构影响。还应将 BEM 与我们的 RoleModel 设计系统 Optics 配合使用,避免重复创建已有内容。如果已有适用的 Optics 组件,就应使用它,必要时进行覆盖,而不是创建新的 BEM 块。

Agent 应优先考虑清晰性、可预测性,并尽量减少意外副作用。

关键词:CSS 审查、BEM 结构、BEM 方法、CSS 最佳实践、重构 CSS、审查 CSS、修复我的 CSS、修复我的 BEM、将我的 CSS 转换为 BEM

什么是 BEM?

BEM 是 Block Element Modifier 的缩写——一种帮助你在前端开发中创建可复用组件并共享代码的方法。

模式语法示例
块.block.card
元素.block__element.card__title
块修饰符.block--modifier.card--elevated
元素修饰符.block__element--modifier.card__title--large
多词名称.block-name.user-profile
命名约定
  • 与其他开发工作一样,名称应清晰表达意图。
  • 在 BEM 中,命名要表达的意图并非所应用的样式或外观,而是它在界面中的用途。
  • 具体的样式通常不适合作为名称,但修饰符除外(small、large、padded 等)。
  • 某些情况下,可以根据具体工作流命名(如带日期的日历)。
  • 根据具有共同类型的工作流命名,通常最为合适(form、table、card、button)。
  • 不一定要根据更广泛的 UI 抽象命名,但在无需上下文的抽象场景中可以这样做(primary、large 等)。
  • 名称应足够具体,能够清晰表达用途;如适用,也应足够通用,以便复用。并非总是能够或适合复用,因此不要过度追求通用性。
  • 尽量使用明确、不易产生歧义的名称。修饰符尤其需要注意这一点。
  • 使用扁平的 BEM 类,并在修饰符中显式使用 &。
  • DOM 结构无需遵循 CSS 类结构。

如果因项目限制或其他原因无法遵循这些指南,请在聊天输出中说明偏离的原因。

基本语法

✅ 正确(请这样做)

.block {
  .block__element {
    &.block__element--modifier { }
  }
  
  &.block--modifier { }
}
<div class="block">
  <div class="block__element">...</div>
  <div class="block__element block__element--modifier">...</div>
</div>

<div class="block block--modifier">
  <div class="block__element">...</div>
  <div class="block__element">...</div>
</div>

🚫 错误(不要这样做)

.block {
  .block--modifier { } /* Use `&` before all Modifier class names */
}

.block_element { /* Use `__` between Blocks and Elements and nest Element within the Block */
  &.block__element-modifier { } /* Use `--` between the Modifier and its Element */
}
<div class="block">...</div>  
<div class="block__element">...</div> 
  <div class="block__element--modifier">...</div> 
</div>

<div class="block__element"> 
  <div class="block__element">...</div> 
</div>

规则摘要

  • 所有类名都必须是完全显式的 BEM。可以嵌套以便组织代码,但选择器不应依赖标签名或 ID。
  • & 只能用作对完整选择器的文本引用。
  • 不得使用 & 构造类名(&--、&__)。
  • 嵌套仅用于组织代码;必须使用显式的 BEM 类名。可以使用嵌套选择器,将元素限定在其块的范围内。
  • 可以使用 &,将修饰符与其块或元素放在一起,同时保持选择器显式。

✅ 正确(请这样做)

.card {
  &.card--featured {}
  &.card--compact {}
  &.card--featured {
    &.card--compact {}
  }
}

🚫 错误(不要这样做)

.card {
  &--featured {}
  &__title {}
  &__title--large {}
}

块

封装一个本身具有意义的独立实体。块可以相互嵌套和交互,但在语义上彼此平等,不存在优先级或层级关系。没有 DOM 表示的整体实体(例如控制器或模型)也可以是块。

命名:

块名可以由小写拉丁字母、数字和连字符组成。创建 CSS 类时,添加简短前缀以进行命名空间划分:.block。较长块名中的空格应替换为连字符。

HTML:

任何接受类名的 DOM 节点都可以是块。

✅ 正确(请这样做)

<div class="card">...</div>
<div class="button">...</div>
<div class="menu">...</div>
<div class="header">...</div>
<div class="search-form">...</div>
<div class="user-profile">...</div>
<div class="modal">...</div>
<div class="navigation">...</div>
<div class="dropdown-menu">...</div>

🚫 错误(不要这样做)

<div class="searchForm">...</div>
<div class="button_primary">...</div>
<div class="userProfile">...</div>
<div class="dropdown__menu">...</div>  
CSS:

仅使用类名选择器。不要使用标签名或 ID,也不要依赖页面上的其他区块或元素。

✅ 正确(这样做)

.card { }
.button { }
.menu { }
.header { }
.search-form { }
.user-profile { }
.modal { }
.navigation { }
.dropdown-menu { }

🚫 错误(不要这样做)

.searchForm {}
.button_primary {}
.userProfile {}
.dropdown__menu {} /* Don't use element syntax for blocks */
}

元素

区块的组成部分,不具有独立含义。任何元素在语义上都与其所属区块相关联。

命名:

元素名称可以由小写拉丁字母、数字、连字符和下划线组成。CSS 类名由区块名称、两个下划线和元素名称组成:.block__elem。较长元素名称中的空格应替换为连字符。

HTML:

区块内的任何 DOM 节点都可以是元素。在给定区块中,所有元素在语义上都是平等的。CSS 中的元素不应在其所属区块之外使用。

✅ 正确(这样做)

<div class='block'>
  <div class='block__element'>
    <div class='block2'>
      <div class='block2__element'>...</div>
    </div>
  </div>
</div>

🚫 错误(不要这样做)

<div class='block'>
  <div class='block__element'>
    <div class='element__element'>...</div> 
  </div>
</div>
CSS:

在 CSS 中,元素应嵌套在其所属区块内。结构不必与 DOM 结构一致。

✅ 正确(这样做)

/* Card block with elements */
.card { /* This is the block; elements are inside */
  .card__header { }
  .card__title { }
  .card__body { }
  .card__footer { }
  .card__image { }
}

/* Menu block with elements */
.menu {
  .menu__item { }
  .menu__link { }
  .menu__icon { }
}

/* Search form block with elements */
.search-form {
  .search-form__input { }
  .search-form__button { }
  .search-form__label { }
}

🚫 错误(不要这样做)

/* Don't create deeply nested element names */
.menu {
  .menu__item { }
  .menu__item__link { } /* Improper naming structure */
  .menu__item__link__icon { } /* Improper naming structure */
}

修饰符

区块或元素上的标记。使用它们来更改外观、行为或状态。

命名:

修饰符名称可以由小写拉丁字母、数字、连字符和下划线组成。CSS 类名由区块或元素名称加上两个连字符组成:.block--modifier 或 .block__elem--modifier,以及 .block--color-black 和 .block--color-red。复杂修饰符名称中的空格应替换为连字符。

在以下情况下,应使用修饰符,而不是创建单独的元素:

  • 更改只是简单的状态变化(例如,激活、禁用、高亮)
  • 更改只是简单的外观变化(例如,尺寸、颜色、布局)
  • 更改不会引入需要额外元素的新内容或功能

如果元素有默认状态和另一种可作为修饰符的状态,请将默认样式添加到基础元素,并在应用修饰符时使用修饰符覆盖这些样式。不要为默认状态创建专属元素,也不要在这种情况下创建两个修饰符。

🚫 错误(不要这样做)

.product-card__image {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.product-card__placeholder {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--op-color-neutral-plus-six) 0%, var(--op-color-neutral-plus-seven) 100%);
}

✅ 正确(这样做)

.product-card__image {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  
  &.product-card__image--placeholder {
    object-fit: unset;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, var(--op-color-neutral-plus-six) 0%, var(--op-color-neutral-plus-seven) 100%);
  }
}
HTML:

修饰符是添加到区块或元素 DOM 节点上的额外类名。只将修饰符类添加到其所修饰的区块或元素上,并保留原有类名。需要明确的是,修饰符类应始终与其基础区块或元素类搭配使用。

✅ 正确(这样做)

<div class="block block--modifier">...</div>
<div class="block block--size-big block--shadow-yes">...</div>

🚫 错误(不要这样做)

<div class="block--modifier utility">...</div> 
CSS:

✅ 正确(这样做)

.menu {
  .menu__item {
    &.menu__item--active { }
  }
  .menu__link { }
  .menu__icon { }
  
  &.menu--padded { }
}

🚫 错误(不要这样做)

.menu {
  .menu__item {
    .menu__item--active { } /* No ampersand */
  }
  
  .menu__link { }
  .menu-link-active { } /* Bad name structure */
  .menu__icon { }
  
  .menu__padded { } /* Improper modifier structure; should be using `&` and `--`, not `__` */
}

其他规则

  • 仅使用类名(不使用 ID)
  • 仅使用扁平类名和选择器
  • 不基于标签设置样式
  • 不基于 DOM 层级设置样式
  • 每个区块只承担一种概念职责
  • 区块可以根据需要包含其他区块
  • 元素不能脱离其所属区块
  • 多词名称使用 kebab-case:.user-profile、.dropdown-menu
  • 元素名称中使用双下划线(__)分隔区块和元素
  • 修饰符名称中使用双连字符(--)分隔区块/元素和修饰符
  • 名称应具有语义、描述性并能体现意图(而非基于外观)
  • 避免使用不被普遍理解的缩写
语法示例

假设有一个表单区块,带有修饰符 theme: "xmas" 和 simple: true,并包含 input 和 submit 元素;submit 元素还有自己的修饰符 disabled: true,用于在表单未填写完整时阻止提交:

✅ 正确(这样做)

<form class="form form--theme-xmas form--simple">
  <input class="form__input" type="text" />
  <input
    class="form__submit form__submit--disabled"
    type="submit" />
</form>
.form {
  .form__input { }
  .form__submit {
    &.form__submit--disabled { }
  }
  
  &.form--simple { }
  &.form--theme-xmas { }
}

🚫 错误(不要这样做)

<form class="form form-simple form--theme-xmas "> 
  <input class="form_input" type="text" /> 
  <input
    class="form__submit--disabled" 
    type="submit" />
</form>
.form {
  .form__input { }
  .form_submit { /* Use `__` between Block and Element */
    .form__submit--disabled { } /* Use `&` before all Modifier class names */
  }
  
  &.form-simple { }  /* Use `--` between Element and Modifier */
}

&.form--theme-xmas { } /* Must nest Elements and Modifiers within Block */

评论

支持 Markdown