프론트 공부/html과 css

CSS 클래스 이름을 짓는 규칙, BEM

홍구리당당 2023. 12. 5. 13:03

0. 오늘의 배울 것

프로젝트를 짜다보면 클래스 이름을 지을 때가 가장 난감하다. 조악한 영어 실력으로 단어 더듬더듬 이어가며 클래스 이름을 지으니 자꾸 이름이 겹치고 헷갈리고 만다.

그래서 이번 포스팅에서는 네이밍 방법론 중 하나인 BEM에 대해 알아보려 한다!!

클래스든, 변수든, 함수든, 남들이 (+ 미래의 나) 알아보기 쉽게 이름을 짓는 것은 매우 중요하다! 이렇게 네이밍하는 데에 사람들이 만들어둔 규칙들이 있다. 여러가지 방법론이 있지만, 오늘은 그 중에서도 많은 곳에서 채택된 BEM 방법론에 대해 알아볼 것이다.

ㅋㅋ

1. BEM이란?

B lock
E lement
M odifier

의 줄임말로, 클래스 이름을 지을 때 block - element - modifier 순으로 이름을 짓자는 방법론이다.

참고로 BEM 방법론에서는 html의 id 속성을 사용하지 않는다. selector 설정이 헷갈리기 때문이다!! 코드가 길어질 수록, 우리가 가져온 요소를 id로 짚어둔 건지, class로 짚어둔건지 기억하기 힘들어지는데 이런 불필요한 일을 막기 위해 그냥 모두 class 속성만 써버리잔 것이다.

1. Block - block은 독립적인 의미를 가지는 추상화된 컴포넌트를 의미한다. 쉽게 말하자면 한 요소 전체를 감싸는 최상위 태그. 보통 우리는 container이라 이름 지엇을 것이다... - 클래스를 적용할 수 있는 DOM 노드라면 뭐든 블록이 될 수 있다.

  1. Element
  • element는 block의 구성 요소이다. block 내에서만 살아있는 요소이기 때문에 block에 의존적이다.
  • blcok 다음에 언더바 2 개로 element 이름을 잇는다.
  • ex) Block__element
  1. Modifier
  • block, element의 속성(상태 또는 행동)을 담당한다. 보통 생긴 게 조금 다르거나, 다르게 동작하는 블럭이나 엘리먼트를 만들 때 추가한다.
  • 클래스 이름 맨 뒤에 대시바 2개로 디자인 특성을 표시한다.
  • ex) Block__element--modifier
  • ex) Block__element--is-active

참고로 구성요소가 단순한 경우 block 다음 바로 나오는 것이 modifier일 수도 있다.

  • ex) myButton--is-active

 

2. 예시

function Card(){
    //...
    return (
        <div className="c-card">
            <img className="c-card__img" />
            <li className="c-card__item c-card__item--is-active"></li>
            <li className="c-card__item"></li>
            <li className="c-card__item"></li>
            <li className="c-card__item"></li>
        </div>
    );
}

네임 스페이스는 뭘까?

위의 예시에서 c-card 라고 클래스 이름을 지었는데, 여기서 c- 가 네임 스페이스이다.

이 클래스를 가진 요소가 어떤 요소인지를 나타내주는 게 바로 네임 스페이스이다. (사실 필자는 이거까지 쓰는 개발자는 거의 보지 못했지만... 대규모 프로젝트에선 써볼만하다.)

자주 쓰이는 네임 스페이스

    예시 설명
c- component c-card-checklist 독립적으로 재사용할 수 있는 요소인 컴포넌트의 클래스 앞에 붙이는 접두사.
l- layout l-grid-container 레이아웃 용으로 쓰이는 태그에 붙이는 접두사.
is- , has- status is-visible, has-loaded 컴포넌트가 가질 수 있는 상태.
h- helper h-show, h-hide 유틸적인 용도로 사용하는 접두사. 일반적으로 위치 지정 또는 가시성을 위한 목적으로만 사용.
js- javascript js-tab-switcher 자바스크립트에 의해 요소가 동작될 수 있음을 의미하며, 이는 스타일이 아닌 자바스크립트만을 위한 네임스페이스이다.

 

3. BEM을 왜 쓸까? (BEM의 장점)

  1. 네이밍을 이해하기 쉬워진다! 이 클래스가 어디서 중첩되는지, 무엇을 위한 것인지 알아보기 편하다.
  2. 클래스 네임만으로 마크업 구조를 파악하기 쉬워진다. 블럭와 엘리먼트로 이름짓고, 부모 태그의 클래스명까지 명시해주기 때문에 어느 집 자식 요소인지 알기 쉬워진다.

 

