prefixed CSS. 모든 클래스 이름에 역할을 의미하는 두 글자의 접두사를 붙이는 것이 특징으로 OOCSS, SMACSS, BEM에서 많은 영감을 받았다.
CSS를 역할에 따라 다음 여섯 가지 그룹으로 분류해 규칙을 정했다.
•
Base
•
Layout
•
Module
◦
Block Module
◦
Element Module
•
Helper
•
Unique
•
Program
개발 요구 사항에 맞춰 독자적으로 그룹을 만들 수도 있다.
PRECSS에서 권장하는 코딩 규칙
코딩 규칙(공백, 들여쓰기, 줄바꿈 등) 관해서는 기본적으로 구글 HTML/CSS Style Guide(https://google.github.io/styleguide/htmlcssguide.html), Principles of writing consistent, idiomatic CSS(https://github.com/necolas/idiomatic-css)을 준수하는 것을 권장한다.
가능한 세계적으로 유명한 규칙을 도입해서 다른 사람이나 회사와 코드를 공유할 때 되도록 차이가 나지 않게 하기 위해서다.
이름 규칙
클래스 이름에서 영향 범위를 유추할 수 있어야 한다.
PRECSS에서 언더스코어는 구조적 계층을 의미한다. 한 계층 안에 여러 단어를 포함하는 경우 앞 문자를 소문자로 하는 로워 캐멀 케이스를 사용한다.
상세도가 복잡해지는 것을 방지하기 위해 ID 셀렉터는 기본적으로 사용하지 않는다.
"bl_half_media" X : 한 계층 안에서 언더스코어 사용
"bl_halfMedia" O : 한 계층 안에서는 로워 캐멀 케이스 사용
JavaScript
복사
각 모듈의 자녀 요소는 기본적으로 부모 요소 이름만 상속받는다.
자녀 요소 안에 자녀 요소가 중첩된 경우에도 중첩된 자녀 요소는 어디까지나 부모의 이름만 상속받는다.
<div "bl_halfMedia"
<img "bl_halfMedia_img"
<div "bl_halfMedia_desc"
<h3 "bl_halfMedia_ttl"
<p "bl_halfMedia_txt"
</div
</div
JavaScript
복사
아래의 경우 중 하나에 해당할 때 중첩된 자녀 클래스 이름에 가장 가까운 부모 요소의 이름을 포함시킬 수도 있다.
•
부모 자녀 관계를 의도적으로 명확히 정의하고자 할 때
•
모듈이 커서 자녀 요소 이름이 중복되지 않게 할 때
<div "bl_halfMedia"
<img "bl_halfMedia_img"
<div "bl_halfMedia_desc"
<h3 "bl_halfMedia_desc_ttl"
<p "bl_halfMedia_desc_txt"
</div
</div
JavaScript
복사
범용적으로 사용되는 단어
•
_wrapper
•
_inner
•
_header
•
_body
•
_footer
<div "bl_halfMedia_wrapper"
<div "bl_halfMedia"
...
JavaScript
복사
단어를 생략하는 경우
BEM 모듈 설계와 이름 규칙은 멋진 아이디어지만 클래스 이름이 너무 길어지는 경우가 있다.
PRECSS는 단어 생략을 권장한다.
단어를 생략하는 경우 구글 HTML/CSS Style Guide(https://google.github.io/styleguide/htmlcssguide.html)의 4.1.3 ID and Class Name Style(4.1.2와 4.1.3)을 기반으로 한다.
두 단어 이상으로 하나의 의미를 나타내는 단어군은 각 앞글자만 따서 대문자로 명시한다.
일반적인 두 단어 이상 예시
mainVisual → MV (?)
연속한 패턴을 가진 두 단어 이상의 예시
northEurope → NE
그 외 자주 사용되는 생략어
시리즈를 만드는 경우
모듈 클래스 이름은 의미/목적/움직임/(형태는 X)을 알 수 있는 것을 권장하지만 모듈이 반복되면 일련번호를 허용한다. 단, 첫번째 모듈은 붙이지 않는다. 미리 고려해서 다 붙이는 것은 장황하기 때문이다.
<div "bl_halfMedia"
<div "bl_halfMedia2"
<div "bl_halfMedia3"
JavaScript
복사
베이스 그룹
영향 범위를 지나치게 넓히지 않는다.
•
접두사 : 없음
SMACSS 베이스 규칙이나 FLOCSS의 Foundation과 거의 동일하며, 리셋 CSS의 규칙 셋이나 기타 프로젝트의 기본이 되는 스타일링이다.
html {
font ~~
}
a {
color: #1565c0;
tdn;
}
img {
mw100%;
vat;
}
CSS
복사
또한 PRECSS는 특정 범위 안에서 한정적으로 베이스 스타일을 적용하는 것을 허용한다.
예를 들어 헤더 안의 스타일링은 모두 흰색이지만 푸터는 파란색으로 통일한다면 적용할 수 있다. 단, 상세도가 높아지므로 사용할 때 반드시 주의해야 한다.
.ly_header a {
white
}
.ly_footer a {
blue
}
CSS
복사
레이아웃 그룹
•
접두사 : ly_
헤더, 보디, 메인, 사이드, 푸터 등 큰 레이아웃을 형성하는 요소에 사용한다.
원칙적으로 레이아웃 관련 스타일링(width, margin, padding, float 등)만 사용할 수 있다.
어디까지나 콘텐츠가 들어갈 테두리를 정의하는 것이다.
예를 들어 헤더 배경 색상이 검은색일 때처럼 테두리와 일치하는 경우는 레이아웃 이외 스타일링도 수행한다.
모듈 그룹
PRECSS는 재사용성이 높은 코드를 모듈이라는 단위로 관리한다.
•
블록 모듈
•
엘리먼트 모듈
블록 모듈
•
접두사 : bl_
해당 모듈만의 몇 가지 자녀 요소를 가지거나 엘리먼트 모듈이나 블록 모듈을 포함할 수 있다.
BEM에서 ‘여러 Element를 가진 Block’이라고 표현할 수도 있다.
이 여러 자녀 요소나 엘리먼트 모듈을 한 덩어리로 정의해서 다양한 페이지에서 사용할 수 있게 한 것이 기본적인 사고방식이다. 웹페이지의 핵심을 담당하는 모듈이다.
<div "bl_card">
<figure "bl_card_imgWrapper">
<img "code.jpg">
</figure>
<div "bl_card_body">
<p "bl_card_ttl">Special ~~ </p>
<p "bl_card_txt">With supporting ~~</p>
</div>
</div>
HTML
복사
.bl_card {
box-shadow
fs
lh
}
.bl_card_imgWrapper {
pos
pt
ofh
}
.bl_card_imgWrapper img { -(1)
pos
top
w100%
transY
}
.bl_card_body {
p
}
.bl_card_ttl {
mb
fs
fw
}
.bl_card_txt {
color
}
CSS
복사
기본적으로 클래스 셀렉터 하나로 유지하지만 BEM 같이 엄격하지 않다.
(1)처럼 범위가 좁혀져 있다면 자녀(손자)셀렉터도 가능하다.
따라서 리스트는 간단하게 마크업할 수 있다.
<ul "bl_bulletList">
<li>
<li>
</ul>
HTML
복사
.bl_bulletList {}
.bl_bulletList > li {
mb10
}
CSS
복사
블록 모듈에 레이아웃 관련 스타일링은 하지 않는다.
블록 모듈에는 다른 요소에 영향을 주지 않는 스타일만 적용한다.
float, width 같은 걸 적용하지 않는다.
폭은 가능한 초깃값이(block element라 부모 요소만큼 넓어짐) 바람직하다.
레이아웃 지정은 BEM과 마찬가지다.
<div "bl_3colCardUnit">
<div "bl_3colCardUnit_item bl_card">
<div "bl_3colCardUnit_item bl_card">
<div "bl_3colCardUnit_item bl_card">
</div>
HTML
복사
.bl_card {} // 레이아웃 관련 스타일링 없음
.bl_3colCardUnit {
display: flex
}
.bl_3colCardUnit_item { // 여기서 레이아웃 관련 스타일링
w31%
mr
}
CSS
복사
레이아웃 관련 지정이 필요한 경우 블록 모듈을 사용하는 Element(bl_3colCardUnit, bl_3colCardUnit_item)에서 스타일을 적용한다.
스타일을 분리하면 .bl_card 모듈은 재사용성이 매우 높은 블록이 되어 범용적으로 사용할 수 있다.
상세도가 한 단계 높아지긴 하지만 이렇게 구현하는 정도는 괜찮다.
<div "bl_3colCardUnit">
<div "bl_card">
<div "bl_card">
<div "bl_card">
</div>
CSS
복사
.bl_card {} // 레이아웃 관련 스타일링 없음
.bl_3colCardUnit {
display: flex
}
.bl_3colCardUnit > .bl_card { // 여기서 레이아웃 관련 스타일링
w31%
mr
}
CSS
복사
블록 모듈 하나만 사용하는 경우 위아래 여백이 필요할 수도 있다. 아래의 방법으로 허용한다.
•
모듈에 직접 설정한다.
•
모듈에 설정하지 않고 헬퍼 클래스를 일일이 HTML에 붙인다.
→ 헬퍼 클래스 절에서 설명한다.
이 규칙을 지키면 부트스트랩 등 CSS 프레임워크의 그리드 시스템과도 간단히 연동할 수 있다.
블록 모듈에서의 개념, 이름의 상세도
클래스 이름에서 형태, 기능, 역할을 유추할 수 있다.
블록 모듈은 레이아웃을 위해 높은 차원의 모듈을 만드는 경우도 있다. 이 때 이름 지침이 있다.
•
Block : 블록 모듈 기본 단위, 그 모듈 특유의 여러 자녀 요소나 엘리먼트 모듈을 포함한다.
•
Unit : 블록의 집합(.bl_3colCardUnit)
•
Container : 유닛의 집합
필자는 block이라는 단어는 생략한다. 현실적으로 유닛 이상의 단위를 쓸 일은 없을 것이다.
엘리먼트 모듈
•
접두사 : el_
버튼이나 라벨, 제목 등 최소 단위의 모듈로 어디에나 삽입 가능한 모듈이다.
매우 범용적인 이름을 추천한다.
"el_newLabel" X
"el_label" O
"el_submitBtn" X
"el_btn" O
CSS
복사
콘텐츠로 들어가는 대상이 뭐든 괴리감이 없게 하기 위함이다.
배경 색상이 바뀌는 등 엘리먼트 모듈이 달라지는 경우, BEM과 같이 Modifier를 사용한 확장 패턴을 구현한다.
<span "el_label el_label__red">
<span "el_label el_label__blue">
HTML
복사
엘리먼트 모듈의 레이아웃 관련 스타일링
엘리먼트에서도 레이아웃 스타일링은 하지 않는다.
단, 블록 모듈에 비해 그 변형에 한계가 있는 경우가 많다. 예를 들면, 버튼 크기의 유형은 사이트에서 대개 5~6가지 정도다. 따라서 엘리먼트 모듈에 직접 width를 주거나 Modifier로 크기를 변경하는 것을 허용한다.
그러나 Modifier 이름은 주의를 기울여야 한다.
<button "el_btn">
<button "el_btn el_btn__w200">
HTML
복사
미디어 쿼리로 데스크톱 환경에서는 200px, 모바일에서는 가로폭을 100%로 지정했을 때 “el_btn__w200”라는 이름은 논리적으로 맞지 않다. 또는 데스크탑과 모바일 둘다 폭을 200px로 하고 싶을 때 이름이 충돌하게 된다.
따라서 Modifier를 만들 때 가급적 ‘small’(s)과 같은 단어를 권장한다.
<button "el_btn el_btn__s">
HTML
복사
.el_btn.el_btn__s {
w200
}
@media screen and (mw:768) {
.el_btn.el_btn__s {
w100%
}
}
CSS
복사
엘리먼트 모듈을 사용하는 엘리먼트의 자녀 요소 클래스를 사용해 스타일링하는 것도 가능하지만 상세도가 동일할 때 선언 순서를 확실하게 관리하지 않으면 덮어쓰기를 할 수 없는 경우가 생긴다.
.el_btn { w300 }
.bl_headerUtils_btn { w200 } // 선언순서에 의해서 덮어쓰는 경우
CSS
복사
.btn_headerUtils_btn.el_btn {} // 상세도를 높여 덮어쓰는 경우
CSS
복사
블록 모듈인가 엘리먼트 모듈인가
정의하기 어렵지만 알기 쉬운 기준으로 ‘다른 여러 모듈 안에 삽입되어 있는가?’를 사용할 수 있다.
버튼이나 라벨을 떠올리면 된다.
또한, ‘루트 요소와 자녀 요소를 포함해 요소 수가 대략 세 개 이내’라는 지침도 도움이 된다.
모디파이어
이름 규칙 : {기반 클래스 이름}__{모디파이어 이름} // 언더바 2개
다음과 같은 경우 모디파이어로 덮어쓴다.
•
모습이 변한다.
•
크기가 변한다.
•
일정한 규칙에 따라 움직임이 변한다.(컬럼 등)
모디파이어 이름 규칙
__backgroundColorRed와 같이 __keyValue를 기본으로 하지만 el_btn__red처럼 상상 가능하다면 key를 생략해도 된다.
BEM은 형태보다 의미를 중시하지만 현실적으로 모든 색에 의미 부여는 어렵기 때문에
PRECSS는 el_btn__red도 허용한다.(el_btn__cautionColor도 가능)
헬퍼 그룹
•
접두사 : hp_
기본적으러 하나의 스타일만으로 ‘이 부분의 스타일만 조정하고 싶은 경우' 사용한다.
덮어쓰기가 매우 의도적이기 때문에 !important를 추가하는 것을 권장한다.
이름 규칙은 Modifier와 마찬가지로 ‘keyValue’ 형태이고 생략할 때 에밋 속기법을 따른다.
hp_mb20
•
px 이외의 단어면 에밋 속기법(없으면 두문자)
•
소수점은 언더스코어
•
음수값은 key를 대문자로 표현
.hp_mt2e { mt: 2em !important} // px 이외 단위
.hp_mt2_5e { mt: 2.5em !important} // 소수점은 언더스코어
.hp_MT2e { mt: -2em !important} // 음수는 대문자
CSS
복사
모디파이어 이름 규칙으로 유효하다.
헬퍼 클래스가 세 개 이상 사용되었다면 유지보수성이 떨어지므로 기본적으로 포함시켜야 할지 고려하는 게 바람직하다.
clearfix에 관해
float 해제 기법도 헬퍼에 포함시킬 수 있다. 접두사는 붙일 필요 없다.
부모 요소에서 overflow: hidden을 본래의 용도로 쓸 수도 있기 때문에 clearfix는 사용하는 것을 권장한다.
헬퍼 확장 그룹을 만든다.
필자는 독자적인 그룹으로 데스크톱 화면 폭용 헬퍼 그룹(lg_)과 태블릿 화면 폭 이하용 헬퍼 그룹(md_)을 만들어 쓴다.
.lg_only { display: block !important }
@media ~~( mw 768 ) {
.lg_only {
display: none !important;
}
}
CSS
복사
.md_only { display: none !important }
@media ~~( mw 768 ) {
.lg_only {
display: block !important;
}
}
CSS
복사
모듈 위아래 사이 여백을 구현하는 헬퍼 클래스
여백이 디자인상으로 통일되어 있으면 직접 넣어도 되지만 아닌 경우가 많다.
카드 모듈 다음에 텍스트가 올 때는 20px을 주고 싶지만 다음 모듈이 오는 경우 40px로 주고 싶다면 이런 경우 모듈 자체에 여백을 위한 스타일링을 수행하는 건 현실적이지 않다.
(반응형 일단 생략)
유니크 그룹
•
접두사 : un_
특정한 한 페이지에서만 적용됨을 명시한 그룹
예를 들어, PRECSS 문서의 최상위 페이지 같은 특별한 페이지, 모듈 설계에서 벗어난 position: absolute가 많이 나타나는 위치에 사용하는 것도 좋다.
다양한 불규칙성에 대한 만능 회피책으로, 곤란할 때 쓰면 된다. 단, 사용할 때 어느 페이지에서 사용하는지 주석으로 남겨두는 것이 좋다.
프로그램 그룹
PRECSS에서는 자바스크립트 등 프로그램에서 요소에 붙이거나 상태를 관리할 때, 전용 클래스를 추가해서 스타일링과 분리한다.
•
접두사: js_
js에서 요소를 얻기 위한 클래스
•
접두사: is_
요소의 상태를 관리하기 위한 클래스, 상태 스타일링은 반드시 적용되어야 하므로 !important를 권장한다.
is_active같은 것은 다른 위치에 영향을 미치지 않도록 반드시 상세도를 높인다.(셀렉터 중첩)
대응 브라우저나 상황에 따라 커스텀 데이터 속성이나 WAI-ARIA로 상태 관리도 허용한다.
.is_active {} // X
.js_accordion_body.is_active {
display: block;
} // O
CSS
복사
block or none(표시/비표시) 같은 경우보다 다양한 스타일링이 필요한 경우에 .js와 .is를 조합하는 것보다 .bl과 .is를 조합해 스타일링하는 걸 제안한다.
오리지널 그룹
오리지널 그리드 레이아웃을 구현한 경우 .gr_4나 .cl_4 같이 그룹을 추가할 수 있다.
PRECSS는 하이픈을 사용하지 않기 때문에 개발 환경 전체에 대한 이름 규칙을 통일할 수도 있다.
정리
•
유니크 그룹이 존재해 영향 범위가 명확한 모듈을 정의할 수 있다.
•
필요에 따라 그룹을 추가해 확장할 수 있다.
•
이름 규칙을 여러 환경에서 사용할 수 있다.