Post

BEM 방법론 - CSS naming convention

BEM이란?

블록 내 블록 중첩을 위한 구조로 HTML에서 수행하는 역할에 따라 CSS 클래스의 이름을 지정하는 방법이다.

Block, Element, Modifier로 구성된다.

Block

블록의 기준은 무엇인가?

독립적으로 재사용 가능한 컴포넌트 단위, html 기준으로 특정 기능을 감싼 부분 (wrapper)을 Block으로 이해할 수 있을 것 같다.

ex) nav menu, form wrap 등

Block 정의에 대한 다른 블로그 참조 : 블록에 추가하려는 이 BEM 요소를 웹 사이트의 다른 영역에서 구성 요소로 사용할 수 있습니까?, 재사용 가능한 기능적으로 독립적인 페이지 컴포넌트

Element

Block을 구성하는 단위

ex) ul이 Block이라면 li는 Element

Block 이름 앞에 __를 붙이고 Element의 이름을 작성한다. ex) .card__image

Modifier

상태나 속성 등이 다른 블록이나 Block이나 Element를 표현할 때 사용

ex) disabled, active

Block이나 Element 이름 앞에 --를 붙이고 Modifier의 이름을 작성한다. ex) .card__image--active

정리

위 BEM에 대한 설명을 조합해보면 BEM 방법론으로 클래스를 만드는 규칙은 .block__element--modifier이라고 할 수 있다.

html 작성

기본 구조

위와 같은 Block 구조는 아래와 같은 html 코드로 표현할 수 있다.

1
2
3
4
5
6
<div class="card">
  <img class="card__image" />
  <h2 class="card__title">I am a card</h2>
  <p class="card__description">I am the card paragraph</p>
  <a class="card__button">Learn more</a>
</div>

중첩

Block 안에 Block이 있는 경우 내부의 Block은 독립된 컴포넌트이면서 Element이기도 하다.

.btn이라는 Block을 구성해놨는데, 이 btn이 card라는 Block 안에서도 사용된다면 어떻게 구성해야 할까?

1
2
3
4
5
6
7
<div class="card">
  <img class="card__image" />
  <h2 class="card__title">I am a card</h2>
  <p class="card__description">I am the card paragraph</p>
  <!-- The button is now it's own block -->
  <a class="btn">Learn more</a>
</div>

위와 같이 .card__ 방식을 사용하지 않고 .btn을 사용하면 독립적인 컴포넌트를 유지하게 된다.

만약 .card 안에서의 .btn에만 css를 적용하고 싶다면 아래처럼 클래스를 중첩하여 작성하면 된다.

1
2
3
4
5
6
7
<div class="card">
  <img class="card__image" />
  <h2 class="card__title">I am a card</h2>
  <p class="card__description">I am the card paragraph</p>
  <!-- The element AND block class is applied to the button -->
  <a class="card__button btn">Learn more</a>
</div>

Element의 Element

Block 안의 Element 안에 Element가 또 있는 경우,

1
2
3
4
5
6
<form class="search-form">
  <div class="search-form__content">
    <input class="search-form__content__input" />
    <button class="search-form__content__button">Search</button>
  </div>
</form>

위처럼 .Block__Element__Element 형식으로로 작성하지 않고 .Block__Element로 작성한다.

content, input, button 모두 .search-form의 동일한 depth의 Element로 보는 것이다.

이 부분은 Element의 depth를 명확히 표현해야 할 때나 개인의 코딩 스타일에 따라 갈릴 것 같다.

1
2
3
4
5
6
<form class="search-form">
  <div class="search-form__content">
    <input class="search-form__input" />
    <button class="search-form__button">Search</button>
  </div>
</form>

modified

1
2
3
4
5
<ul class="tab">
  <li class="tab__item tab__item--focused">탭 01</li>
  <li class="tab__item">탭 02</li>
  <li class="tab__item">탭 03</li>
</ul>

css 작성

1
2
3
4
5
6
7
8
9
10
11
12
.menu {
  &__item {
    &--active {
    }
    &--disabled {
    }
  }
  &__button {
    &--focus {
    }
  }
}

참고사이트

How To Nest Blocks Within Blocks in BEM
[CSS 방법론] BEM 방식
Boost Your CSS with BEM Naming and SASS Nesting

This post is licensed under CC BY 4.0 by the author.