I am online
← Back to Articles

BEM with SCSS: Write Clean, Scalable CSS

CSSJuly 13, 2026

Introduction

As projects grow, CSS can quickly become difficult to maintain. Classes become inconsistent, selectors become overly specific, and components start affecting one another.

Combining BEM (Block Element Modifier) with SCSS provides a structured, scalable approach to writing CSS that remains easy to understand—even in large applications.

What is BEM?

BEM stands for:

  • Block – A standalone component.
  • Element – A part of a block.
  • Modifier – A variation or state of a block or element.

Syntax

block
block__element
block--modifier
block__element--modifier

Example:

<div class="card card--featured">
  <h2 class="card__title">Article Title</h2>
  <p class="card__description">
    Clean and maintainable CSS.
  </p>
</div>

Why use BEM?

BEM helps developers:

  • Improve readability
  • Reduce CSS conflicts
  • Avoid specificity issues
  • Make components reusable
  • Scale large projects
  • Simplify collaboration

Instead of writing:

.sidebar ul li a.active {
  color: blue;
}

You write:

.sidebar__link--active {
  color: blue;
}

Much cleaner.

Why combine BEM with SCSS?

SCSS allows nesting, variables, mixins, and reusable utilities.

Combined with BEM, it creates a predictable project structure.

Example:

.card {
  background: white;
  border-radius: 12px;

  &__title {
    font-size: 24px;
    font-weight: 600;
  }

  &__description {
    color: #666;
  }

  &--featured {
    border: 2px solid #2563eb;
  }
}

Compiled CSS:

.card {}

.card__title {}

.card__description {}

.card--featured {}

Project Structure

A common SCSS architecture looks like this:

scss/
│
├── abstracts/
│   ├── _variables.scss
│   ├── _mixins.scss
│   └── _functions.scss
│
├── base/
│   ├── _reset.scss
│   ├── _typography.scss
│   └── _global.scss
│
├── components/
│   ├── _button.scss
│   ├── _card.scss
│   └── _modal.scss
│
├── layout/
│   ├── _header.scss
│   ├── _footer.scss
│   └── _grid.scss
│
└── main.scss

Each component follows BEM naming.

Example: Button Component

HTML

<button class="button">
  Save
</button>

<button class="button button--primary">
  Save
</button>

<button class="button button--danger">
  Delete
</button>

SCSS

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;

  padding: 0.75rem 1.25rem;

  border: none;
  border-radius: 8px;

  cursor: pointer;

  transition: 0.2s;

  &--primary {
    background: #2563eb;
    color: white;
  }

  &--danger {
    background: #dc2626;
    color: white;
  }

  &:hover {
    opacity: 0.9;
  }
}

Example: Card Component

HTML

<article class="card card--featured">
  <img
    class="card__image"
    src="/image.jpg"
    alt="Article image"
  />

  <div class="card__content">
    <h2 class="card__title">
      Modern CSS
    </h2>

    <p class="card__description">
      Learn modern CSS architecture.
    </p>

    <a class="card__button" href="#">
      Read More
    </a>
  </div>
</article>

SCSS

.card {
  overflow: hidden;

  border-radius: 12px;

  background: white;

  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.08);

  &__image {
    width: 100%;
    display: block;
  }

  &__content {
    padding: 1.5rem;
  }

  &__title {
    margin-bottom: 0.5rem;
    font-size: 1.5rem;
  }

  &__description {
    color: #666;
  }

  &__button {
    display: inline-block;
    margin-top: 1rem;
  }

  &--featured {
    border: 2px solid #2563eb;
  }
}

Avoid Deep Nesting

Good

.card {
  &__title {}

  &__content {}

  &--featured {}
}

Avoid

.card {
  .content {
    .title {
      span {
        strong {
        }
      }
    }
  }
}

Deep nesting creates overly specific selectors and makes maintenance harder.

Organize Modifiers

Instead of:

.button-primary {}

Use:

.button {
  &--primary {}

  &--secondary {}

  &--outline {}
}

Use Variables

$primary: #2563eb;
$danger: #dc2626;
$radius: 10px;
.button {
  border-radius: $radius;

  &--primary {
    background: $primary;
  }

  &--danger {
    background: $danger;
  }
}

Reusable Mixins

@mixin flex-center {
  display: flex;
  align-items: center;
  justify-content: center;
}

Usage

.button {
  @include flex-center;
}

Common BEM Mistakes

Mixing components:

<div class="card">
  <button class="modal__button">

Correct:

<div class="card">
  <button class="card__button">

Generic names:

.title
.text
.content

Better:

.card__title
.hero__title
.modal__title

Multiple unrelated modifiers:

<div class="button red big rounded">

Better:

<div class="button button--danger button--large">

Benefits in Large Projects

Using BEM with SCSS makes it easier to:

  • Build reusable UI components
  • Maintain consistent naming
  • Work in large development teams
  • Reduce CSS bugs
  • Scale applications over time
  • Improve readability for new developers

Whether you're building a small landing page or a large React, Vue, or Next.js application, adopting a structured CSS methodology early will save time and reduce technical debt.

BEM and SCSS complement each other perfectly. BEM provides a clear naming convention, while SCSS offers powerful features like variables, mixins, and nesting to keep styles modular and maintainable.

By following these practices, you'll create components that are easier to understand, reuse, and scale—making your frontend codebase more robust as your project grows.