一键导入
pleasant-bem-css
Pleasant BEM Syntax and methodology. Read it each time you write CSS class names.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Pleasant BEM Syntax and methodology. Read it each time you write CSS class names.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
Discipline for administering a server or workstation through a git repo that documents its config so it can be rebuilt from scratch.
Guidelines for working on a ParoiCMS website directory. Use when developing or debugging website themes, templates, and configuration.
| name | pleasant-bem-css |
| description | Pleasant BEM Syntax and methodology. Read it each time you write CSS class names. |
| license | CC0 1.0 |
| metadata | {"author":"Paleo","version":"0.1.0","repository":"https://github.com/paleo/skills"} |
This document explains how to properly use BEM (Block-Element-Modifier) methodology in the codebase.
We don't use the classic BEM syntax. We use Pleasant BEM.
Syntax:
.BlockName.BlockName.modifierName.BlockName-elementName.BlockName-elementName.modifierNameRegular modifiers change the appearance or state of a specific block or element. They are the most frequently used BEM feature:
<!-- Block modifier -->
<button className="Button.primary">Save</button>
<button className="Button.secondary">Cancel</button>
<!-- Element modifier -->
<div className="Card">
<h2 className="Card-title.large">Title</h2>
</div>
.Button {
padding: 8px 16px;
border: 1px solid #ccc;
}
.Button.primary {
background: blue;
color: white;
}
.Button.secondary {
opacity: 0.5;
cursor: not-allowed;
}
.Card-title {
font-size: 16px;
}
.Card-title.large {
font-size: 24px;
}
Use regular modifiers for:
.Button.primary, .Alert.warning).Input.focused, .Modal.open).Text.small, .Icon.large)The Pleasant BEM syntax includes three extensions to standard BEM conventions. These are advanced features used only in specific situations:
Use sparingly. Prefix with an underscore a CSS class that can affect multiple unrelated blocks across the application:
._mobile .PageTitle {
/* something specific for mobile devices */
}
._mobile .Post-h1 {
/* something specific too */
}
Global modifiers are only needed for:
.\_mobile, .\_print).\_dark-mode)Note: Most component variations should use regular modifiers, not global ones.
Elements can be styled using child selectors and sibling selectors within their block:
.TitledList-ul > li {
background-color: #ccc;
}
Note: This ties some CSS classes to HTML tags, but preserves scalability and the ability to nest sub-blocks.
Global modifiers can be used for styling semantic elements using cascading and inheritance. It's also fine to use "pseudo BEM blocks" (like .Text) that act like global modifiers but with block characteristics for formatted content:
._text,
.Text {
hyphens: auto;
overflow-wrap: break-word;
em, i {
font-style: italic;
}
strong, b {
font-weight: bold;
}
p, ul, ol {
margin-bottom: .65em;
}
img.left {
float: left;
}
img.right {
float: right;
}
}
.Text {
&::after { /* because of the floated images */
clear: both;
content: "";
display: block;
}
}
Important: Do not use any styles that apply to the container box (background, border, display, flex, grid, margin, padding, position, etc.) on the global modifier itself. Instead, use in association with other CSS classes:
<article className="Post">
<h1 className="Post-h1 _text">Here a <em>formatted title</em></h1>
<div className="Post-body Text">
<p>Some <strong>formatted text</strong>.</p>
</div>
</article>
A BEM element (.Block-element) must always be a descendant of its block (.Block). Using an element class without its parent block violates encapsulation and breaks the methodology.
// ❌ BAD: Element without its block
<>
<span className="PaField-label">Label</span>
</>
// ✅ GOOD: Elements inside their block
<label className="PaField">
<span className="PaField-label">Label</span>
</label>
Blocks can be composed by adding multiple block classes to an element when the element semantically belongs to both:
// ✅ GOOD: Element belongs to both blocks
<label className="PaSelectField PaField">...</label>
This is valid because:
<label> IS a select wrapper (PaSelectField)<label> IS a form field (PaField)Always use PaField block for form field layouts:
<label className="PaField">
<span className="PaField-label">{t("common.title")}</span>
...input element...
</label>
<div className="PaMb2">...</div>