Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/choegyumin/markup-coding-conventions
마크업 코딩 컨벤션 (HTML/CSS 스타일 가이드)
https://github.com/choegyumin/markup-coding-conventions
Last synced: 23 days ago
JSON representation
마크업 코딩 컨벤션 (HTML/CSS 스타일 가이드)
- Host: GitHub
- URL: https://github.com/choegyumin/markup-coding-conventions
- Owner: choegyumin
- License: other
- Archived: true
- Created: 2015-05-18T02:04:22.000Z (about 9 years ago)
- Default Branch: master
- Last Pushed: 2018-12-28T08:34:54.000Z (over 5 years ago)
- Last Synced: 2024-02-25T01:33:24.203Z (4 months ago)
- Language: HTML
- Homepage:
- Size: 459 KB
- Stars: 16
- Watchers: 2
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Lists
- awesome-References - html/css 코드 컨벤션
README
# Markup Coding Conventions (HTML/CSS Style Guide)
## Table of Contents
[Glossaries](#glossaries)
- [1. HTML](#html)
- [1-1. Syntax](#html-syntax)
- [1-2. Doctype](#html-doctype)
- [1-3. Metadata](#html-metadata)
- [1-4. Elements](#html-elements)
- [1-5. Attributes](#html-attributes)
- [1-6. Import](#html-import)
- [2. CSS](#css)
- [2-1. Syntax](#css-syntax)
- [2-2. Charset](#css-charset)
- [2-3. Selectors](#css-selectors)
- [2-4. z-index](#css-z-index)
- [2-5. Import](#css-import)
- [2-6. Media Query](#css-media-query)
- [2-7. Nesting](#css-nesting)
- [2-8. Extend](#css-extend)
- [2-9. Reset](#css-reset)
- [2-10. Vendor Prefix](#css-vendor-prefix)
- [3. Naming](#naming)
- [3-1. Selectors](#naming-selectors)[Changelogs](#changelogs)
[License](#license)Glossaries
먼저 스타일 가이드에 자주 사용되는 용어의 정의를 설명합니다.
- 엘리먼트(Element)
- HTML 문서를 구성하는 요소(태그)를 의미합니다.
- 애트리뷰트(Attribute)
- 엘리먼트에 부여할 수 있는 특성을 의미합니다.
- 선택자(Selector)
- 엘리먼트를 식별할 수 있는 이름을 의미합니다.
- 스타일(Style)
- 엘리먼트에 부여할 스타일 시트(Style Sheet)를 의미합니다. 인라인 스타일(Inline Style), 내부 스타일(Internal Style), 외부 스타일(External Style), CSS 네가지로 구분합니다.
- 프로퍼티(Property)
- 스타일과 관련된 문맥일 경우 스타일 시트의 속성을 의미합니다.
- 프리픽스(Prefix) & 서픽스(Suffix)
- 네이밍 시 사용되는 접두사, 접미사를 의미합니다.
- 컴포넌트(Component)
- 하나 이상의 기능 또는 역할을 가진 컨텐츠 단위의 UI 구성요소를 의미합니다.
[↑ Table of Conetnts](#table-of-contents)
1. HTML
HTML 코드의 작성 규칙을 설명합니다.
1-1. Syntax
> **EditorConfig의 사용을 권장합니다!**
- 들여쓰기는 2개의 공백 문자(소프트탭)을 사용하세요. 다른 규칙으로 통일하여 작성해도 됩니다.
- 모든 엘리먼트 명과 애트리뷰트 명은 케밥 표기법(`kebab-case`)으로 작성하세요.
- 모든 애트리뷰트 값은 큰 따옴표(`"`)로 감싸세요.
- 닫는 태그가 선택적이라도 생략하지 마세요. (ex: ``, `` 래퍼 엘리먼트
필요에 따라 본문을 숨겨야 하거나, 본문 위에 다른 레이어 엘리먼트가 겹칠 수도 있습니다. 본문의 화면 조작을 위해 본문을 래퍼 엘리먼트에 작성하세요.
```html
Hello, World!
```
#### B. 스타일 제어가 어려운 엘리먼트
자식 엘리먼트 태그가 한정적이거나(ex. ``) 스타일 제어에 한계를 가진 엘리먼트(ex. ``)가 컴포넌트의 루트 역할로 쓰일 땐 나중에 발생할 유지보수를 고려해 `
> 이 외의 불필요한 엘리먼트 상속은 반드시 피해야 합니다!
```html
```
#### C. 테이블 제목
`` 엘리먼트의 뷰를 숨길 때는 새로운 엘리먼트로 감싸서 숨기세요. ``을 바로 숨긴다면 브라우저에 따라 스타일이 깨질 수도 있습니다.
```html
My Caption
```
테이블의 제목이 필요없거나 이미 제공되었다면 생략하세요. 컨텐츠를 중복 제공하는 것은 좋지 않습니다. 이 때 `aria-labelledby` 애트리뷰트를 사용하면 더 좋습니다.
```html
My Caption
My Caption
My Caption
```
#### D. 입력 필드
회원가입 폼의 입력 필드처럼 너비, 높이가 유동적이라면 인라인 스타일로 제어하세요. 이렇게 하면 불필요한 클래스 생성을 막을 수 있습니다.
```html
```
1-5. Attributes
애트리뷰트는 변하지 않는 것부터 먼저 선언하세요. 애트리뷰트의 순서가 비슷한 엘리먼트끼리 통일되므로 검색하기 편해집니다.
```html
```
#### A. Boolean 애트리뷰트
HTML5에서는 Boolean 애트리뷰트를 선언하는 것 만으로도 `true` 값을 가집니다. 필요하지 않다면 값을 작성하지 마세요.
```html
```
#### B. `name` 애트리뷰트
`name` 애트리뷰트 값은 비즈니스 로직을 작성하는 언어의 네이밍 규칙에 맞게 작성하는 것을 권장합니다.
```html
```
1-6. Import
- HTML5에서 CSS와 JS 파일을 불러올 때 `type` 애트리뷰트는 이미 기본값을 가집니다. 필요하지 않다면 선언하지 마세요.
- `` 엘리먼트는 가급적 `<head>` 또는 `<body>` 엘리먼트의 가장 마지막에 작성하세요. 웹브라우저는 `<script>` 엘리먼트를 만나면 처리가 끝날 때까지 HTML 파싱을 멈춥니다.
[↑ Table of Conetnts](#table-of-contents)
<h2 id="css">2. CSS</h2>
CSS와 SASS, LESS, Stylus 등의 CSS 전처리기(CSS Preprocessor) 코드의 작성 규칙을 설명합니다.
<h3 id="css-syntax">2-1. Syntax</h3>
> **<a target="_blank" href="http://editorconfig.org/">EditorConfig</a>와 Lint의 사용을 권장합니다!**
- 들여쓰기는 2개의 공백 문자(소프트탭)을 사용하세요. 다른 규칙으로 통일하여 작성해도 됩니다.
- 프로퍼티는 한 줄에 하나씩 작성하세요. 다른 규칙으로 통일하여 작성해도 됩니다.
- 프로퍼티는 영문 소문자로 작성하세요.
- 일반적으로 작은 따옴표(`'`)를 사용하지만 `@charset` 선언과 타입 선택자는 큰 따옴표(`"`)를 사용하세요. 가능하다면 생략하는 것이 가장 좋습니다.
<h3 id="css-charset">2-2. Charset</h3>
문서의 언어셋은 `UTF-8`으로 최상위에 선언하세요. 언어셋이 정해진 번들링 파일이라면 선언하지 않습니다.
```css
@charset "UTF-8";
```
<h3 id="css-selectors">2-3. Selectors</h3>
- **선택자는 가급적 중첩하지 마세요!**
- **렌더링 성능 최적화를 위해 클래스, 가상 선택자 외의 선택자는 사용을 피하세요!**
> 선택자의 중첩을 피하는 방법은 <a href="#naming">3. Naming</a> 섹션을 참고하세요.
> ###### 참고자료
> - <a target="_blank" href="http://markdotto.com/2012/03/02/stop-the-cascade/">Stop the cascade · @mdo</a>
> - <del><a target="_blank" href="https://developer.mozilla.org/ko/docs/Web/CSS/Writing_Efficient_CSS">효율적인 CSS 작성하기 - CSS | MDN</a></del> (<a target="_blank" href="http://webclub.tistory.com/361"> 번역본</a>)
<h3 id="css-z-index">2-4. z-index</h3>
`z-index` 스택을 `0`부터 규칙 없이 쌓는다면 순서가 꼬일 수 밖에 없습니다. 엘리먼트의 특성에 맞게 계층을 분리하여 체계적으로 관리하는 것이 더 좋은 방법입니다.
> **CSS 전처리기의 믹스인을 활용한다면 간편하게 작성할 수 있습니다.**
```scss
/* scss */
.foo {
position: absolute;
@include layer-index('floating', 3000);
}
/* css */
.foo {
z-index: 16203000
}
```
#### A. Normal
평범한 엘리먼트입니다.
- Value: `-1` ~ `99999`
#### B. `inline-popover`
마우스 오버 또는, 클릭 등의 이벤트 트리거링으로 특정 상황에서 상위에 노출되어야 하는 엘리먼트입니다. 상태 클래스를 이용하여 스택을 유동적으로 관리하세요.
> 부모 엘리먼트의 위치에 영향을 받지 않는 엘리먼트는 `inline-popover` 대신 `popover`을 사용합니다.
- Value: `16100000` ~ `16199999`
```css
.dropdown {
position: relative;
}
.dropdown.is-expand {
position: absolute;
@include layer-index('inline-popover');
}
```
#### C. `floating`
플로팅 레이어는 항상 상위에 떠있어야 합니다.
- Value: `16200000` ~ `16299999`
#### D. `dialog`
다이얼로그는 본문보다 위에 노출되어야 합니다.
- Value: `16300000` ~ `16399999`
#### E. `popover`
이벤트 트리거링으로 상위에 노출되어야 하는 엘리먼트입니다. `inline-popover`와 같은 상황일 때 엘리먼트가 `position: fixed;`거나 `<body>`의 자식으로 존재한다면 사용하세요.
- Value: `16400000` ~ `16499999`
```css
.dropdown {}
.dropdown-menu {
position: fixed;
@include layer-index('popover');
}
```
#### F. `toast`
토스트는 사용자가 확인할 수 있도록 페이지의 최상위에 노출되어야 합니다.
- Value: `16500000` ~ `16599999`
#### G. `super`
무조건 최상위에 노출됩니다. 정말 필요할 때만 사용하세요.
- Value: `16600000` ~ `16699999`
#### H. `skip`
스킵 네비게이션은 어디서든 접근 가능해야 하므로 다른 레이어에 절대 가려지지 않아야 합니다.
- Value: `16777271`
<h3 id="css-import">2-5. Import</h3>
**CSS의 기본 문법인 `@import`는 성능 문제를 가지고 있습니다. 절대 사용하지 마세요!** 대신 아래의 방법으로 개발하세요.
- 여러개의 `<link>` 엘리먼트로 작성하기
- 하나의 CSS 파일로 작성하기
- CSS 전처리기의 `@import` 문법을 사용하기
- 번들러 등의 도구를 이용하여 하나의 CSS 파일로 병합하기
```html
<!-- Too Bad -->
<style>
@import url("one.css");
@import url("two.css");
@import url("three.css");
</style>
<!-- Good -->
<link rel="stylesheet" href="one.css">
<link rel="stylesheet" href="two.css">
<link rel="stylesheet" href="three.css">
<!-- Very Nice -->
<link rel="stylesheet" href="bundle.css"> <!-- one.css, .. in bundle.css -->
```
<h3 id="css-media-query">2-6. Media Query</h3>
미디어 쿼리는 컴포넌트 단위로 분류하여 관련 규칙 바로 뒤에 작성하세요. 이렇게 하면 파편화된 스타일이 한곳으로 모여져 가독성이 좋아집니다. 불가능하다면 문서의 마지막에 모아서 작성하세요.
```css
.foo-a {}
.foo-b {}
@media (min-width: 768px) {
.foo-a {}
.foo-b {}
}
.bar {}
```
```css
.foo-a {}
.foo-b {}
.bar {}
@media (min-width: 768px) {
.foo-a {}
.foo-b {}
}
```
<h3 id="css-nesting">2-7. Nesting</h3>
너무 많은 선택자의 중첩은 피해야 하므로, **CSS 전처리기가 지원하는 Nesting 문법은 주의해서 사용해야 합니다!** 무분별하게 사용하면 컴파일된 CSS가 엉망이 될 수도 있습니다.
> - 선택자의 중첩을 피해야하는 이유는 <a href="#css-selectors">2-3. Selectors</a> 섹션의 참고자료를 참고하세요.
> - 선택자의 중첩을 피하는 방법은 <a href="#naming">3. Naming</a> 섹션을 참고하세요.
```scss
/* Bad */
.foo {
.bar {
color: #abc;
}
}
/* Good */
.foo__bar {
color: #abc;
}
```
<h3 id="css-extend">2-8. Extend</h3>
**CSS 전처리기가 지원하는 Extend 문법은 절대 사용하지 마세요! Mixin으로 대체하세요!**
> ###### 참고자료
> - <a target="_blank" href="https://sass-guidelin.es/ko/#extend">Sass 가이드라인</a>
> - <a target="_blank" href="https://csswizardry.com/2014/11/when-to-use-extend-when-to-use-a-mixin/">When to use @extend; when to use a mixin - CSS Wizardry</a>
<h3 id="css-reset">2-9. Reset</h3>
초기화 스타일은 서비스에 맞게 정의하세요. 만약 <a target="_blank" href="http://necolas.github.io/normalize.css/">normalize.css</a> 또는 <a target="_blank" href="http://getbootstrap.com/">Bootstrap</a> 등의 프레임워크를 사용한다면 초기화를 생략하세요.
<h3 id="css-vendor-prefix">2-10. Vendor Prefix</h3>
벤더 프리픽스 프로퍼티는 일반 프로퍼티보다 먼저 선언하세요.
```css
/* Bad */
.foo {
box-shadow: 0 1px 2px rgba(0, 0, 0, .15);
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .15);
}
/* Good */
.foo {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .15);
box-shadow: 0 1px 2px rgba(0, 0, 0, .15);
}
```
[↑ Table of Conetnts](#table-of-contents)
<h2 id="naming">3. Naming</h2>
네이밍 규칙을 설명합니다.
<h3 id="naming-selectors">3-1. Selectors</h3>
> 이 규칙은 *<a target="_blank" href="http://csswizardry.com/2015/08/bemit-taking-the-bem-naming-convention-a-step-further/">BEMIT</a> 방법론*(*<a target="_blank" href="https://en.bem.info/methodology/naming-convention/">BEM</a>* + *<a target="_blank" href="http://csswizardry.net/talks/2014/11/itcss-dafed.pdf">ITCSS</a>*)을 기반으로 작성되었습니다.
> ###### 참고자료
> - BEM
> - <a target="_blank" href="https://en.bem.info/">BEM</a>
> - <a target="_blank" href="http://getbem.com/">Get BEM</a>
> - ITCSS
> - <a target="_blank" href="http://csswizardry.net/talks/2014/11/itcss-dafed.pdf">Managing CSS Projects with ITCSS</a>
> - <a target="_blank" href="https://www.xfive.co/blog/itcss-scalable-maintainable-css-architecture/">ITCSS: SCALABLE AND MAINTAINABLE CSS ARCHITECTURE</a>
> - <a target="_blank" href="https://willianjusten.com.br/organizando-seu-css-com-itcss/">Organizando seu CSS com ITCSS</a>
> - BEMIT
> - <a target="_blank" href="http://csswizardry.com/2015/08/bemit-taking-the-bem-naming-convention-a-step-further/">BEMIT: Taking the BEM Naming Convention a Step Further</a>
> - <a target="_blank" href="http://csswizardry.com/2015/03/more-transparent-ui-code-with-namespaces/">More Transparent UI Code with Namespaces</a>
> - <a target="_blank" href="http://www.jamesturneronline.net/blog/bemit-naming-convention.html">The BEMIT naming convention</a>
- **스타일 제어를 위해 아이디 선택자의 사용을 피하세요!**
- **클래스명은 반드시 엘리먼트의 의미를 전부 담아서 네이밍하세요!**
- **클래스명은 페이지에 상속받지 않으며, 디자인보다는 구조, 기능, 목적을 나타내는 이름으로 네이밍하세요!**
#### A. Naming
Syntax: `<BLOCK>[__<ELEMENT>][--<MODIFIER>][.is|has-<STATE>]`
- 기본 네이밍 규칙은 BEM을 따릅니다.
```BLOCK__ELEMENT--MODIFIER```
- 상태 클래스는 `modifier`에서 분리하여 따로 관리합니다.
```BLOCK__ELEMENT--MODIFIER.is-STATE```
```html
<div class="widget">
<div class="widget__wrapper widget__wrapper--dark">
<input class="input" type="text" aria-label="Text Field">
<button class="btn" type="reset">Reset</button>
<button class="btn btn--submit is-disabled" type="submit" disabled>Submit</button>
</div>
</div>
```
```css
.widget {} /* BLOCK */
.widget__wrapper {} /* BLOCK__ELEMENT */
.widget__wrapper--dark {} /* BLOCK__ELEMENT--MODIFIER */
.input {} /* BLOCK */
.btn {} /* BLOCK */
.btn.is-disabled {} /* .BLOCK.is-STATE */
.btn--submit {} /* .BLOCK--MODIFIER */
.btn--submit.is-disabled {} /* .BLOCK--MODIFIER.is-STATE */
```
#### B. Layer
스타일 시트의 계층(Layer)은 9단계로 나뉩니다.
- Settings
- Tools
- Generic
- Base
- Objects
- Components
- Pages
- Themes
- Utilities(Trumps)
###### Example with SASS(scss)
```scss
@import "settings/_breakpoints";
@import "settings/_colors";
@import "tools/_functions";
@import "tools/_mixins";
@import "generic/_normalize";
@import "base/_forms";
@import "base/_headings";
@import "base/_hr";
@import "base/_links";
@import "base/_lists";
@import "base/_page";
@import "base/_quotes";
@import "base/_tables";
@import "objects/_grid";
@import "components/_comment";
@import "components/_fields";
@import "components/_dialog";
@import "components/_drawer";
@import "components/_footer";
@import "components/_header";
@import "components/_page-title";
@import "components/_pagination";
@import "components/_post";
@import "components/_share-menu";
@import "pages/_about";
@import "pages/_archive";
@import "pages/_contact";
@import "pages/_error";
@import "pages/_faq";
@import "utilities/_blind";
```
##### a. Settings
전역 변수를 작성하세요.
```scss
$breakpoints: (
//'xsmall': 'screen',
'small': 'screen and (min-width: 640px)',
'medium': 'screen and (min-width: 1024px)',
'large': 'screen and (min-width: 1280px)',
'xlarge': 'screen and (min-width: 1440px)',
'retina': 'screen and (-webkit-min-device-pixel-ratio:1.5)'
);
```
##### b. Tools
CSS 전처리기를 사용한다면 Function과 Mixin을 작성하세요.
```scss
@mixin background-rgba($color, $alpha) {
$rgba: rgba($color, $alpha);
$ie-hex-str: ie-hex-str($rgba);
background-color: $rgba;
filter: progid:DXImageTransform.Microsoft.gradient(StartColorStr=#{$ie-hex-str},EndColorStr=#{$ie-hex-str});
&:not([dummy]) {
filter: progid:DXImageTransform.Microsoft.gradient(enabled='false');
}
}
```
##### c. Generic
문서의 초기 스타일을 작성하세요.
```scss
html,
body {}
a,
input,
textarea,
button {}
```
##### d. Base
태그 선택자 또는 타입 선택자를 이용하여 각 태그 엘리먼트의 기본 스타일을 작성하세요.
```scss
button,
input[type='button'],
input[type='submit'],
input[type='reset'],
input[type='image'] {}
```
##### e. Objects
반복적이며 재사용이 가능한 디자인 패턴을 작성하세요. 이는 시각적인 효과보단 레이아웃을 위한 스타일을 중점으로 작성합니다. 클래스 대신 CSS 전처리기의 믹스인으로 작성하는 것도 좋은 방법입니다.
```scss
.row {}
.col-s12 {}
.col-m12 {}
.col-l12 {}
```
##### f. Components
컴포넌트 스타일을 작성하세요.
```scss
.combobox {}
.combobox__item {}
.combobox.is-expanded {}
```
##### g. Pages
페이지 스타일을 작성하세요. 컴포넌트 기반 개발 방식을 따르는 경우에도 페이지 스타일이 무수히 많아진다면 설계가 잘못됐을 가능성이 높습니다. (Pages 계층은 *ITCSS* 규칙이 아닙니다)
> ###### 참고자료
> - <a target="_blank" href="http://slowalk.tistory.com/2440">슬로워크 블로그 :: 스타일 가이드로 웹서비스 개발하기</a>
```scss
.about-page {}
```
##### h. Themes
테마 스타일을 작성하세요.
```html
<html class="dark-theme">
<body>
<div class="spinner"></div>
</body>
</html>
```
```scss
.combobox {
.dark-theme & {}
}
```
```scss
.combobox {}
.dark-theme {
.combobox {}
}
```
테마 스타일을 새로운 CSS 파일로 분리하여 작성할 수도 있습니다.
```html
<link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/css/dark-theme.css">
```
##### i. Utilities (Trumps)
스타일을 오버라이드하거나 전역 스타일로 사용할 수 있는 헬퍼를 작성합니다. 때에 따라 프로퍼티에 `!important`를 추가할 수 있습니다.
```scss
.blind {}
```
[↑ Table of Conetnts](#table-of-contents)
<h2 id="license">License</h2>
이 저작물은 <a rel="license" target="ccl" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" style="vertical-align:top">크리에이티브 커먼즈 저작자표시-비영리-동일조건변경허락 4.0 국제 라이선스</a>에 따라 이용할 수 있습니다.
<img alt="크리에이티브 커먼즈 저작자표시-비영리-동일조건변경허락" title="" style="border-width:0;vertical-align:top" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
[↑ Table of Conetnts](#table-of-contents)