OOCSS(Object Oriented CSS)는 CSS를 모듈 방식으로 코딩하여 중복을 최소화하는 기법이다.
OOCSS는 두가지 원칙이 있는데 이 두가지 원칙을 지키며 개발을 해야한다.
- 구조와 외형의 분리 (Separate structure and skin)
- 컨테이너와 내용의 분리 (Separate container and content)
구조와 외형이 어떤 것을 의미할까? 구조(Structure)는 width
, height
, padding
, margin
, border
같은 것들이다. 외형(Skin)은 color
, border-color
, font-color
, background-color
같이 구조의 변화 없이 적용할 수 있는 속성들이다.
CSS
/*structure*/
.box{
width: 200px;
height: 50px;
padding: 10px;
}
.button{
width: 400px;
overflow: hidden;
border: solid 1px #ccc;
}
/*skin*/
.common-skin{
background: linear-gradient(#ccc, #222);
}
HTML
<div class="box common-skin">...</div>
<div class="button common-skin">...</div>
이런 식으로 구조를 포함하는 속성들만 모아 클래스를 생성하고, 외형만 포함하는 css속성들을 모은 클래스를 생성한다. 그 후 원하는 요소에 클래스 이름만 달아줌으로 스타일링한다. 이 방식을 사용하여 구조와 외형들을 결합하면 다양한 결과물을 얻을 수 있다.
어떤 태그를 직접 선택하거나 자손 선택자를 사용하여 스타일링 하는 것은 재사용성을 낮춘다. 따라서 다른 요소들간에 공통적으로 적용되어야 할 속성이 무엇인지 파악하는 것이 중요하다.
.globalwidth{
position:relative;
padding:20px;
margin: 0 auto;
width:980px;
overflow:hidden;
}
.header-inside{
padding-top:20px;
padding-bottom:20px;
height:260px;
}
이렇게 globalwidth
라는 클래스에 다른 요소에도 사용될 수 있는 속성들을 추출하면 중복된 코드를 줄일 수 있기 때문에 컨테이너와 내용의 분리도 꼭 지켜야 한다.
SMACSS는 Scalable and Modular Architecture CSS의 줄임말로 확장형 모듈식으로 CSS를 구성하는 기법이다. CSS를 Base, Layout, Module, State, Theme 이렇게 다섯가지 카테고리로 나누어 스타일을 정리한다.
기초 스타일을 지정하는 부분으로 default.css
, reset.css
를 적용하는 부분이 Base에 포함된다. 아이디나 클래스 선택자를 사용하는 것이 아니라 기본 태그의 스타일을 지정하는 것이다. 이때 !important
는 허용되지 않는다.
html, body, form {margin:0;padding:0;}
input[type=text] {border:1px solid #999;}
a {color:#000;}
a:hover {color:#666;}
큰 틀의 레이아웃, 다양한 요소들을 구별할 때 사용한다. 주요 컴포넌트에는 header
, footer
, aside
, container
, content
등이 있고, 하위 컴포넌트에는 list
, item
, form
등이 있다. 주요 컴포넌트는 id를 사용하고, 하위 컴포넌트는 class를 사용하여 스타일을 지정한다. 클래스 명을 사용할 때는 l-
또는 layout-
을 붙인다.
#content {width:80%;float:left;}
#aside {width:20%}
.l-fixed #content {
width: 600px;
margin-right: 10px;
}
.l-fixed #aside {
width: 200px
}
레이아웃 안의 더 작은 부분을 가리킬 때 module을 사용하는데 이는 재사용을 가능하게 하기 위함이다. 버튼, 위젯, 배너 등이 이 부분에 포함될 수 있다. 각 모듈은 독립적일 수 있도록 설계해야하며 다른 곳에서도 사용할 수 있어야 한다. 재사용을 해야하기 때문에 id선택자와 엘리먼트 선택자는 사용하지 않고, class 선택자를 사용한다. 만약 엘리먼트 선택자를 사용해야 하는 경우에는 child 선택자(>
)만 사용한다. 모듈 안에 또 다른 모듈이 들어갈 수 있다.
HTML
<div class="box">
<span class="box-name"> ... </span>
<span class="box-items"> ... </span>
</div>
CSS
.box { ... }
.box-name { ... }
.box-items { ... }
툴팁, 아코디언 등 어떤 요소의 상태가 열리거나 닫히는 등의 상태 변화가 일어나는 경우에 사용하는 스타일이다. 클래스를 사용하며 is-
또는 s-
접두사를 사용한다. 상태 스타일은 복잡한 상황에서 !important
를 사용할 수 있다.
<!-- 레이아웃 요소, 접힌 상태 -->
<div id="header" class="is-collapsed">
<form>
<!-- 모듈, 오류 상태 -->
<div class="msg is-error">
There is an error!
</div>
<!-- 연관된 라벨이 숨겨진 상태 -->
<label for="search" class="is-hidden">Search</label>
<input type="text" id="search">
</form>
</div>
#header
는 레이아웃 요소임을 알 수 있으며, .is-collapsed
로 접힌 상태임을 알 수 있다..msg
는 모듈이며 .is-error로 오류 상태임을 알 수 있다.#searchbox
연관된 라벨은 숨겨져 있는 것을 알 수 있다. (.is-hidden
)사이트 전체의 look and feel을 제어한다. 색상이나 이미지를 다룰 때 사용하는데 테마 스타일의 규칙만 모아서 분리한다. 이미 스타일링된 요소 뒤에 다시 재선언하여 테마만 입히는 방식이다.
/* main.css */
.box {
border: 1px solid;
}
/* theme.css - main.css 뒤에서 읽히도록 적용 */
.box {
border-color: blue;
}
BEM은 Block Element Modifier의 약자로 OOCSS, SMACSS보다 더 많이 사용되는 방법론이다. BEM을 사용한다면 id는 사용하지 않고, class만 사용한해야 한다는 것에 주의하자.
재사용이 가능한 독립적인 컴포넌트를 block이라고 한다. 로고 같은 경우는 웹 페이지에서 재사용될 일이 많기 때문에 block이라고 할 수 있다. header, aside, content, footer 등 또한 독립적으로 존재해야 하기 때문에 block이 된다. 이 때 block은 환경에 영향을 받으면 안되기 때문에 여백이나 위치를 설정할 수 없다.
만약 block 안에 또 다른 block이 들어간다면 그냥 클래스 이름을 지정하면 된다.
<div class="header">
<div class="menu">...</div>
<div class="search">...</div>
</div>
element는 block을 구성하는 요소 단위로 의존적인 성격을 가진다. 자신이 속한 블록 안에서만 존재하기 때문에 다른 곳에서 재사용할 수 없는 것들을 element라고 한다. 클래스 이름은 block__element
이렇게 짓는다. 만약 header안에 있는 title이라면 class명은 header__title
가 되겠다. element안에 또 다른 element가 존재할 수 있는데 이 경우에 계속 __
를 붙이는 것은 아니다. 자신을 포함하는 block만 __
앞에 붙여주면 된다.
❌ BAD
<form class="search-form">
<div class="search-form__content">
<input class="search-form__content__input"/>
<button class="search-form__content__button">Search</button>
</div>
</form>
위처럼 __
중첩되는 것이 아니라 아래처럼 사용하면 된다.
⭕ GOOD
<form class="search-form">
<div class="search-form__content" >
<input class="search-form__input" />
<button class="search-form__button">Search</button>
</div>
</form>
이때 주의해야 할점은 다른 블록 앨리먼트 요소에 의존하는 선택자를 사용하면 안된다는 것이다. .search-form .search-form__input
이렇게 선택하면 .search-form__input
은 .search-form
에 의존하게 된다. 따라서 단순히 .search-form__input
클래스명 하나만 선택하면 된다. 이미 이름 자체가 고유하기 때문에 다른 블록이나 엘리먼트들을 함께 지정하지 않아도 된다.
modifier는 block이나 element의 속성을 나타낼 때 사용한다. block—modifier
, block__element—modifier
같은 형태로 사용할 수 있다. modifier 앞에 —
를 붙여주는 것이다. class="block__element—modifier"
이렇게 modifier 혼자 단독으로 사용될 수 없고 class="block__element block__element—modifier"
처럼 기본 블록이나 요소이름을 설정한 후 뒤에 modifier를 추가하는 형태로 사용한다.
modifier에는 boolean 타입과 key-value 타입이 있다.
form__button--focused
boolean 타입인데 이름만 봐서 form 블록의 button 엘리먼트가 focused 되었을 때 사용하는 속성들이라는 것을 쉽게 알아차릴 수 있다.
key-value 형식에서는 하이픈으로 키와 값을 연결하여 사용한다. title—color-gray
어떤 태그가 이 클래스를 가진다면 title블록임을 알 수 있고, color는 gray로 설정되리라 알아차릴 수 있다. 하이픈 하나로 key와 value를 구분해 modifier로 사용한 것이다.
&
과 함께 사용할 때 매우 편리하다.