4. BEM의 주의점?

문제 1) BEM은 클래스 이름을 통한 모듈화를 하기 좋지만, 태그 중첩이 깊어질 수록 클래스 이름이 지나치게 길어져요!
답안 1) 클래스 네임에서 무작정 모든 부모 클래스 이름을 붙여넣지 말고, 최상위 block 이름 하나만 표현하자!!

// 이렇게 하면 너무 길어진다...
<div class="c-card">
    <div class="c-card__header">
        <h2 class="c-card__header__title">Title</h2>
    </div>

    <div class="c-card__body">
        <img class="c-card__body__img" src="some-img.png" alt="description">
        <p class="c-card__body__text">text 1</p>
        <p class="c-card__body__text">text 2 with link
            <a href="/somelink.html" class="c-card__body__text__link">link to ...</a>
        </p>
    </div>
</div>

// 대신 이렇게 바꾸자...

<div class="c-card">
    <div class="c-card__header">
        <h2 class="c-card__title">Title</h2>
    </div>

    <div class="c-card__body">
        <img class="c-card__img" src="some-img.png" alt="description">
        <p class="c-card__text">text 1</p>
        <p class="c-card__text">text 2 with link
            <a href="/somelink.html" class="c-card__link">link to ...</a>
        </p>
    </div>
</div>

 

문제 2) modifier 클래스를 덧붙일지, 새로운 컴포넌트를 만들지 고민돼요.
답안 2) 이 문제는 사실 BEM 문제라기보단 그냥 프론트 코드를 짜면서 생기는 전반적인 고민이겠지만, BEM 문서 BEM CSS의 10가지 한계점 에 나온 문제이므로 그냥 가져왔다. css만으로 관리하기 힘들다면, 당연히 새로운 컴포넌트를 만들어 써야겠지만 단순 css 문제라면 modifier을 추가한 클래스네임을 만들어보자.

 

문제 3) 상태를 어떻게 다룰까요?
답안 3) 여기서 말하는 상태란, 이벤트에 따른 요소의 스타일을 말한다! 예를 들어 navigation bar가 home page에선 position: sticky 속성을 가지지만, 다른 페이지에선 position: relative 속성을 가지게 하기 위해선 navigation bar의 클래스 네임에 isHomePage ? nav is-sticky : nav 이렇게 클래스 이름을 붙여 관리할 수 있을 것이다. 그렇지만 BEM 방법론에 따라 isHomPage ? nav nav--is-sticky : nav 이렇게 nav의 하위 클래스로 이름 지을 수도 있을 것이다.
is-sticky 클래스는 nav만의 클래스로 만들지, 아님 재사용 가능한 클래스로 만들지는 프로젝트에 달려있다. 만약 동일한 작업이 많을 거 같다면 클래스를 독립적으로 만들어 사용하자.

 

문제 4) 요소에 클래스를 추가하지 않아도 될까요?
답안 4) 아래 코드에선 예를 들어 .card{ & p{ /** ... **/ }} 이렇게 not pure한 tag로 요소 스타일링을 할 수도 있을 것이다. 다만 next js 기준 not pure tag를 쓰지 않게끔 되어있고, BEM 방법론에서도 중첩관계 표현을 위해 클래스 명을 활용하는 것을 권장하니 이왕이면 클래스 이름으로 스타일링을 하자.

//... 
return (
    <div class="card">
        <p> ... </p>
    </div>
);

 

문제 5) 자식 요소에 클래스를 한 개만 써도 될까요?
답안 5) nesting 문법을 쓰거나 자손 선택자를 통해 css를 꾸밀 수 있으니 html 에서 className을 하나씩만 줘도 상관은 없다. 그렇지만 중첩 관계를 잘 표현하기 위해 상위 클래스까지 다 써주는 것을 권장한다.

// 안 좋은 예시.
<button class="btn--secondary">my button</button>

// 이렇게 써야 좋다!!
<button class="btn btn--secondary">my button</button>

'프론트 공부 > html과 css' 카테고리의 다른 글

CSS의 레이아웃, Grid  (0) 2023.10.16
CSS의 레이아웃, Flex Box  (1) 2023.10.16
html의 문법과 시맨틱 태그  (0) 2023.10.16
CSS의 포지션 속성  (0) 2023.10.16