在SCSS中使用BEM命名规范

在SCSS中使用BEM(Block Element Modifier)命名规范可以显著提高代码的可读性和可维护性。 以下是详细的实现方法和最佳实践:


1. BEM核心结构

scss 复制代码
/* Block */
.block { /* 块样式 */ }

/* Element (用双下划线连接) */
.block__element { /* 元素样式 */ }

/* Modifier (用双连字符连接) */
.block--modifier { /* 修饰符样式 */ }

2. SCSS中的BEM实现方式

(1) 基础写法

scss 复制代码
// Block
.card {
  padding: 20px;

  // Element
  &__header {
    font-size: 18px;
  }

  // Modifier
  &--featured {
    border: 2px solid gold;
  }
}

编译结果:

css 复制代码
.card { padding: 20px; }
.card__header { font-size: 18px; }
.card--featured { border: 2px solid gold; }

(2) 嵌套元素的多层级

scss 复制代码
.menu {
  &__item {
    &__icon {
      /* .menu__item__icon (不推荐超过2级) */
    }
  }
}

⚠️ 建议 :避免超过2级嵌套(如.block__elem1__elem2),改用扁平化命名。

(3) 元素修饰符

scss 复制代码
.btn {
  &__icon {
    &--large { /* .btn__icon--large */ }
  }
}

3. 修饰符的独立使用

scss 复制代码
// Block + Modifier(不依赖元素)
.button {
  &--disabled { opacity: 0.5; }
}

// 元素 + Modifier
.form {
  &__input {
    &--error { border-color: red; }
  }
}

4. 状态类(结合SMACSS)

scss 复制代码
// 用 is-/has- 前缀表示动态状态
.tab {
  &.is-active { /* JavaScript触发的状态 */ }
  &.has-error { /* 错误状态 */ }
}

5. SCSS变量 + BEM

scss 复制代码
$block: 'card';
$element: '__header';
$modifier: '--featured';

.#{$block} {
  &#{#{$element}} { color: blue; }
  &#{$modifier} { background: gold; }
}

6. 媒体查询中的BEM

scss 复制代码
.card {
  @media (min-width: 768px) {
    &__title { font-size: 24px; }
  }
}

7. 实战案例

组件:带状态的卡片

scss 复制代码
.card {
  padding: 16px;
  border-radius: 8px;

  &__title {
    font-weight: bold;
    
    &--highlight { color: #ff5722; }
  }

  &__body {
    margin-top: 10px;
  }

  &--dark {
    background: #333;
    color: white;
  }

  &.is-collapsed {
    .card__body { display: none; }
  }
}

对应HTML:

html 复制代码
<div class="card card--dark is-collapsed">
  <h2 class="card__title card__title--highlight">标题</h2>
  <div class="card__body">内容</div>
</div>

8. 避免的常见错误

错误写法 问题 正确写法
.card .title 依赖DOM结构 .card__title
.card--header 修饰符误用于元素 .card__header
.card__btn--red 用颜色命名修饰符 .card__btn--warning

9. 最佳实践

  1. 命名语义化

    .search-form__input

    .left-col__textbox

  2. SCSS嵌套不超过3层

    scss 复制代码
    .block {
      &__elem1 {
        &__elem2 { /* 尽量避免 */ }
      }
    }
  3. 修饰符独立于元素

    scss 复制代码
    .block--modifier { /* 块级修饰符 */ }
    .block__elem--modifier { /* 元素修饰符 */ }
  4. 与工具类结合

    html 复制代码
    <div class="card u-mt-20 is-active">
      <!-- BEM + Utility Classes -->
    </div>

10. 扩展技巧

(1) 占位符选择器(Placeholder)

scss 复制代码
%card-base {
  border-radius: 8px;
}

.card {
  @extend %card-base;
  &--featured {
    @extend %card-base;
    border-width: 2px;
  }
}

(2) Mixin生成BEM类

scss 复制代码
@mixin element($name) {
  &__#{$name} {
    @content;
  }
}

.card {
  @include element('header') {
    font-size: 20px;
  }
}

通过SCSS的嵌套和&符号,BEM规范可以更直观地实现,同时保持CSS输出的整洁性。建议结合SMACSS的状态类和Atomic CSS的工具类,构建高可维护的前端样式体系。

相关推荐
CodeCraft Studio8 分钟前
纯前端文档编辑组件——Spire.WordJS全新发布
前端·javascript·word·office·spire.wordjs·web文档编辑·在线文档编辑器
前端一课12 分钟前
第 32 题:Vue3 Template 编译原理(Template → AST → Transform → Codegen → Render 函数)
前端·面试
前端一课15 分钟前
第 33 题:Vue3 v-model 原理(语法糖 → props + emit → modelValue → update:modelValue)
前端·面试
前端一课20 分钟前
第 25 题:说一下 Vue3 的 keep-alive 原理?缓存是怎么做的?
前端·面试
前端一课22 分钟前
第 30 题:Vue3 自定义渲染器(Custom Renderer)原理- 为什么 Vue 能渲染到 DOM / Canvas / WebGL / 三方平台
前端·面试
前端一课22 分钟前
【vue高频面试题】第 23 题:Vue3 自定义指令(directive)完整解析
前端·面试
前端一课23 分钟前
第 28 题:Vue3 的 Diff 算法核心原理(双端 Diff、PatchFlags、Block Tree、静态提升)
前端·面试
前端一课24 分钟前
【vue高频面试题】第 21 题:Vue3 中的 Slot(插槽)— 基础、原理、使用场景、面试必问点
前端·面试
前端一课25 分钟前
第 24 题:Vue3 的组件通信方式(props / emit / v-model / provide-inject / expose / eventBus
前端·面试