├── 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 | Lezhin 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 | --------------------------------------------------------------------------------