레진 마크업 가이드는 유연하고 지속 가능한 코드 작성을 위한 사내 표준입니다. Code Guide by @mdo를 기반으로 상식적인 내용과 장황한 내용은 제거했으며 팀에서 논의한 내용을 추가했습니다.
기본 규칙 #
W3C 문법과 레진 마크업 가이드라인을 지켜 코드를 작성합니다. 많은 사람이 참여했더라도 한명이 쓴 것처럼 보이는 코드가 좋습니다. 팀원들과 논의하여 업데이트할 수 있습니다.
에디터 설정 #
규칙을 준수하기 위해 에디터 환경을 설정해 둡니다.
- 들여쓰기는 공백문자 4개로 합니다.
- 파일 저장 시 줄 끝 공백문자를 제거합니다.
- 파일 저장 시 UTF-8 인코딩으로 저장합니다.
- 파일의 맨 마지막은 줄바꿈으로 끝납니다.
HTML #
HTML 문법 #
- 들여쓰기는 공백문자 4 개를 사용합니다.
- 속성(attr)값에는 항상 큰 따옴표를 사용합니다.
- 단일 태그에는 슬래시(
/)를 사용하지 않습니다. (예:<br />or<img />)
<!DOCTYPE html><html><head><title>Page title</title></head><body><imgsrc="logo.png" alt="Lezhin"><h1class="hello-world">Hello, world!</h1></body></html>HTML5 doctype #
모든 HTML 페이지 시작 지점에 공백 없이 HTML5 문서 타입을 선언합니다.
<!DOCTYPE html><html>
...
</html>언어(lang) 속성 #
문서 루트인 html 요소에 lang 속성을 추가합니다.
- 영어:
en - 한국어:
ko - 일본어:
ja
<htmllang="ko">인코딩 설정 #
문자열 인코딩을 명시적으로 선언합니다.
<head><metacharset="UTF-8"></head>IE 호환모드 설정 #
인터넷 익스플로러가 항상 최신 버전의 레이아웃 엔진을 사용하여 문서를 렌더링하도록 지정합니다.
<metahttp-equiv="X-UA-Compatible" content="IE=Edge">CSS, JavaScript 삽입 #
CSS와 JavaScript를 불러올 때 type 속성을 생략합니다.
<!-- External CSS --><linkrel="stylesheet" href="code-guide.css"><!-- In-document CSS --><style> ... </style><!-- JavaScript --><scriptsrc="code-guide.js"></script>속성(attr) 선언 순서 #
HTML 태그 속성은 가독성을 위해 아래 순서대로 작성합니다.
- 선택자로 사용하는
id,class속성은 가장 앞에 선언합니다. - 콘텐츠를 설명하는
alt,title,role,aria-*속성은 가장 뒤에 선언합니다.
<aid="..." class="..." href="#">Example link</a><inputclass="form-control" type="text"><imgsrc="..." alt="..." title="...">Boolean 속성 #
불리언 속성의 값은 지정하지 않습니다.
<inputtype="text" disabled><inputtype="checkbox" value="1" checked><optionvalue="1" selected>1</option>마크업 간소화 #
모듈화를 고려하여 마크업은 간결하게 작성합니다.
<!-- Not so great --><spanclass="avatar"><imgsrc="..." alt="..."></span><!-- Better --><imgclass="avatar" src="..." alt="...">문서 개요(HTML5 아웃라인) #
섹셔닝 요소와 헤딩 요소를 이용하여 문서 개요를 논리적으로 구성합니다. 섹셔닝 요소(section, article, nav, aside)에는 헤딩 요소를 명시적으로 사용합니다. 명시적 헤딩 기법은 h1 요소를 한 페이지에 한 번 사용합니다. 헤딩 요소만으로 문서 개요를 파악할 수 있어야 합니다.
<!-- Bad HTML --><body><h1>동물</h1><div><h1>포유류</h1><div><h1>고래</h1></div></div></body><!-- Good HTML --><body><h1>동물<h1><article><h2>포유류<h2><section><h3>고래<h3></section></article></body>완벽함보다는 실용성을 추구 #
HTML 표준을 준수하고 시맨틱한 문서를 작성하기 위해 노력하기는 하지만 추가적인 노력이 필요하지 않은 범위내에서만 합니다. 최대한 간결한 코드를 사용하도록 합니다.
CSS #
CSS 문법 #
들여쓰기는 공백문자() 4개를 사용합니다.
/* 들여쓰기에 tab 문자 사용 안 함 */
{
property: value;
property: value;
}선택자를 그룹핑하는 경우 쉼표(,) 뒤에서 줄바꿈합니다.
/* X */
.selector1, .selector2 { ... }
/* O */
.selector1,
.selector2 { ... }속성값에는 홑따옴표('')를 사용합니다.
/* X */
[type=text] { ... }
[type="text"] { ... }
{ background:url(ex.png); }
{ background:url("ex.png"); }
/* O: 속성 선택자 속성값에 홑따옴표 사용 */
[type='text'] { ... }
/* O: CSS 속성값에 홑따옴표 사용 */
{ background:url('ex.png'); }한 줄에 하나의 속성만 작성하고, 마지막은 항상 세미콜론(;)으로 끝냅니다.
/* 속성이 하나 뿐이라면 한 줄에 작성합니다. 여는 중괄호({) 좌우로 하나의 공백, 닫는 중괄호(}) 왼쪽에 하나의 공백을 포함합니다. */
.selector { property: value; }
/* 속성이 둘 이상이라면 속성 기준으로 줄바꿈합니다. 여는 중괄호({) 뒤에서 줄바꿈하고, 닫는 중괄호(})는 새로운 줄에 놓습니다. */
.selector {
property: value;
property: value;
}
/* 여는 중괄호({) 앞에는 항상 공백 하나를 포함합니다. *//* 콜론(:) 뒤에는 항상 공백 하나를 포함합니다. */다중 속성값들은 쉼표(,) 뒤에 공백 또는 줄바꿈을 포함합니다.
/* 속성값이 길지 않은 경우 한 줄에 표현 */
{ box-shadow:1px1px1px#ccc,-1px-1px1px#000; }
/* 속성값이 길면 여러 줄에 표현 */
{
background-image:url('//cdn.lezhin.com/assets/images/header.png'),url('//cdn.lezhin.com/assets/images/footer.png');
}괄호(()) 안에서는 쉼표(,) 뒤에 공백을 넣지 않습니다.
/* X */color:rgba(0,0,0,.5);
/* O */color:rgba(0,0,0,.5);축약 가능한 값을 축약합니다.
/* X */color:#ffffff;
font-weight: normal;
font-weight: bold;
border: none;
opacity:0.5;
border-width:0px;
background-size:100% auto;
background-position:50%50%;
/* O */color:#fff;
font-weight:400;
font-weight:700;
border:0;
opacity:.5;
border-width:0;
background-size:100%;
background-position:50%;의미있는 블럭 기준으로 빈 줄을 포함합니다.
/* X: 선택자 또는 속성 사이에 빈 줄 금지 */
.selector1 { ... }
.selector2 {
property: value;
property: value;
}
/* O: 의미있는 블럭 기준으로 빈 줄 포함 *//* 헤더 */
.header { ... }
.header__element { ... }
/* 풋터 */
.footer { ... }
.footer__element { ... }속성(property) 선언 순서 #
포지셔닝과 박스모델 관련 속성을 가장 먼저 작성하고 나머지는 뒤에 놓습니다.
{
/* Positioning */position: absolute;
top:0;
right:0;
bottom:0;
left:0;
z-index:100;
/* Box-model */display: block;
float: right;
flex:1;
width:100px;
height:100px;
/* Typography */font: normal 13px"Helvetica Neue", sans-serif;
line-height:1.5;
color:#333;
text-align: center;
/* Background */background-color:#f5f5f5;
/* Border */border:1px solid #e5e5e5;
border-radius:3px;
/* etc */opacity:1;
}미디어 쿼리 위치 #
미디어쿼리는 관련 규칙이 있는 자리에 모아 놓습니다.
.element { ... }
.element-avatar { ... }
.element-selected { ... }
@media (min-width:640px) {
.element { ... }
.element-avatar { ... }
.element-selected { ... }
}단일 속성 #
하나의 속성만 포함한다면 개행하지 않습니다.
/* Single declarations on one line */
.span1 { width:60px; }
.span2 { width:140px; }
.span3 { width:220px; }
/* Multiple declarations, one per line */
.sprite {
display: inline-block;
width:16px;
height:15px;
background-image: url(../img/sprite.png);
}전처리문 중첩 #
과도하게 중첩하지 않습니다. 선택자 반복을 피하는 용도로만 중첩을 사용하십시오.
/* Without nesting */
.table>thead>tr>th { … }
.table>thead>tr>td { … }
/* With nesting */
.table>thead {
th { … }
td { … }
}전처리문 계산식 #
계산식에 괄호를 사용합니다.
/* Bad example */
.element { margin:10px0@variable*210px; }
/* Good example */
.element { margin:10px0 (@variable*2) 10px; }주석 #
주석은 간결하게 작성합니다. scss 파일은 한 줄 주석(//) 사용이 가능하지만 CSS 파일에 남지 않습니다.
/* Bad example *//* Modal - Wrapping element for .modal-header, .modal-body, modal-footer */
.modal {
...
}
/* Good example *//* Modal */
.modal {
...
}클래스 작명 #
- 클래스 이름 규칙은 BEM(Block Element Modifier)스타일을 따릅니다.
- 클래스 이름은 영문 카멜케이스(camelCase), 숫자, 더블 대시(
--), 더블 언더스코어(__)만 사용합니다. - 짧고 간결하게 작성하되 축약하지 않습니다.
.btn과 같이 쉽게 의미를 유추 할 수 있는 축약은 괜찮지만.bn와 같이 의미를 파악하기 어려운 축약은 사용하지 않습니다. - 시각적 표현 대신 의미, 구조, 목적을 담아 작명합니다.
- 변화 또는 상태를 나타내는 추가 클래스는 블록 또는 요소 이름에 더블 대시(
--)를 붙여 작명합니다.
/* Bad example */
.sform { ... }
.themeLezhin { ... }
.sf-input { ... }
.sf-btn { ... }
.SearchformButtonDisabled { ... }
/* Good example */
.blockName { ... } // Block
.blockName__elementName { ... } // Element
.blockName--modifierName { ... } // Block Modifier
.blockName__ElementName--modifierName { ... } // Element Modifier선택자 #
- 타입 선택자를 사용하지 않습니다. 클래스 선택자를 사용합니다.
- 선택자 우선순위(specificity)를 높이는 조합과 중첩을 사용하지 않습니다. 조합과 중첩은 3회를 초과하지 않습니다.
- 여러 클래스를 묶을 때 쉼표 후 개행합니다.
/* Bad example */section.tweet>header { ... }
section.tweet>header.tweet__header { ... }
.tweet> .tweet__header, .tweet> .tweet__username { ... }
/* Good example */
.tweet { ... }
.tweet__header,
.tweet__username { ... }컴포넌트 #
- 컴포넌트 별로 코드를 모아서 작성합니다.
- 계층 구조의 순서에 따라 작성합니다.
- 코드 블럭을 분리할 때 공백(줄 바꿈)을 일관성 있게 사용합니다.
- 여러개의 *.scss 파일을 나눌 때, 페이지보다는 컴포넌트 별로 나눕니다.
/* Modal: modal.scss */
.modal { ... }
.modal__header { ... }
.modal__body { ... }
.modal__footer { ... }
.modal__footer--disabled { ... }License #
Released under MIT by, and copyright 2014, @mdo and @lezhin