CSS 방법론(SMACSS,BEM,OOCSS)
- 7 minscss의 활용도가 높아지고 대규모 프로젝트가 많아짐에 따라 코드베이스를 유지보수하기가 어려워졌고 이를 해결하기 위해 css를 작성하는 방법에 대한 여러 가이드라인을 문서화하기 시작했습니다. css방법론에는 대표적으로 SMACSS,BEM,OOCSS가있고 이 세 방법론 모두 같은 지향점을 갖고있습니다.
- 코드의 재 사용성 높이기
- 쉽게 유지보수 할 수 있도록 하기
- 확장 가능하게 하기
- 클래스명으로 무슨 의미인지 예측 가능하도록 하기
SMACSS (Scalable and Modular Architecture for CSS)
smacss는 css를 모듈화하고 확장 가능하게 만드는것을 목표로 하며 스타일을 다섯가지로 분류하고, 각 유형에 맞는 선택자(selector)
와 작명법(naming convention)
,코딩 기법
을 제시합니다.
- 기초(Base)
- 레이아웃(Layout)
- 모듈(Module)
- 상태(States)
- 테마(Theme)
기초 - Base
- 각 브라우저의 스타일을 초기화 시키는 목적으로 사용
html, body{height:100%;}
body{font-family:나눔고딕, 돋움, arial, sans-serif;font-size:12px;line-height:19px;color:#6f6f6f;}
body, div, h1, h2, h3, h4, h5, h6, ul, ol, li, dl, dt, dd, p,
form, fieldset, input, table, tr, th, td{margin:0;padding:0}
h1, h2, h3, h4, h5, h6{font-weight:normal;font-size:100%}
ul, ol, li{list-style:none}
fieldset, img{border:none}
레이아웃 - Layout
- 주요 요소(id), 하위 요소(class)로 구분하고 접두사를 사용
- 주요 컴포넌트는 id 셀렉터, 하위 컴포넌트 class 셀렉터로 스타일 작성
- 클래스명은 접두사로 l-, layout- 명시 요구
#content {width:80%;float:left}
#aside {width:20%}
.l-fixed #content {...}
.l-fixed #aside {...}
모듈 - Module
- 페이지내에서 재사용 가능한 구성요소(네비게이션 바,배너,위젯)
<div class="box">
<span class="box-name"> ... </span>
<span class="box-items"> ... </span>
</div
.box { ... }
.box-name { ... }
.box-items { ... }
상태 - State
- 요소의 상태 변화를 표현하고 접두사 사용(Hidden, expend, active, hover 등)
<div class="btn_area">
<a href="#" class="btn btn_good is-active">좋아요</a>
<a href="#" class="btn btn_bad">나빠요</a>
</div>
테마 - Theme
- 사용자가 테마를 선택할 수 있는 경우 사용
- 색상이나 이미지를 불변하는 스타일과 분리, 기존 스타일을 재 선언하여 사용할 수 있다.
// base.css
.header {
background-color: green;
}
// theme.css
.header {
background-color: red;
}
BEM (Block Element Modifier)
클래스를 구조화하여 이름을 지정, 코드의 유연성과 유지 관리 가능성을 높이는 방법이며 블록(block)
, 요소(element)
, 상태(modifier)
로 구분하여 클래스 작성한다. 클래스명을 작명 할 때 에는 Block__Element–Modifier 로 작명한다.
Block
- 재사용 가능한 영역(header,nav,article,footer,navigation.logo…)
- 문단 전체에 적용된 element 또는 element를 담고 있는 컨테이너를 말한다.
- 태그,id는 사용할수 없다.
.header { ... }
.block { ... }
.footer { ... }
Element
- 블록내의 구성요소
- 두개의 underscores( _ )로 표기
.header { ... }
.header__link { ... }
.header__tap { ... }
.header__tap__item { ... }
- 다른 block/element과 의존성을 가지면 안된다.
/* Good */
.block__elem {
color : yellow;
}
/* Bad */
.block .block__elem{
color : yellow;
}
div .block__elem{
color : yellow;
}
Modifier
- 요소의 상태를 표현
- 두개의 hyphen(-)로 표기
.header--hide { ... }
.header__tap--big { ... }
.header__tap--big { ... }
BEM을 활용한 마크업
<header class="layout-header">
<div class="layout-header__wrapper">
<h1 class="layout-header__logo">
<a href=""><img src="" alt=""></a>
</h1>
<nav class="layout-gnb">
<h2 class="__accessibility">전체 메뉴</h2>
<ul class="layout-gnb-menu">
<li class="layout-gnb-menu__item">...</li>
<li class="layout-gnb-menu__item">...</li>
<li class="layout-gnb-menu__item">...</li>
</ul>
</nav>
</div>
</header>
<main id="container" class="layout-container">
<div class="main-container">
<section class="main-visual" id="main-visual">
<h2 class="__accessibility">메인 비주얼</h2>
<ul class="main-visual__wrapper">
<li class="main-visual__item">
<figcaption class="main-visual__item-figure">
<h3 class="main-visual-item-main__sub">...</h3>
<h2 class="main-vusual-item-main__title">...</h2>
</figcaption>
<img src="" alt="" class="main-visual__image">
</li>
</ul>
<button type="button"
class="main-visual__button main-visual__button--prev">이전</button>
<button type="button"
class="main-visual__button main-visual__button--next">다음</button>
</section>
</div>
</main>
.main-visual {
margin: 0 auto;
position: relative;
width: 100%;
height: 950px;
overflow: hidden;
min-width: 1140px;
max-width: 1920px;
}
.main-visual__wrapper {
position: relative;
width: 100%;
height: 100%;
z-index: 1;
}
.main-visual__item-figure {
width:1140px;
margin:0 auto;
position:relative;
display:inline-block;
z-index:1;
padding-top:281px;
height:100%;
}
BEM의 가장 큰 장점은 클래스명의 고유화로 직관적이며 CSS 및 UI가 구조화 된 장점을 누릴 수 있다.
OOCSS (Object Oriented)
CSS를 모듈 방식으로 코딩하여 중복을 최소화
하는 기법
- 구조와 외형의 분리 (Separate structure and skin)
- 컨테이너와 내용 분리 (Separate container and content)
구조와 외형의 분리
- 구조 : width, height, border, padding, margin
- 외형 : color, border-color, font-color, background-color
// 기존 방식
<a class=”facebook_btn”>Facebook</a>
<a class=”twitter_btn”>Twitter</a>
// OOCSS 적용
<a href="#" class="btn bluebg">장바구니</a>
<a href="#" class="btn redbg">바로구매</a>
.btn {공통 버튼 스타일 정의}
컨테이너와 내용 분리
- 위치에 의존적인 스타일을 정의하지 않는다.
- 어떤 태그라도 동일한 외형 제공
<div class="header common-width">Header</div>
<div class="footer common-width">Footer</div>
.header{ ... }
.footer{ ... }
.common-width{ ... }
<h3 class="subtitle"> H3 subtitle </h3>
<span class="subtitle"> span subtitle </span>
.subtitle { ... }
OOCSS는 마크업에 클래스를 추가하기때문에 HTML이 오히려 유지보수가 어렵다는 의견이 있고, 가독성이 떨어진다. 그러나 CSS코드가 재사용되면서 코드의 길이가 줄어들고 파일크기가 작아져 속도를 향상시킬수 있다.
결론
각각의 방법론에는 장/단점이 존재하기 때문에 자신에게(팀원 및 프로젝트별로) 최적의 방법론을 사용하는것이 중요하다. 분명한 점은 다른 개발자들이 나의 코드를 직관적으로 이해하고 많은 고민할 필요 없이 코드를 수정하여 공헌할 수 있게 하기 위해서는 잘 정의된 css가 중요하다.
참고
CSS 방법론 — BEM (Block Element Modifier) CSS방법론 SMACSS, BEM, OOCSSWIT - NTS UIT Blog