CSS

CSS BEM 방법론, 가독성에 대하여

남희정 2023. 9. 5. 02:27

CSS 렌더링 방식과 선언 순서를 공부하고나서 코드를 보니 클래스명 정의에 대해 모호함을 느꼈다. 프로젝트에서 시멘틱 태그로 선언을 못했다. 로컬에 설치되는 거라 SEO가 필요없고, 단일페이지라 일반적인 웹구조를 갖고 있지 않아서 더욱 고민이었다. BEM을 중심으로 CSS에서 확보해야할 가독성에 대해 알아보자.


Computer Sciene에는 두 가지 어려운 문제가 있다. 캐시 무효화(cache invalidation)와 이름 붙이기
- Phil Karlton

 

CSS 방법론

소규모 사이트에서는 스타일을 구성하는 방식이 일반적으로 문제가 되지 않는다. 하지만 프로젝트가 업데이트 될수록 코드의 복잡도가 상승되면서 세 가지 측면의 효율성이 중요해진다. 코드를 작성하는 데에 걸리는 시간, 필요한 코드의 양, 브라우저에서 수행하는 로딩의 양.

CSS Cascading Style Sheets는 프로그래밍 언어가 아니라 웹 페이지를 꾸미는 서식과 관련된 코드이지만, 이또한 복잡해지면 작업량이 증가하는 건 필연적이다. 불필요한 작업을 최소화하고 작성된 코드를 쉽게 파악하고 유지보수성까지 고려할 수 있는 일관성있는 규칙이 필요했다. CSS를 통일성있게 관리하려는 여러 방법론들이 등장했다. 프로젝트의 요구 사항, 팀 선호도 및 목표에 따라 선택되는 컨벤션은 달라질 수 있다.

 

CSS Rule set과 Specificity

HTML 내부 인라인 태그로만 스타일을 지정하다가 1996년, CSS가 만들어졌다.

1) inline-style이 기록된 부분들을 하나로 묶어 별도의 스타일을 선언(Declaration)한다.
2) HTML에서 원하는 태그를 찾아서 선택(Select)하여 스타일을 적용한다.

 

CSS rule set

콘텐츠와 서식 파일이 분리된 상황에서 HTML을 최대한 건들이지 않고 CSS 내에서만 변경할 수 있는 방법, 그리고 새로운 개발자가 투입되거나 인수를 시행할 경우에도 직관적으로 어떤 부분을 나타내는지 명확하게 알 수 있는 방식을 갈구하게 된다.

하나의 콘텐츠를 여러 디자인으로 커스텀하는 방식보다는 하나의 디자인과 컴포넌트를 중심으로 서비스를 키워나가는 형식으로 발전을 하게 된다.

 

복잡한 Selector → 간단한 Selector → No Selector
Global Scope → Local Scope
HTML과 CSS의 분리 → 컴포넌트로 결합

 

기존 CSS는 대규모 애플리케이션을 고려하여 만들어진 것이 아니기 때문에 결정적으로 큰 문제 2가지가 존재했다.

 

✔️ Global Scope

✔️ Specificity

Cascading Style Sheets의 Cascading이라는 특징에 맞게 CSS의 Rule set의 적용대상에 서식이 겹칠 경우엔 어떤 서식을 더 우선으로 적용할지 규칙이 정해져있다. 작성 순서만이 아닌 CSS Rule이 기존에 가지고 있는 고유의 명시도(Specificity)에 따라 우선순위가 다르게 적용을 할 수 있도록 설계되었다.

코드 선언 순서대로 적용되지 않고, 고유한 명시도로 적용이 된다는 것은 기존 CSS를 덮어쓰기 위해 더 복잡한 Selector를 써야 했고, 복잡한 Selector를 덮어쓰기 위해 우선순위를 변경하는 !important와 같은 코드를 남발하도록 했다.

처음부터 CSS를 작성하는 컨벤션을 잘 짜면 이런 문제들을 해결할 수 있지 않을까? 하여 나온 것이 여러 방법론들이다.

 

방법론이 해결하고자 했던 것

1) 여러 명이 함께 작업을 할 때 공통적으로 사용할 수 있는 아키텍처

2) 명시도, 우선순위 관리

3) 이름을 짓는 컨벤션

 

CSS 공간을 줄이고 프로그래머 간의 협력을 조직하고, 대규모 CSS 코드베이스를 유지하는 것을 목표로 하는 방법론이 많이 있다. 이는 Twitter, Facebook, Github과 같은 대규모 프로젝트에서는 명백하지만 다른 프로젝트에서는 종종 거대한 CSS 파일 상태로 매우 빠르게 성장한다.

 

  • OOCSS — CSS "객체"로 컨테이너와 콘텐츠 분리
  • SMACSS — CSS 규칙에 대한 5가지 범주로 CSS를 작성하기 위한 스타일 가이드
  • SUITCSS — 구조화된 클래스 이름과 의미 있는 하이픈
  • Atomic — 스타일을 원자적 또는 분할할 수 없는 조각으로 분해

 

BEM .Block__Element--Modify

러시아의 웹 기업 1위 Yandex가 만든 CSS 방법론.

Selector 이름을 보고 무엇을 하는지 알 수 있어야 하고, 어디서 사용하는지 알 수 있어야 하고, Class들의 관계를 알 수 있어야 한다.

 

BEM

 

1️⃣ Block

✶ 재사용할 수 있는 기능적으로 독립적인 페이지 구성 요소.

