레진 마크업 가이드는 유연하고 지속 가능한 코드 작성을 위한 사내 표준입니다. Code Guide by @mdo를 기반으로 상식적인 내용과 장황한 내용은 제거했으며 팀에서 논의한 내용을 추가했습니다.
W3C 문법과 레진 마크업 가이드라인을 지켜 코드를 작성합니다. 많은 사람이 참여했더라도 한명이 쓴 것처럼 보이는 코드가 좋습니다. 팀원들과 논의하여 업데이트할 수 있습니다.
규칙을 준수하기 위해 에디터 환경을 설정해 둡니다.
/
)를 사용하지 않습니다. (예: <br />
or <img />
)<!DOCTYPE html>
<html>
<head>
<title>Page title</title>
</head>
<body>
<img src="logo.png" alt="Lezhin">
<h1 class="hello-world">Hello, world!</h1>
</body>
</html>
모든 HTML 페이지 시작 지점에 공백 없이 HTML5 문서 타입을 선언합니다.
<!DOCTYPE html>
<html>
...
</html>
문서 루트인 html
요소에 lang
속성을 추가합니다.
en
ko
ja
<html lang="ko">
문자열 인코딩을 명시적으로 선언합니다.
<head>
<meta charset="UTF-8">
</head>
인터넷 익스플로러가 항상 최신 버전의 레이아웃 엔진을 사용하여 문서를 렌더링하도록 지정합니다.
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
CSS와 JavaScript를 불러올 때 type
속성을 생략합니다.
<!-- External CSS -->
<link rel="stylesheet" href="code-guide.css">
<!-- In-document CSS -->
<style> ... </style>
<!-- JavaScript -->
<script src="code-guide.js"></script>
HTML 태그 속성은 가독성을 위해 아래 순서대로 작성합니다.
id
, class
속성은 가장 앞에 선언합니다.alt
, title
, role
, aria-*
속성은 가장 뒤에 선언합니다.<a id="..." class="..." href="#">Example link</a>
<input class="form-control" type="text">
<img src="..." alt="..." title="...">
불리언 속성의 값은 지정하지 않습니다.
<input type="text" disabled>
<input type="checkbox" value="1" checked>
<option value="1" selected>1</option>
모듈화를 고려하여 마크업은 간결하게 작성합니다.
<!-- Not so great -->
<span class="avatar">
<img src="..." alt="...">
</span>
<!-- Better -->
<img class="avatar" src="..." alt="...">
섹셔닝 요소와 헤딩 요소를 이용하여 문서 개요를 논리적으로 구성합니다. 섹셔닝 요소(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 표준을 준수하고 시맨틱한 문서를 작성하기 위해 노력하기는 하지만 추가적인 노력이 필요하지 않은 범위내에서만 합니다. 최대한 간결한 코드를 사용하도록 합니다.
들여쓰기는 공백문자(
) 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: 1px 1px 1px #ccc, -1px -1px 1px #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 { ... }
포지셔닝과 박스모델 관련 속성을 가장 먼저 작성하고 나머지는 뒤에 놓습니다.
{
/* 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: 10px 0 @variable*2 10px; }
/* Good example */
.element { margin: 10px 0 (@variable * 2) 10px; }
주석은 간결하게 작성합니다. scss 파일은 한 줄 주석(//
) 사용이 가능하지만 CSS 파일에 남지 않습니다.
/* Bad example */
/* Modal - Wrapping element for .modal-header, .modal-body, modal-footer */
.modal {
...
}
/* Good example */
/* Modal */
.modal {
...
}
--
), 더블 언더스코어(__
)만 사용합니다..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
/* Bad example */
section.tweet > header { ... }
section.tweet > header.tweet__header { ... }
.tweet > .tweet__header, .tweet > .tweet__username { ... }
/* Good example */
.tweet { ... }
.tweet__header,
.tweet__username { ... }
/* Modal: modal.scss */
.modal { ... }
.modal__header { ... }
.modal__body { ... }
.modal__footer { ... }
.modal__footer--disabled { ... }
Released under MIT by, and copyright 2014, @mdo and @lezhin