BEM이란?
BEM은 Block, Element, Modifier의 약자로, HTML과 CSS를 작성하는 데 사용되는 네이밍 방법론입니다.
BEM은 페이지의 컴포넌트를 작은 블록(Block)으로 나눈 다음 각 블록(Block)에 속하는 요소(Element)와 요소(Element)의 변형(Modifier)을 식별하기 위해 특별한 클래스 이름을 사용합니다.
- Block(블록): 독립적으로 존재하는 페이지 컴포넌트의 이름입니다. 블록(Block)은 기능적으로 독립적이며 다른 블록(Block)과 관련이 없습니다. 예를 들어, “header”, “menu”, “button” 등이 블록(Block)에 해당합니다.
- Element(요소): 블록(Block) 내부에 존재하며 블록(Block)의 일부를 나타냅니다. 요소(Element)는 블록(Block) 내부에서 유일한 이름을 가지며, 블록(Block)이 바뀌면 요소(Element)의 이름도 변경되어야 합니다. 예를 들어, “menu item”, “list item”, “button text” 등이 요소(Element)에 해당합니다.
- Modifier(변형): 블록(Block) 또는 요소(Element)의 상태를 변경하는 것입니다. 이러한 변형(Modifier)은 블록(Block) 또는 요소(Element)의 모양, 상태, 행동 등을 변경할 수 있습니다. 예를 들어, “disabled”, “active”, “selected” 등이 변형(Modifier)에 해당합니다.
BEM은 쉽게 이해하고 작성하기 쉽기 때문에 대규모 프로젝트에서 특히 유용합니다. 또한, BEM을 사용하면 스타일 규칙을 일관되게 유지할 수 있으며, 재사용 가능한 CSS 코드를 작성할 수 있습니다.
예를 들면 다음과 같습니다:
<div class="card card--featured">
<div class="card__header">
<h2 class="card__title">카드 제목</h2>
</div>
<div class="card__content">
<p class="card__text">샘플 텍스트가 포함된 추천 카드</p>
</div>
<div class="card__footer">
<a href="#" class="button button--primary">더보기</a>
</div>
</div>
HTML위의 HTML 코드에서 card는 블록(Block)에 해당하며, card__header, card__content, card__footer는 요소(Element)에 해당합니다. 또한, card–featured는 card 블록(Block)의 변형(Modifier)으로, featured라는 클래스 이름을 사용하여 표시됩니다.
※ BEM에서 클래스 이름을 작성할 때 하이픈(-)과 언더바(_)를 2개씩 사용하여 블록(Block), 요소(Element), 변형(Modifier)의 관계를 구분합니다. 이렇게 작성된 클래스 이름은 코드의 가독성을 높이고 유지 보수를 용이하게 만들어줍니다.
※ BEM에서 클래스 이름에 하이픈(-)과 언더바(_)를 2개씩 사용하는 이유는 블록(Block), 요소(Element), 변형(Modifier)의 관계를 명확하게 표시하기 위해서입니다.
이름이 2단어 이상으로 이루어져 있다면?
BEM에서 블록(Block), 요소(Element), 변형(Modifier) 이름에 2개 이상의 단어가 포함될 경우에는 단어 사이에 하이픈(-)을 사용하여 구분해줍니다.
예를 들어, “profile card” 블록(Block)의 경우 profile-card와 같이 작성하면 됩니다. 이렇게 하면 클래스 이름이 profile과 card로 구분될 수 있어 가독성이 높아집니다. 마찬가지로, “header menu”라는 요소(Element)의 경우 header-menu와 같이 작성할 수 있습니다.
변형(Modifier)의 경우에도 동일한 원칙이 적용됩니다. 예를 들어, “highlighted button”이라는 변형(Modifier)의 경우 button–highlighted와 같이 작성하면 됩니다.
따라서, 클래스 이름에 여러 단어가 포함된 경우에는 하이픈(-)을 사용하여 단어를 구분하고, 단어의 첫 글자는 소문자로 작성하는 것이 좋습니다. 이렇게 하면 클래스 이름이 명확하고 가독성이 좋아지며, 코드의 유지 보수가 용이해집니다.
다음은 2단어 이상으로 이루어진 요소의 예입니다:
<div class="profile-card profile-card--featured">
<div class="profile-card__header">
<h2 class="profile-card__title">프로필 카드 제목</h2>
</div>
<div class="profile-card__content">
<p class="profile-card__text">샘플 텍스트가 포함된 프로필 카드</p>
</div>
<div class="profile-card__footer">
<a href="#" class="button button--primary button--large">더보기</a>
</div>
</div>
HTMLVue나 React 같은 SPA에서는 어떻게 사용하는가?
Vue에서 BEM 방식을 사용할 때, 블록(Block)에 컴포넌트 이름을 포함시켜 작성하는 것이 일반적입니다. 이렇게 하면 컴포넌트의 스타일링이 다른 컴포넌트와 구분되어, 코드의 가독성이 좋아지고 유지보수성이 향상됩니다.
Vue에서 컴포넌트를 정의할 때는, name 속성을 사용하여 컴포넌트 이름을 설정할 수 있습니다. 이 name 속성을 이용하여 BEM 방식에서 블록(Block) 이름에 해당하는 클래스 이름을 작성할 수 있습니다.
다음은 Vue에서 컴포넌트 이름을 이용하여 BEM 방식으로 클래스 이름을 작성한 예입니다:
<template>
<div class="my-component my-component--large">
<h2 class="my-component__title">컴포넌트 제목</h2>
<p class="my-component__text">샘플 텍스트가 있는 구성 요소</p>
</div>
</template>
<script>
export default {
name: 'MyComponent'
}
</script>
<style scoped>
.my-component {
border: 1px solid #ccc;
border-radius: 4px;
padding: 16px;
margin-bottom: 16px;
}
.my-component--large {
font-size: 24px;
}
.my-component__title {
font-size: 24px;
margin: 0;
}
.my-component__text {
font-size: 16px;
margin: 0;
}
</style>
HTML컴포넌트의 이름이 매우 길다면?
BEM 방식에서 클래스 이름은 구체적이면서도 간결하고 명확해야 합니다. 클래스 이름을 구성할 때 하이픈(-)을 사용하여 단어를 구분하고, 요소(Element)와 변형(Modifier)의 경우 언더바(_)를 사용하여 구분합니다.
예를 들어 UserCustomStatistics.vue 라는 컴포넌트에서 클래스를 작성한다고 가정하였을 때 단순히 생각하면 다음과 같은 클래스 이름이 될수도 있습니다.
<div class="user-custom-statistics--card-item__title">
HTMLuser-custom-statistics–card-item__title 같은 클래스 이름을 사용하면, 하나의 클래스 이름이 너무 길어져서 가독성이 떨어질 수 있습니다. 이러한 경우에는 블록(Block)과 요소(Element), 변형(Modifier)의 구분을 더욱 세분화(user-custom-statistics와 card-item__title)하여 클래스 이름을 작성하는 것이 좋습니다.
예를 들면 다음과 같습니다:
<template>
<div class="user-custom-statistics">
<div class="user-custom-statistics__card-item">
<h3 class="card-item__title">{{ title }}</h3>
<p class="card-item__value">{{ value }}</p>
</div>
</div>
</template>
HTML위의 코드에서 user-custom-statistics__card-item 클래스 이름은 UserCustomStatistics 컴포넌트의 요소(Element)로, user-custom-statistics 블록(Block) 아래에 포함됩니다. 이렇게 하면 클래스 이름의 구분이 더욱 세분화되어, 가독성과 유지보수성이 향상됩니다.
※ 추가적인 BEM의 예 ※
Block
header, main, footer, section, form, nav, list, timeline, media …
Element
header__title, header__nav, main__title, main__posts, footer__copyright, footer__nav, section__title, section__description, form__label, form__input, nav__menu, list__item, timeline__item, media__image, media__caption …
Modifier
btn, table, form__input, form__label, and card are blocks, and btn–primary, btn–secondary, btn–disabled, table–striped, form__input–error, form__label–required, card–highlighted …