bem-structure
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseOverview
概述
This skill guides AI in writing CSS using the BEM (Block Element Modifier) methodology for creating maintainable, scalable, and reusable stylesheets with clear naming conventions and component structure, while exercising judgment about scope, risk, and architectural impact. It also should use BEM in conjunction with Optics, our RoleModel design system, so that it's not recreating things that already exist. If there is already an Optics component that fits the need, it should be used and/or overridden as necessary instead of creating a new BEM block.
The agent should prioritize clarity, predictability, and minimal unintended side effects.
Keywords: CSS review, BEM structure, BEM methodology, CSS best practices, Refactor CSS, Review CSS, Fix my CSS, Fix my BEM, BEM-ify my CSS
此技能指导AI使用BEM(Block Element Modifier)方法论编写CSS,以创建具备清晰命名约定和组件结构的可维护、可扩展且可复用的样式表,同时对范围、风险和架构影响做出合理判断。此外,还应结合我们RoleModel设计系统中的Optics进行使用,避免重复开发已有的内容。如果已有符合需求的Optics组件,应优先使用并根据需要进行覆盖,而非创建新的BEM块。
智能体应优先保证代码的清晰性、可预测性,并尽量减少意外副作用。
关键词:CSS审查、BEM结构、BEM方法论、CSS最佳实践、重构CSS、审查CSS、修复我的CSS、修复我的BEM、将我的CSS改造为BEM规范
What is BEM?
什么是BEM?
BEM stands for Block Element Modifier - a methodology that helps you create reusable components and code sharing in front-end development.
| Pattern | Syntax | Example |
|---|---|---|
| Block | | |
| Element | | |
| Block Modifier | | |
| Element Modifier | | |
| Multi-word names | | |
BEM代表Block Element Modifier(块-元素-修饰符),是一种帮助你在前端开发中创建可复用组件和实现代码共享的方法论。
| 模式 | 语法 | 示例 |
|---|---|---|
| 块 | | |
| 元素 | | |
| 块修饰符 | | |
| 元素修饰符 | | |
| 多词名称 | | |
Naming Convention
命名约定
- As with any other development, intention revealing names are important.
- In BEM, the intention we are trying to convey in naming is not based on the styling that gets applied or its appearance, but rather its purpose in the interface.
- Specific styling typically makes for bad naming with the exception of modifiers (small, large, padded, etc.).
- Naming after the specific workflow can, in certain cases, be acceptable. (calendar with days).
- Naming after the shared type of workflow tends to be the sweet spot. (form, table, card, button).
- Naming after the broader UI abstraction is not always necessary, but can be used for abstract cases with no context required (primary, large, etc).
- Be specific enough to convey purpose clearly, but general enough to allow for reuse if applicable. Reuse won't always be possible or desirable, so don't push it too far.
- Try to use names that are explicit and not open to interpretation. This will need to be considered most often for modifiers.
- Use flat BEM classes with explicit usage for modifiers.
& - DOM structure does not need to follow CSS class structure.
If you're not able to follow these guidelines due to project constraints or other reasons, please document the reasons for the deviation in the chat output.
- 与任何开发工作一样,表意明确的名称至关重要。
- 在BEM中,命名要传达的意图并非基于应用的样式或外观,而是其在界面中的用途。
- 除修饰符(如small、large、padded等)外,基于具体样式的命名通常不可取。
- 在某些情况下,可以根据特定工作流命名(如带日期的日历)。
- 基于通用工作流类型命名是最佳选择(如表单、表格、卡片、按钮)。
- 基于更宽泛的UI抽象命名并非总是必要,但可用于无需上下文的抽象场景(如primary、large等)。
- 名称应足够具体以清晰传达用途,但也要具备一定通用性以支持复用(若适用)。复用并非总是可行或必要,无需过度强求。
- 尽量使用表意明确、无歧义的名称,这一点在修饰符命名中尤为重要。
- 使用扁平化BEM类,并在修饰符中显式使用。
& - DOM结构无需与CSS类结构保持一致。
若因项目限制或其他原因无法遵循这些准则,请在聊天输出中记录偏差原因。
Basic Syntax
基础语法
✅ GOOD (Do this)
css
.block {
.block__element {
&.block__element--modifier { }
}
&.block--modifier { }
}html
<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>🚫 BAD (Don't do this)
css
.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 */
}html
<div class="block">...</div>
<div class="block__element">...</div> <!-- Incorrect; Element has become the Block -->
<div class="block__element--modifier">...</div> <!-- Incorrect; Modifier must be accompanied by a corresponding Element -->
</div>
<div class="block__element"> <!-- Incorrect; Element must be accompanied by a corresponding Block -->
<div class="block__element">...</div> <!-- Incorrect; Do not nest an element within itself -->
</div>✅ 正确示例(推荐做法)
css
.block {
.block__element {
&.block__element--modifier { }
}
&.block--modifier { }
}html
<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>🚫 错误示例(避免做法)
css
.block {
.block--modifier { } /* 所有修饰符类名前需使用`&` */
}
.block_element { /* 块与元素之间需使用`__`,并将元素嵌套在块内 */
&.block__element-modifier { } /* 修饰符与其所属元素之间需使用`--` */
}html
<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>Rule Summary
规则总结
- All class names MUST be fully explicit BEM. Nesting is allowed for organization, but selectors should not rely on tag names or IDs.
- may be used only as a textual reference to the full selector
& - MUST NOT be used to construct class names (
&,&--)&__ - Nesting is for organization only; explicit BEM class names are required. Nested selectors may be used to scope elements under their block if desired.
- may be used to co-locate modifiers with their Block or Element while keeping selectors explicit.
&
✅ GOOD (Do this)
css
.card {
&.card--featured {}
&.card--compact {}
&.card--featured {
&.card--compact {}
}
}🚫 BAD (Don't do this)
css
.card {
&--featured {}
&__title {}
&__title--large {}
}- 所有类名必须是完全符合BEM规范的显式命名。允许通过嵌套进行代码组织,但选择器不应依赖标签名或ID。
- 仅可作为完整选择器的文本引用
& - 禁止使用构造类名(如
&、&--)&__ - 嵌套仅用于代码组织;必须使用显式BEM类名。若需要,可使用嵌套选择器将元素限定在其所属块的作用域内。
- 可使用将修饰符与其所属块或元素放在同一位置,同时保持选择器的显式性。
&
✅ 正确示例(推荐做法)
css
.card {
&.card--featured {}
&.card--compact {}
&.card--featured {
&.card--compact {}
}
}🚫 错误示例(避免做法)
css
.card {
&--featured {}
&__title {}
&__title--large {}
}Block
块
Encapsulates a standalone entity that is meaningful on its own. While blocks can be nested and interact with each other, semantically they remain equal; there is no precedence or hierarchy. Holistic entities without DOM representation (such as controllers or models) can be blocks as well.
块是一个独立的、具备完整意义的实体。块可以嵌套并相互交互,但在语义上它们是平等的,不存在优先级或层级关系。没有DOM表示的整体实体(如控制器或模型)也可作为块。
Naming:
命名:
Block names may consist of lowercase Latin letters, digits, and dashes. To form a CSS class, add a short prefix for namespacing: . Spaces in long block names are replaced by dash.
.block块名可由小写拉丁字母、数字和连字符组成。为形成CSS类,需添加一个短前缀作为命名空间:。长块名中的空格需替换为连字符。
.blockHTML:
HTML:
Any DOM node can be a block if it accepts a class name.
✅ GOOD (Do this)
html
<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>🚫 BAD (Don't do this)
html
<div class="searchForm">...</div>
<div class="button_primary">...</div>
<div class="userProfile">...</div>
<div class="dropdown__menu">...</div> <!-- Don't use element syntax for blocks -->任何可添加类名的DOM节点都可作为块。
✅ 正确示例(推荐做法)
html
<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>🚫 错误示例(避免做法)
html
<div class="searchForm">...</div>
<div class="button_primary">...</div>
<div class="userProfile">...</div>
<div class="dropdown__menu">...</div> <!-- 请勿对块使用元素语法 -->CSS:
CSS:
Use class name selector only. No tag name or IDs. No dependency on other blocks/elements on a page.
✅ GOOD (Do this)
css
.card { }
.button { }
.menu { }
.header { }
.search-form { }
.user-profile { }
.modal { }
.navigation { }
.dropdown-menu { }🚫 BAD (Don't do this)
css
.searchForm {}
.button_primary {}
.userProfile {}
.dropdown__menu {} /* Don't use element syntax for blocks */
}仅使用类名选择器。禁止使用标签名或ID。不依赖页面上的其他块/元素。
✅ 正确示例(推荐做法)
css
.card { }
.button { }
.menu { }
.header { }
.search-form { }
.user-profile { }
.modal { }
.navigation { }
.dropdown-menu { }🚫 错误示例(避免做法)
css
.searchForm {}
.button_primary {}
.userProfile {}
.dropdown__menu {} /* 请勿对块使用元素语法 */
}Element
元素
Parts of a block and have no standalone meaning. Any element is semantically tied to its block.
元素是块的组成部分,自身不具备独立意义。任何元素在语义上都与其所属块紧密关联。
Naming:
命名:
Element names may consist of lowercase Latin letters, digits, dashes and underscores. CSS class is formed as block name plus two underscores plus element name: . Spaces in long element names are replaced by dash.
.block__elem元素名可由小写拉丁字母、数字、连字符和下划线组成。CSS类的格式为:块名 + 双下划线 + 元素名:。长元素名中的空格需替换为连字符。
.block__elemHTML:
HTML:
Any DOM node within a block can be an element. Within a given block, all elements are semantically equal. An element should not be used outside of the block that contains it in the CSS.
✅ GOOD (Do this)
html
<div class='block'>
<div class='block__element'>
<div class='block2'>
<div class='block2__element'>...</div>
</div>
</div>
</div>🚫 BAD (Don't do this)
html
<div class='block'>
<div class='block__element'>
<div class='element__element'>...</div> <!-- Incorrect; element has become the block -->
</div>
</div>块内的任何DOM节点都可作为元素。在一个块中,所有元素在语义上是平等的。在CSS中,元素不应脱离其所属块使用。
✅ 正确示例(推荐做法)
html
<div class='block'>
<div class='block__element'>
<div class='block2'>
<div class='block2__element'>...</div>
</div>
</div>
</div>🚫 错误示例(避免做法)
html
<div class='block'>
<div class='block__element'>
<div class='element__element'>...</div> <!-- 错误;元素不能作为块使用 -->
</div>
</div>CSS:
CSS:
In the CSS, elements should be nested inside of the block they belong to. The structure doesn't need to match the DOM structure.
✅ GOOD (Do this)
css
/* 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 { }
}🚫 BAD (Don't do this)
css
/* Don't create deeply nested element names */
.menu {
.menu__item { }
.menu__item__link { } /* Improper naming structure */
.menu__item__link__icon { } /* Improper naming structure */
}在CSS中,元素应嵌套在其所属块的选择器内。CSS结构无需与DOM结构匹配。
✅ 正确示例(推荐做法)
css
/* 包含元素的卡片块 */
.card { /* 这是块;元素嵌套在其中 */
.card__header { }
.card__title { }
.card__body { }
.card__footer { }
.card__image { }
}
/* 包含元素的菜单块 */
.menu {
.menu__item { }
.menu__link { }
.menu__icon { }
}
/* 包含元素的搜索表单块 */
.search-form {
.search-form__input { }
.search-form__button { }
.search-form__label { }
}🚫 错误示例(避免做法)
css
/* 请勿创建深度嵌套的元素名称 */
.menu {
.menu__item { }
.menu__item__link { } /* 命名结构不正确 */
.menu__item__link__icon { } /* 命名结构不正确 */
}Modifier
修饰符
Flags on blocks or elements. Use them to change appearance, behavior or state.
修饰符是块或元素的标记,用于改变其外观、行为或状态。
Naming:
命名:
Modifier names may consist of lowercase Latin letters, digits, dashes and underscores. CSS class is formed as block’s or element’s name plus two dashes: or and with . Spaces in complicated modifiers are replaced by dash.
.block--modifier.block__elem--modifier.block--color-black.block--color-redModifiers should be used over creating separate elements when:
- The change is a simple state change (e.g., active, disabled, highlighted)
- The change is a simple appearance change (e.g., size, color, layout)
- The change does not introduce new content or functionality that would require additional elements
If you have a default state for an element and another that would be a modifier, add the default styles to the base element and use the modifier to override those styles when the modifier is applied. Don't create an exclusive element for the default and also don't create two modifiers for this case.
🚫 BAD (Don't do this)
css
.music-entry__artwork-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
.music-entry__artwork-placeholder {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, var(--color-tan) 0%, var(--color-beige) 100%);
}✅ GOOD (Do this)
css
.music-entry__artwork-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
&.music-entry__artwork-image--placeholder {
object-fit: unset;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, var(--color-tan) 0%, var(--color-beige) 100%);
}
}修饰符名可由小写拉丁字母、数字、连字符和下划线组成。CSS类的格式为:块/元素名 + 双连字符: 或 ,以及 、这类格式。复杂修饰符中的空格需替换为连字符。
.block--modifier.block__elem--modifier.block--color-black.block--color-red当满足以下条件时,应使用修饰符而非创建新元素:
- 仅为简单状态变更(如active、disabled、highlighted)
- 仅为简单外观变更(如尺寸、颜色、布局)
- 变更不会引入需要额外元素支持的新内容或功能
若元素有默认状态和一个修饰符状态,应将默认样式添加到基础元素中,使用修饰符来覆盖默认样式。请勿为默认状态创建单独的元素,也不要为此创建两个修饰符。
🚫 错误示例(避免做法)
css
.music-entry__artwork-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
.music-entry__artwork-placeholder {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, var(--color-tan) 0%, var(--color-beige) 100%);
}✅ 正确示例(推荐做法)
css
.music-entry__artwork-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
&.music-entry__artwork-image--placeholder {
object-fit: unset;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, var(--color-tan) 0%, var(--color-beige) 100%);
}
}HTML:
HTML:
Modifier is an extra class name which you add to a block/element DOM node. Add modifier classes only to blocks/elements they modify, and keep the original class. To be clear, a modifier class should always be used in conjunction with its base block/element class.
✅ GOOD (Do this)
html
<div class="block block--modifier">...</div>
<div class="block block--size-big block--shadow-yes">...</div>🚫 BAD (Don't do this)
html
<div class="block--modifier utility">...</div> <!-- Missing base block class and using utility class -->修饰符是添加到块/元素DOM节点上的额外类名。仅可将修饰符类添加到其对应的块/元素上,并保留原始类。需要明确的是,修饰符类应始终与其基础块/元素类一起使用。
✅ 正确示例(推荐做法)
html
<div class="block block--modifier">...</div>
<div class="block block--size-big block--shadow-yes">...</div>🚫 错误示例(避免做法)
html
<div class="block--modifier utility">...</div> <!-- 缺少基础块类,且使用了工具类 -->CSS:
CSS:
✅ GOOD (Do this)
css
.menu {
.menu__item {
&.menu__item--active { }
}
.menu__link { }
.menu__icon { }
&.menu--padded { }
}🚫 BAD (Don't do this)
css
.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 `__` */
}✅ 正确示例(推荐做法)
css
.menu {
.menu__item {
&.menu__item--active { }
}
.menu__link { }
.menu__icon { }
&.menu--padded { }
}🚫 错误示例(避免做法)
css
.menu {
.menu__item {
.menu__item--active { } /* 未使用& */
}
.menu__link { }
.menu-link-active { } /* 命名结构错误 */
.menu__icon { }
.menu__padded { } /* 修饰符结构不正确;应使用`&`和`--`,而非`__` */
}Miscellaneous Rules
其他规则
- Classes only (no IDs)
- Flat classes and selectors only
- No tag-based styling
- No styling based on DOM hierarchy
- One conceptual responsibility per Block
- Blocks can contain blocks if needed
- Elements do not exist outside their Block
- Use kebab-case for multi-word names: ,
.user-profile.dropdown-menu - Use double underscore () to separate block from element in element names
__ - Use double dash () to separate block/element from modifier in modifier names
-- - Keep names semantic, descriptive, and intention-revealing (not appearance-based)
- Avoid abbreviations that aren't universally understood
- 仅使用类选择器(禁止使用ID)
- 仅使用扁平化类和选择器
- 禁止基于标签进行样式设置
- 禁止基于DOM层级进行样式设置
- 每个块仅承担一个概念性职责
- 若需要,块可以包含其他块
- 元素不能脱离其所属块独立存在
- 多词名称使用短横线命名法(kebab-case):、
.user-profile.dropdown-menu - 元素名称中使用**双下划线()**分隔块与元素
__ - 修饰符名称中使用**双连字符()**分隔块/元素与修饰符
-- - 名称应具备语义化、描述性,且表意明确(避免基于外观命名)
- 避免使用非通用的缩写
Syntax Example
语法示例
Suppose you have block form with modifiers and and with elements and , and element with its own modifier for not submitting form while it is not filled:
theme: "xmas"simple: trueinputsubmitsubmitdisabled: true✅ GOOD (Do this)
html
<form class="form form--theme-xmas form--simple">
<input class="form__input" type="text" />
<input
class="form__submit form__submit--disabled"
type="submit" />
</form>css
.form {
.form__input { }
.form__submit {
&.form__submit--disabled { }
}
&.form--simple { }
&.form--theme-xmas { }
}🚫 BAD (Don't do this)
html
<form class="form form-simple form--theme-xmas "> <!-- Incorrect; cannot have multiple blocks -->
<input class="form_input" type="text" /> <!-- Incorrect; must use `__` between Block and Element -->
<input
class="form__submit--disabled" <!-- Incorrect; missing Element -->
type="submit" />
</form>css
.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 */假设你有一个表单块,带有修饰符和,以及元素和,其中元素带有自己的修饰符(用于在表单未填写完成时禁止提交):
theme: "xmas"simple: trueinputsubmitsubmitdisabled: true✅ 正确示例(推荐做法)
html
<form class="form form--theme-xmas form--simple">
<input class="form__input" type="text" />
<input
class="form__submit form__submit--disabled"
type="submit" />
</form>css
.form {
.form__input { }
.form__submit {
&.form__submit--disabled { }
}
&.form--simple { }
&.form--theme-xmas { }
}🚫 错误示例(避免做法)
html
<form class="form form-simple form--theme-xmas "> <!-- 错误;不能使用多个块类 -->
<input class="form_input" type="text" /> <!-- 错误;块与元素之间必须使用`__` -->
<input
class="form__submit--disabled" <!-- 错误;缺少元素类 -->
type="submit" />
</form>css
.form {
.form__input { }
.form_submit { /* 块与元素之间需使用`__` */
.form__submit--disabled { } /* 所有修饰符类名前需使用`&` */
}
&.form-simple { } /* 元素与修饰符之间需使用`--` */
}
&.form--theme-xmas { } /* 元素和修饰符必须嵌套在块内 */
```",