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.