├── LICENSE.md
└── README.md
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Mark Otto.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 레진 마크업 가이드
2 |
3 | 레진 마크업 가이드는 유연하고 지속 가능한 코드 작성을 위한 사내 표준입니다. [Code Guide by @mdo](http://mdo.github.io/code-guide)를 기반으로 상식적인 내용과 장황한 내용은 제거했으며 팀에서 논의한 내용을 추가했습니다.
4 |
5 | - - -
6 |
7 | 1. [기본 규칙](#basic)
8 | 2. [에디터 설정](#editor)
9 | 3. [HTML](#html)
10 | 1. [HTML 문법](#html-syntax)
11 | 2. [HTML5 doctype](#html-doctype)
12 | 3. [언어(lang) 속성](#html-lang)
13 | 4. [인코딩 설정](#html-charset)
14 | 5. [IE 호환모드 설정](#html-ie-compatible)
15 | 6. [CSS, JavaScript 삽입](#html-type-attr)
16 | 7. [속성(attr) 선언 순서](#html-attr-order)
17 | 8. [Boolean 속성](#html-boolean-attr)
18 | 9. [마크업 간소화](#html-simplification)
19 | 10. [문서 개요(HTML5 아웃라인)](#html-outline)
20 | 11. [완벽함보다는 실용성을 추구](#html-pragmatism)
21 | 4. [CSS](#css)
22 | 1. [CSS 문법](#css-syntax)
23 | 2. [속성(property) 선언 순서](#css-property-order)
24 | 3. [미디어 쿼리 위치](#css-media-query)
25 | 4. [단일 속성](#css-single-property)
26 | 5. [전처리문 중첩](#css-preprocessor-nesting)
27 | 6. [전처리문 계산식](#css-preprocessor-calculation)
28 | 7. [주석](#css-comment)
29 | 8. [클래스 작명](#css-naming)
30 | 9. [선택자](#css-selector)
31 | 10. [컴포넌트](#css-component)
32 | 5. [License](#license)
33 |
34 | - - -
35 |
36 | ## 기본 규칙 #
37 |
38 | W3C 문법과 레진 마크업 가이드라인을 지켜 코드를 작성합니다. 많은 사람이 참여했더라도 한명이 쓴 것처럼 보이는 코드가 좋습니다. 팀원들과 논의하여 업데이트할 수 있습니다.
39 |
40 | - - -
41 |
42 | ## 에디터 설정 #
43 | 규칙을 준수하기 위해 에디터 환경을 설정해 둡니다.
44 |
45 | * 들여쓰기는 공백문자 4개로 합니다.
46 | * 파일 저장 시 줄 끝 공백문자를 제거합니다.
47 | * 파일 저장 시 UTF-8 인코딩으로 저장합니다.
48 | * 파일의 맨 마지막은 줄바꿈으로 끝납니다.
49 |
50 | - - -
51 |
52 | ## HTML #
53 |
54 | ### HTML 문법 #
55 |
56 | * 들여쓰기는 공백문자 4 개를 사용합니다.
57 | * 속성(attr)값에는 항상 큰 따옴표를 사용합니다.
58 | * 단일 태그에는 슬래시(`/`)를 사용하지 않습니다. (예: ` ` or ``)
59 |
60 | ```html
61 |
62 |
63 |
64 | Page title
65 |
66 |
67 |
68 |
Hello, world!
69 |
70 |
71 | ```
72 |
73 | ### HTML5 doctype #
74 | 모든 HTML 페이지 시작 지점에 공백 없이 HTML5 문서 타입을 선언합니다.
75 | ```html
76 |
77 |
78 | ...
79 |
80 | ```
81 |
82 | ### 언어(lang) 속성 #
83 | 문서 루트인 `html` 요소에 `lang` 속성을 추가합니다.
84 | * 영어: `en`
85 | * 한국어: `ko`
86 | * 일본어: `ja`
87 |
88 | ```html
89 |
90 | ```
91 |
92 | ### 인코딩 설정 #
93 | 문자열 인코딩을 명시적으로 선언합니다.
94 | ```html
95 |
96 |
97 |
98 | ```
99 |
100 | ### IE 호환모드 설정 #
101 | 인터넷 익스플로러가 항상 최신 버전의 레이아웃 엔진을 사용하여 문서를 렌더링하도록 지정합니다.
102 | ```html
103 |
104 | ```
105 |
106 | ### CSS, JavaScript 삽입 #
107 | CSS와 JavaScript를 불러올 때 `type` 속성을 생략합니다.
108 | ```html
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 | ```
118 |
119 | ### 속성(attr) 선언 순서 #
120 | HTML 태그 속성은 가독성을 위해 아래 순서대로 작성합니다.
121 |
122 | 1. 선택자로 사용하는 `id`, `class` 속성은 가장 앞에 선언합니다.
123 | 2. 콘텐츠를 설명하는 `alt`, `title`, `role`, `aria-*` 속성은 가장 뒤에 선언합니다.
124 |
125 | ```html
126 | Example link
127 |
128 |
129 | ```
130 |
131 | ### Boolean 속성 #
132 | 불리언 속성의 값은 지정하지 않습니다.
133 | ```html
134 |
135 |
136 |
137 | ```
138 |
139 | ### 마크업 간소화 #
140 | 모듈화를 고려하여 마크업은 간결하게 작성합니다.
141 | ```html
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 | ```
150 |
151 | ### 문서 개요(HTML5 아웃라인) #
152 | 섹셔닝 요소와 헤딩 요소를 이용하여 문서 개요를 논리적으로 구성합니다. 섹셔닝 요소(`section`, `article`, `nav`, `aside`)에는 헤딩 요소를 명시적으로 사용합니다. 명시적 헤딩 기법은 `h1` 요소를 한 페이지에 한 번 사용합니다. 헤딩 요소만으로 문서 개요를 파악할 수 있어야 합니다.
153 | ```html
154 |
155 |
156 |
동물
157 |
158 |
포유류
159 |
160 |
고래
161 |
162 |
163 |
164 |
165 |
166 |
167 |
동물
168 |
169 |
포유류
170 |
171 |
고래
172 |
173 |
174 |
175 | ```
176 |
177 | ### 완벽함보다는 실용성을 추구 #
178 | HTML 표준을 준수하고 시맨틱한 문서를 작성하기 위해 노력하기는 하지만 추가적인 노력이 필요하지 않은 범위내에서만 합니다. 최대한 간결한 코드를 사용하도록 합니다.
179 |
180 |
181 | - - -
182 |
183 | ## CSS #
184 |
185 | ### CSS 문법 #
186 |
187 | 들여쓰기는 공백문자(` `) 4개를 사용합니다.
188 | ```css
189 | /* 들여쓰기에 tab 문자 사용 안 함 */
190 | {
191 | property: value;
192 | property: value;
193 | }
194 | ```
195 |
196 | 선택자를 그룹핑하는 경우 쉼표(`,`) 뒤에서 줄바꿈합니다.
197 | ```css
198 | /* X */
199 | .selector1, .selector2 { ... }
200 |
201 | /* O */
202 | .selector1,
203 | .selector2 { ... }
204 | ```
205 |
206 | 속성값에는 홑따옴표(`''`)를 사용합니다.
207 | ```css
208 | /* X */
209 | [type=text] { ... }
210 | [type="text"] { ... }
211 | { background: url(ex.png); }
212 | { background: url("ex.png"); }
213 |
214 | /* O: 속성 선택자 속성값에 홑따옴표 사용 */
215 | [type='text'] { ... }
216 |
217 | /* O: CSS 속성값에 홑따옴표 사용 */
218 | { background: url('ex.png'); }
219 | ```
220 |
221 | 한 줄에 하나의 속성만 작성하고, 마지막은 항상 세미콜론(`;`)으로 끝냅니다.
222 | ```css
223 | /* 속성이 하나 뿐이라면 한 줄에 작성합니다. 여는 중괄호({) 좌우로 하나의 공백, 닫는 중괄호(}) 왼쪽에 하나의 공백을 포함합니다. */
224 | .selector { property: value; }
225 |
226 | /* 속성이 둘 이상이라면 속성 기준으로 줄바꿈합니다. 여는 중괄호({) 뒤에서 줄바꿈하고, 닫는 중괄호(})는 새로운 줄에 놓습니다. */
227 | .selector {
228 | property: value;
229 | property: value;
230 | }
231 |
232 | /* 여는 중괄호({) 앞에는 항상 공백 하나를 포함합니다. */
233 | /* 콜론(:) 뒤에는 항상 공백 하나를 포함합니다. */
234 | ```
235 |
236 | 다중 속성값들은 쉼표(`,`) 뒤에 공백 또는 줄바꿈을 포함합니다.
237 | ```css
238 | /* 속성값이 길지 않은 경우 한 줄에 표현 */
239 | { box-shadow: 1px 1px 1px #ccc, -1px -1px 1px #000; }
240 |
241 | /* 속성값이 길면 여러 줄에 표현 */
242 | {
243 | background-image:
244 | url('//cdn.lezhin.com/assets/images/header.png'),
245 | url('//cdn.lezhin.com/assets/images/footer.png');
246 | }
247 | ```
248 |
249 | 괄호(`()`) 안에서는 쉼표(`,`) 뒤에 공백을 넣지 않습니다.
250 | ```css
251 | /* X */
252 | color: rgba(0, 0, 0, .5);
253 |
254 | /* O */
255 | color: rgba(0,0,0,.5);
256 | ```
257 |
258 | 축약 가능한 값을 축약합니다.
259 | ```css
260 | /* X */
261 | color: #ffffff;
262 | font-weight: normal;
263 | font-weight: bold;
264 | border: none;
265 | opacity: 0.5;
266 | border-width: 0px;
267 | background-size: 100% auto;
268 | background-position: 50% 50%;
269 |
270 | /* O */
271 | color: #fff;
272 | font-weight: 400;
273 | font-weight: 700;
274 | border: 0;
275 | opacity: .5;
276 | border-width: 0;
277 | background-size: 100%;
278 | background-position: 50%;
279 | ```
280 |
281 | 의미있는 블럭 기준으로 빈 줄을 포함합니다.
282 | ```css
283 | /* X: 선택자 또는 속성 사이에 빈 줄 금지 */
284 | .selector1 { ... }
285 |
286 | .selector2 {
287 |
288 | property: value;
289 |
290 | property: value;
291 |
292 | }
293 |
294 | /* O: 의미있는 블럭 기준으로 빈 줄 포함 */
295 | /* 헤더 */
296 | .header { ... }
297 | .header__element { ... }
298 |
299 | /* 풋터 */
300 | .footer { ... }
301 | .footer__element { ... }
302 | ```
303 |
304 |
305 | ### 속성(property) 선언 순서 #
306 | 포지셔닝과 박스모델 관련 속성을 가장 먼저 작성하고 나머지는 뒤에 놓습니다.
307 | ```css
308 | {
309 | /* Positioning */
310 | position: absolute;
311 | top: 0;
312 | right: 0;
313 | bottom: 0;
314 | left: 0;
315 | z-index: 100;
316 | /* Box-model */
317 | display: block;
318 | float: right;
319 | flex: 1;
320 | width: 100px;
321 | height: 100px;
322 | /* Typography */
323 | font: normal 13px "Helvetica Neue", sans-serif;
324 | line-height: 1.5;
325 | color: #333;
326 | text-align: center;
327 | /* Background */
328 | background-color: #f5f5f5;
329 | /* Border */
330 | border: 1px solid #e5e5e5;
331 | border-radius: 3px;
332 | /* etc */
333 | opacity: 1;
334 | }
335 | ```
336 |
337 | ### 미디어 쿼리 위치 #
338 | 미디어쿼리는 관련 규칙이 있는 자리에 모아 놓습니다.
339 | ```css
340 | .element { ... }
341 | .element-avatar { ... }
342 | .element-selected { ... }
343 | @media (min-width: 640px) {
344 | .element { ... }
345 | .element-avatar { ... }
346 | .element-selected { ... }
347 | }
348 | ```
349 |
350 | ### 단일 속성 #
351 | 하나의 속성만 포함한다면 개행하지 않습니다.
352 | ```css
353 | /* Single declarations on one line */
354 | .span1 { width: 60px; }
355 | .span2 { width: 140px; }
356 | .span3 { width: 220px; }
357 |
358 | /* Multiple declarations, one per line */
359 | .sprite {
360 | display: inline-block;
361 | width: 16px;
362 | height: 15px;
363 | background-image: url(../img/sprite.png);
364 | }
365 | ```
366 |
367 | ### 전처리문 중첩 #
368 | 과도하게 중첩하지 않습니다. 선택자 반복을 피하는 용도로만 중첩을 사용하십시오.
369 | ```css
370 | /* Without nesting */
371 | .table > thead > tr > th { … }
372 | .table > thead > tr > td { … }
373 |
374 | /* With nesting */
375 | .table > thead {
376 | th { … }
377 | td { … }
378 | }
379 | ```
380 |
381 | ### 전처리문 계산식 #
382 | 계산식에 괄호를 사용합니다.
383 | ```css
384 | /* Bad example */
385 | .element { margin: 10px 0 @variable*2 10px; }
386 |
387 | /* Good example */
388 | .element { margin: 10px 0 (@variable * 2) 10px; }
389 | ```
390 |
391 | ### 주석 #
392 | 주석은 간결하게 작성합니다. scss 파일은 한 줄 주석(`//`) 사용이 가능하지만 CSS 파일에 남지 않습니다.
393 | ```css
394 | /* Bad example */
395 | /* Modal - Wrapping element for .modal-header, .modal-body, modal-footer */
396 | .modal {
397 | ...
398 | }
399 |
400 | /* Good example */
401 | /* Modal */
402 | .modal {
403 | ...
404 | }
405 | ```
406 |
407 | ### 클래스 작명 #
408 | * 클래스 이름 규칙은 [BEM(Block Element Modifier)](http://getbem.com/naming/)스타일을 따릅니다.
409 | * 클래스 이름은 영문 카멜케이스(camelCase), 숫자, 더블 대시(`--`), 더블 언더스코어(`__`)만 사용합니다.
410 | * 짧고 간결하게 작성하되 축약하지 않습니다. `.btn`과 같이 쉽게 의미를 유추 할 수 있는 축약은 괜찮지만 `.bn`와 같이 의미를 파악하기 어려운 축약은 사용하지 않습니다.
411 | * 시각적 표현 대신 의미, 구조, 목적을 담아 작명합니다.
412 | * 변화 또는 상태를 나타내는 추가 클래스는 블록 또는 요소 이름에 더블 대시(`--`)를 붙여 작명합니다.
413 |
414 | ```css
415 | /* Bad example */
416 | .sform { ... }
417 | .themeLezhin { ... }
418 | .sf-input { ... }
419 | .sf-btn { ... }
420 | .SearchformButtonDisabled { ... }
421 |
422 | /* Good example */
423 | .blockName { ... } // Block
424 | .blockName__elementName { ... } // Element
425 | .blockName--modifierName { ... } // Block Modifier
426 | .blockName__ElementName--modifierName { ... } // Element Modifier
427 | ```
428 |
429 | ### 선택자 #
430 | * 타입 선택자를 사용하지 않습니다. 클래스 선택자를 사용합니다.
431 | * 선택자 우선순위(specificity)를 높이는 조합과 중첩을 사용하지 않습니다. 조합과 중첩은 3회를 초과하지 않습니다.
432 | * 여러 클래스를 묶을 때 쉼표 후 개행합니다.
433 |
434 | ```css
435 | /* Bad example */
436 | section.tweet > header { ... }
437 | section.tweet > header.tweet__header { ... }
438 | .tweet > .tweet__header, .tweet > .tweet__username { ... }
439 |
440 | /* Good example */
441 | .tweet { ... }
442 | .tweet__header,
443 | .tweet__username { ... }
444 | ```
445 |
446 | ### 컴포넌트 #
447 | * 컴포넌트 별로 코드를 모아서 작성합니다.
448 | * 계층 구조의 순서에 따라 작성합니다.
449 | * 코드 블럭을 분리할 때 공백(줄 바꿈)을 일관성 있게 사용합니다.
450 | * 여러개의 *.scss 파일을 나눌 때, 페이지보다는 컴포넌트 별로 나눕니다.
451 |
452 | ```css
453 | /* Modal: modal.scss */
454 | .modal { ... }
455 | .modal__header { ... }
456 | .modal__body { ... }
457 | .modal__footer { ... }
458 | .modal__footer--disabled { ... }
459 | ```
460 |
461 | - - -
462 |
463 | ### License #
464 |
465 | Released under MIT by, and copyright 2014, @mdo and @lezhin
466 |
--------------------------------------------------------------------------------