➡️ 블록은 조상의 영향을 받아서는 안되며, 차례로 자손에게도 영향을 주어서는 안된다. 이 블록이 어디에 배치되어 있는지에 상관없이.

✶ HTML에서 블록은 class 속성으로 표시된다. (태그, id 선택자를 사용하지 않는다.)

✶ 블록끼리 서로 중첩해서 작성할 수 있다.

✶ 환경에 영향을 받지 않아야 한다. 여백이나 위치를 설정하면 안된다.

✶ `header`, `container`, `menu`, `checkbox`, `input`

 

2️⃣ Element

✶ 독립적으로 존재할 수 없는, 블록 안에서 특정 기능을 담당하는 요소

✶ 필수가 아닌 선택적으로 사용한다.

✶ `menu item`, `list item`, `checkbox caption`, `header title`

 

3️⃣ Modify

✶ 형태가 아닌 목적에 맞게 결정하기블록이나 요소 뒤에 --(하이픈 두 개)를 붙여 기존 스타일의 속성을 추가 및 변경하는 데 사용.

✶ Boolean 타입과 Key-value 타입이 있다.

Boolean : 수식어가 있으면 값이 true 라고 가정한다. (form__button — disabled)

Key-value : 키, 벨류를 하이픈으로 연결하여 표시한다. (color-red, theme-ocean)

✶ `disabled`, `highlighted`, `checked`, `fixed`, `size big`, `color yellow`

 

BEM은 웹 프로젝트를 코딩하는 방법에 대한 방법론입니다.
개발을 자동화하고 프로덕션 코드를 최적화 하는 Toolkit이며
더 빠르고 더 나은 개발을 돕는 라이브러리 입니다.
- Yandex

 

작명 규칙 Naming Convention

✶ id, tag, 자손 선택자를 사용하지 않고 오직 class 선택자만을 사용하여 작성해야한다.

➡️ 블록이 페이지 내에서 고유하다고 생각하더라도 나중에 변경될 수 있다.

✶ 형태가 아닌 목적에 맞게 결정하기

✶ 소문자, 숫자 만을 이용한다.

✶ 여러 단어의 조합은 하이픈으로 연결한다.

✶ DOM 요소와의 관계를 나타내기 위해 js-* 클래스 명을 사용

 

// Bad 💩

#header {
    height: 100px;
}

#header .nav {
    font-size: 15px;
}

#header p {
    font-size: 15px;
}
// GOOD 👽

.header {
    height: 100px;
}

.header__nav {
    font-size: 15px;
}

.header__text {
    font-size: 15px;
}

이 기본 규칙을 통해 id, 자손 선택자 사용시 생기는 CSS 우선 순위 문제를 방지할 수 있고, 태그 선택자 사용시 다른 태그에 스타일이 적용되는 문제를 방지할 수 있다.

 

장,단점

😃

종속성, 우선순위에 의한 문제가 생기지 않는다.

블록이 독립적이라 완성된 프로젝트의 블록을 다른 프로젝트의 블록으로 넣을 수 있다.

재사용성 증가로 유지 관리해야 하는 CSS 코드의 양이 줄어든다.

블록 라이브러리를 구축할 수 있다.

이해하기 쉽고 단순하지만 견고한 구조

 

😞

중첩이 길어질수록 클래스 명이 길어진다. (profile__text--point, button--state-success)

<button class="c-button c-button--primary c-button--huge is-active">Click me!</button>

수정자(Modifier) or 새로운 컴포넌트?

만약 c-card와 비슷한 c-panel 요소가 있는 경우 우리는 새롭게 컴포넌트를 만들어야 하는지, 수정자(Modifier)를 사용해야 하는지 고민할 수 있다. 이런 경우 수정자부터 시작하는 것이 좋다. 그러나 그렇게 만든 요소의 CSS를 관리하기 어려워 진다면, 이 때는 새로운 컴포넌트로 만드는 것이 좋다.

상태를 다루는 법

<!-- standalone state hook -->
<div class="c-card is-active">
    […]
</div>

<!-- or BEM modifier -->
<div class="c-card c-card--is-active">
    […]
</div>

일관성을 위해 BEM 수정자를 사용하는 것도 좋지만, 독립적인 상태 클래스의 장점은 어디에서나 사용 가능하다는 점이다. 동일한 작업을 하는 부분이 있다면, 이는 독립적으로 만들어 재사용하는 편이 좋을 것 같다.

 

도구 자체에 집중하기보다 목적성에 맞게 사용하는 현명함이 중요하다.

BEM으로 CSS를 직접 수정해보고 stateofcss에서 밝힌 CSS 프레임워크 1위 Tailwind CSS에 대해 알아보아야겠다.

 

 


Scaling Down The BEM Methodology For Small Projects

역사로 알아보는 CSS가 어려워진 이유: ①웹 문서에서 웹 애플리케이션으로

BEM

CSS Inheritance, The Cascade And Global Scope: Your New Old Worst Best Friends

[CSS] BEM 방법론, CSS 클래스 네임을 어떻게 지을까?

What you can borrow from Yandex front-end dev

[번역] 디버깅 시간을 절약할 수 있는 CSS 네이밍

BEM 10가지 일반적인 문제와 이를 피하는 방법

'CSS' 카테고리의 다른 글

명료한 CSS 선언 순서, 렌더링과 연관지어 생각해보기  (2) 2023.08.14