도란도란 :: [CSS] 네이밍 컨벤션 BEM

프론트앤드, 특히 css 쪽에서 자주 사용하는 BEM (Block Element Modifier) 방법론에 대해서 정리하려 합니다.

 

BEM은 전체적으로 이렇게 이루어집니다.

 

  • 항상 영어 소문자만을 사용합니다. 카멜 케이스 등은 사용하지 않습니다.
  • 일반적으로 한 요소는 하이픈으로 연결합니다. (예를 들면 input-text, button-submit, modal-alert 등등.. )
  • 네이밍의 조합은 형태-의미-순서-상태 순으로 사용합니다. (예시 button-submit-03-disable)
  • 언더스코어는 파일, 폴더, 이미지 등에만 사용합니다(image_elysia_asset_01.png)
  • 숫자를 사용할 때는 확장성을 고려해 1, 2 이런 식으로 표현하지 않고 01, 02, 03… 혹은 001, 002, 003처럼 사용합니다. 앞에 0을 붙이지 않으면, 이미지 정렬 시 1 다음에 2가 오지 않고 10이 오는 등, 정렬 순서가 엉망이 될 수 있기 때문입니다.

 

BLOCK

여기서 Block은 문단 전체에 적용되는 요소, 혹은 그 요소를 담고 있는 큰 덩어리입니다.

이 Block들은 클래스의 컴포넌트를 형성하고, 항상 맨 앞에 위치합니다. 여기서 이 클래스의 이름을 정의할 때는, 해당 Block의 목적을 기술해야 하며, 이 Block 자체의 형태 등을 고려하지는 않습니다.

  • 옳은 예시

button, header, modal, textarea 등 이것이 무엇인가? 에 대해 목적을 알 수 있는 적절한 이름

<button class="button"> ... </button><header class="header"> ... </header><div class="modal"> ... </div><textarea class="textarea"> ... </textarea>
  • 틀린 예시

red-text, big-radio-button, #0000FF-awesome-thing 등 자체의 형태는 사용되지 않습니다.

<p class="red-text"> ... </p><input type="radio" class="big-radio-button"> ... </input><button class="deep-blueable-awesome-thing"> ... </button>

이 Block은 환경에 영향을 받으면 안 됩니다. 이를테면, margin을 넣거나 position으로 top, left 값을 조절하는 등 여백이나 위치를 설정하면 안 됩니다.

이를 통해, Block을 재사용하거나 위치를 변경하는 등 Block의 독립성을 보장합니다.

Block은 서로 중첩해서 사용할 수 있으며, 여러 번 중첩해서 사용할 수 있습니다.

  • 예시
<header class="header">
  <div class="logo">
    <img class="image" />
  </div>
  <textarea class="textarea"></textarea>
</header>

 

Element

Block이 포함하고 있는, Block에서 별도로 사용할 수 없는 한 Block을 이루고 있는 부분입니다.

Block이 전체라면, Element들은 조각을 일컫습니다. 해당 Element는 두 개의 underscore로 표시합니다.

.block-name__element-name { ... }

여기서 두 개로 표시하는 이유는, 기존 Block 이름 자체에 하이픈 및 언더바가 사용될 수 있으므로, 기존 네이밍과 혼동하지 않도록 두 개로 표기해서 가독성을 살리기 위함입니다.

  • 예시
<div class="qna-form">
  <p class="qna-form__text">
    ....
  </p>
<div>

Element는 서로 중첩할 수 있으며, 여러 중첩 수준을 가질 수 있습니다.

여기서 Element는 항상 다른 Element가 아니며, Block의 일부분입니다. 다른 Element의 부분으로 사용할 수 없습니다.

그리고 Block에는 Element가 없을 수도 있습니다. Block에 Element는 반드시 들어가야 하는 건 아니며 선택적으로 사용할 수 있습니다.

  • 예시
<form class="search-form">
  <div class="search-form__content">
    <input class="search-form__input">
    <button class="search-form__button">Search</button>
  </div>
</form><!-- 이렇게 다른 Element의 Element로는 사용하면 안 됩니다. -->
<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>

 

Modifier

Block 혹은 Element의 형태. 즉, 모양(color, size … ) 이나 상태 (focusing, disable,) 행동 (showing, enable) 등을 정의하며, 하이픈 두 개로 표현합니다. ( — )

Block 에 바로 붙여서 사용할 수도 있고, Block의 Element에 붙여서 길게 사용할 수도 있습니다. 여기서 중요한 건 항상 Block의 일부여야 하며, 단독으로 사용해서는 안 됩니다.

  • 예시
.block__element--modifier { ... }.block--modifier { ... }

여기서 Modifier에는 boolean 타입과 key-value 타입이 있습니다.

만약 Modifier를 boolean으로 표시한다면 기본적으로 값이 true라고 가정하며, key와 value를 표시할 때는 하이픈으로 연결해서 사용합니다.

  • 예시
<!-- 굳이 enable을 지정하진 않고, 따로 Modifier를 붙이지 않습니다 -->
<div class="modal__button--disable"> </div><!-- 키와 값을 하이픈으로 연결합니다 -->
<div class="image--theme-ocean"> </div><div class="button--color-deep-blueable"> </div>

 

BUT?

이렇게 정리했지만 사실 css에서 모든 부분에서 BEM이 사용되지는 않습니다.

BEM은 뭔가 엄청 복잡해 보이고 이상해 보이는 건 사실입니다. 하지만 그만큼 가독성이 뛰어나며, 효과적으로 대상을 지칭할 수 있게 됩니다.

하지만, 다음과 같은 상황에서는 굳이 억지로 사용할 필요는 없습니다.

  • 예시 1
p,
a,
span {
  font-family: "NotoSansKr", "Inter";
}.bold {
  font-family: "NotoSansKr-Bold", "Inter-Bold";
}

위와 같은 상황은 굳이 세분화하지 않아도 그냥 이대로 있는 거라 어떻게 할 수도 없고, 억지로 할 필요도 없습니다.

오히려 header__text — bold 이런 식으로 하나하나 잡아 늘인다면 손이 많이 가고 괜히 귀찮아지기만 하게 됩니다. 의미 없는 건 덤이지요.

  • 예제 2
.elysia-logo { ... }

그냥 로고를 넣은 클래스입니다. 만약 이걸 BEM으로 표현한다면,

.header {}
.header__logo {}

이렇게 변하게 됩니다. BEM 기법은 언제 어떤 것이 연관성 있게 묶였는가를 파악하는 것입니다.

그냥 어쩌다 보니 블록 안에 들어있다고 해서 모두 BEM 요소가 되는 것은 아닙니다. 지금 이 로고는 header에 우연히 들어와 있었을 뿐, 나중에 사이드바로 가거나 푸터로 갈 수도 있습니다. 이 요소들의 범위에는 어떤 맥락으로든 시작할 수 있어, 꼭 필요한 곳에 적용해야 합니다.

<div class="content">
    <h1 class="content__headline"> ... </h1>
</div>

여기서 우리는 저것을 그냥 .headline이라고 지을 수도 있습니다. 여기서 중요한 건 저 headline이 .content 안에 있어서 특정한 css를 유지하는지, 아니면 그냥 우연히 content 안에 들어와 있는 것인지를 꼭 확인해야 합니다. 물론 후자라면, BEM을 사용할 이유가 없습니다.

 

출처 : Elysia TechBlog

 

반응형