mcpField
B
bem-structure

bem-structure

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

关于 bem-structure

bem-structure 是指导 AI 按 BEM 方法编写和审查 CSS 的技能,面向维护前端样式的开发者。它强调语义化命名、明确选择器,并优先复用 RoleModel 的 Optics 组件。

主要功能

  1. 01BEM 块、元素与修饰符规范
  2. 02明确且语义化的类名
  3. 03避免标签、ID 和层级选择器
  4. 04修饰符使用显式选择器
  5. 05优先复用 Optics 组件

适用场景

  1. 01为新界面编写 BEM 样式
  2. 02重构或审查现有 CSS
  3. 03修复不符合 BEM 的类名
  4. 04判断是否应复用 Optics 组件

安装

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

$npx skills add https://github.com/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