Work/HTML, CSS

[CSS] BEM - CSS : 코드 부분화

디쟈이너 2021. 3. 26. 19:29

✏️ BEM을 익히기 위해BEM Methology 사이트를 번역하며 학습/정리 한 내용입니다.

 

 


 

 

코드를 구조화하고 저장하기 위한 기본 원칙이 BEM-style CSS에 적용됩니다

  • 코드는 각각 부분화됩니다. 각 블록과 블록의 선택적 엘리먼트, 모디파이어 로직은 별도의 파일에 정의됩니다
  • CSS 파일은 BEM 프로젝트의 파일 시스템 구성 규칙에 따라 저장됩니다

코드를 부분화하고 파일 구조를 제어할 때의 장점은 아래와 같습니다.

  • 프로젝트 전체에서 정보 탐색을 단순화합니다
  • 컴포넌트를 재사용하거나 이동시킬 수 있습니다
  • 재정의 레벨로 사용하거나 조합해 사용할 수 있습니다
button/                      # Directory of the button
    _size
        button_size_s.css    # CSS implementation of the modifier

    button.css               # CSS implementation of the button block

프로젝트에 위와 같은 시스템으로 button 블록이 존재한다고 예상해봅시다. 이러한 분리는 내가 원하는 파일을 빠르게 찾을 수 있게 도와줍니다.

단일 책임 원칙

객체 지향 프로그래밍에서와 마찬가지로, CSS에 대한 BEM 접근 방식의 단일 책임 원칙은 모든 CSS 구현물이 각각의 구현물에 책임을 갖는것을 의미합니다.

<header class="header">
    <button class="button header__button">...</button>
</header>
.button {
    font-family: Arial, sans-serif;
    border: 1px solid black;
    background: #fff;
}

외부 여백이나 위치 지정 (button 블록에 header__button 엘리먼트의 외부 영역과 위치를 설정해보겠습니다)

Correct:

.header__button {
    margin: 30px;
    position: relative;
}

Incorrect:

.header__button {
    font-family: Arial, sans-serif;
    position: relative;
    border: 1px solid black;
    margin: 30px;
}

단일 책임을 위한 선택자 구분은 코드에 유연성을 더해줍니다.

개방/폐쇄 원칙

페이지의 HTML 엘리먼트는 모디파이어에 의해 확장되어야하지만 변경을 위해 닫혀야 합니다.

<button class="button">...</button>
<button class="button">...</button>
.button {
    font-family: Arial, sans-serif;
    text-align: center;
    font-size: 11px;
    line-height: 20px;
}

버튼의 사이즈를 바꿔야 하는 경우. 개방/폐쇄 원칙에 따라 버튼을 확장합니다.

<button class="button">...</button>
<button class="button button_size_s">...</button>
.button {
    font-family: Arial, sans-serif;
    text-align: center;
    font-size: 11px;
    line-height: 20px;
}

.button_size_s {
    font-size: 13px;
    line-height: 24px;
}

기존 버튼의 기능은 button_size_s 클래스를 통해 확장됩니다 (font-sizeline-height 속성의 재정의). 이제 페이지에는 크기가 다른 두개의 버튼이 있습니다.

개방/폐쇄원칙 위반

  • 기존 CSS 구현을 변경하는 경우버튼의 현재 CSS 구현은 폐쇄되어야합니다. 변경사항은 button 블록 전체에 적용될것이기 때문입니다.
  • .button { font-family: Arial, sans-serif; text-align: center; font-size: 13px; line-height: 24px; }
  • 맥락별로 수정이제 버튼의 디자인은 버튼 블록의 위치에 따라 달라집니다. 변경사항은 content 블록 내부의 모든 button 블록에 적용됩니다.
  • .button { font-family: Arial, sans-serif; text-align: center; font-size: 11px; line-height: 20px; } .content .button { font-size: 13px; line-height: 24px; }

DRY

DRY("Don't Repeat Yourself") 는 코드 반복을 줄이기위한 소프트웨어 개발 원칙입니다.

BEM 방법론과 관련하여 이 원칙은 각 BEM 엔티티(실체)가 시스템 내에서 모호하지 않은 단일 표현을 가져야한다는것을 의미합니다.

<button class="button">...</button>
<button class="btn">...</button>
.button {
    font-family: Arial, sans-serif;
    text-align: center;
    color: #000;
    background: #fff;
}

.btn {
    font-family: Arial, sans-serif;
    text-align: center;
    color: #000;
    background: rgba(255, 0, 0, 0.4);
}

위 예제처럼 btn 선택자는 button 블록의 기존 구현을 반복하고 있습니다. DRY 원칙을 적용하여 아래와 같이 작성할 수 있습니다.

<button class="button button_theme_islands">...</button>
<button class="button button_theme_simple">...</button>
.button {
    font-family: Arial, sans-serif;
    text-align: center;
}

.button_theme_islands {
    color: #000;
    background: #fff;
}

.button_theme_simple {
    color: #000;
    background: rgba(255, 0, 0, 0.4);
}

모디파이어룰 추가해 btn 블록을 제거했습니다.

DRY 원칙의 중요성은 버튼과 같이 기능적으로 유사한 컴포넌트들에만 적용됩니다.

 

 

위와 같이 버튼 사이에 약간의 외형적인 차이가 있습니다. DRY 원칙은 정확히 이러한 유형의 엔티티에 관한 것입니다. 이 블록들은 기능적으로 유사하지만 형식이 다릅니다.

예를 들어 아래와 같이 같은 색이나 크기를 가지고 있다고 해서 서로 다른 유형의 블록을 결합할 이유는 없습니다.

 

 

상속 대신 조합

상속은 기존 CSS 클래스를 기반으로 새 CSS 클래스를 정의하는 구조를 말합니다. 파생된 클래스는 상위 속성을 사용할 뿐 아니라 자체 속성을 추가할 수 있습니다.

새로운 CSS 구현은 기존 CSS를 조합하여 BEM에서 형성됩니다. 이를 통해 코드의 연결성이 사라지고 유연해집니다.

아래와 같은 세가지 구현물이 있다고 가정합니다.

  • button 블록의 버튼
  • menu 블록의 메뉴
  • popup 블록의 팝업

위 구현물을 가지고 드롭다운 리스트 를 구현합니다.

미리 만들어둔 구현물이 있는경우 해당 컴포넌트의 상호 작용 방식을 올바르게 설명해줘야합니다.

<div class="select">
    <button class="button select__button">
        <span class="button__text">Block</span>
    </button>
</div>

<div class="popup">
    <div class="menu">
        <div class="menu__item">Block</div>
        <div class="menu__item">Element</div>
        <div class="menu__item">Modifier</div>
    </div>
</div>
반응형