Sass 코딩 컨벤션
Sass Coding Convention
Sass 작성을 위한 컨벤션에 대해 알아봅니다.
Table of Contents
- 폴더 구조 [Folder structures]
- 파일 구조 [File structures]
- 인코딩 [Encoding]
- 중첩 [Nesting]
- 들여쓰기 및 선언 순서 [Style Rules]
- 띄워쓰기 [Spacing words]
- 주석 [Comments]
- 네이밍규칙 [Naming]
- 믹스인 [Mixin]
- @extend [Extend]
- 제어구문 (@if, @each, @for 등) [Control Statements]
- 연산자 [Operators]
Sass 코딩컨벤션은 마크업 코딩컨벤션을 상속하여 코드 스타일링등의 기본 작성 규칙들은 마크업 코딩 컨벤션을 따르며, 그밖의 Sass만의 문법들에 대한 규칙을 정의함.
1. 폴더 구조 [Folder structures]
root
ㄴ src
ㄴ scss
ㄴ common
ㄴ import
ㄴ * (선택)
ㄴ lib (선택)
ㄴ css
ㄴ img
ㄴ *.html
-
기본구조는 마크업 코딩컨벤션의 폴더 구조 규칙을 따른다.
-
root/내에서 src/외의 폴더는 자유롭게 관리한다.
-
lib/와 import/*/은 필요에 따라 생성한다.
2. 파일 구조 [File structures]
scss
ㄴ 서비스명.scss
ㄴ common
ㄴ _base.scss
ㄴ _variables.scss
ㄴ _mixins.scss
ㄴ _placeholders.scss
ㄴ import
ㄴ _*.scss
ㄴ * (선택)
ㄴ lib (선택)
ㄴ _*.scss
scss/
- 서비스명.scss : import 구문으로 이루어진 메인
common/
- _base.scss : CSS reset 모음
- _variables.scss
- _mixins.scss
- _placeholders.scss : extend 모음
import/
- _*.scss : 기능 또는 페이지 이름으로 자유롭게 생성
lib/ : 외부라이브러리 모음 (선택)
- _*.scss: 외부라이브러리
import/ 내의 파일 네이밍은 강제하지 않으며, 편의를 위해 다음과 같이 사용할 수 있다.
- 파일명에 prefix붙여 네이밍한다.
- 하위 폴더를 생성하여 파일을 구분해 넣는다.
3. 인코딩 [Encoding]
- windows 환경에서 컴파일 시 오류가 발생할 수 있으므로 모든 scss파일에 charset을 선언한다.
- 컴파일 후에 charset 선언은 하나만 남게 되므로 여러 파일에서 작성해도 문제없다.
@charset 선언 전에 공백없도록 주의하여 최상단에 선언한다.
@charset "UTF-8"
body {
margin: 0;
}
4. 중첩 [Nesting]
- 최대 3뎁스 중첩까지 사용하는 것을 권장한다 ( 셀렉터의 갯수가 아닌 scss 코드상의 중첩 )
- 3뎁스가 넘어갈 경우는 하위연결자를 활용하거나 별도의 모듈로 뽑아내는 것을 고려한다.
- 미디어 쿼리의 중괄호는 중첩수에 포함하지 않는다.
권장되는 사용법
.foo {
.bar {
.baz {
}
.baz .qux {
}
}
}
.foo {
.bar {
.baz {
}
.qux {
}
}
}
나쁜 사용법
.foo {
.bar {
.baz {
.qux {
}
}
}
}
5. 들여쓰기 및 선언 순서 [Style Rules]
- 중첩 마다 들여 쓰기 한다.
- 하위 선택자가 시작될 때 빈 줄을 추가한다.
extend
/include
를 상단에 모아쓰고 그 뒤에 빈 줄을 추가한다.- 재선언이 필요한 경우 include를 필요한 위치에 추가 할 수 있다.
권장되는 사용법
.foo {
//@extend, @include는 상단에 모아쓰고 그 뒤 빈 줄을 추가한다.
@extend %a;
@extend %b;
@include abc(n);
//속성 별 개행.
display: block;
overflow: hidden;
position: relative;
z-index: 10;
width: 100px;
margin: 0;
padding: 0;
border: 1px solid red;
background: red;
font-weight: bold;
letter-spacing: -1px;
text-decoration: underline;
//상황에 따라 하단에 위치할수도 있음.
@include bcd(n);
//하위 선택자가 시작될 때 빈 줄 추가.
.bar {
...
}
}
나쁜 사용법
//개행 하지 않음
.foo {
@extend %a;@extend %b;@include abc(n);display:block;overflow:hidden;position:relative;z-index:10;width:100px;margin:0;padding:0;border:1px solid red;background:red;font-weight:bold;letter-spacing:-1px;text-decoration:underline;
.bar {...}
}
//@extend를 상단에 모아 쓰지 않음, @extend와 @include 다음 빈줄을 추가 하지 않음
.foo {
@include abc(n);
display: block;
overflow: hidden;
position: relative;
z-index: 10;
@extend %b;
width: 100px;
@extend %a;
.bar {
...
}
}
//하위 선택자 전에 빈줄을 추가 하지 않음, 들여쓰기 하지 않음
.foo {
@extend %a;
@extend %b;
@include abc(n);
display: block;
overflow: hidden;
position: relative;
z-index: 10;
width: 100px;
.bar {
margin: 0;
padding: 0;
}
}
scss 파일이 css로 변환되는 과정에서 설정에 따라 공백과 여백을 없앨 수 있다. 때문에 scss 파일에서는 css 파일과 달리 가독성에 중점을 두고 속성마다 개행 한다.
ui 별로 파일을 나누면 한 파일의 길이를 줄일 수 있다.
@extend
와 @include
를 사용한 바로 다음 라인은 @extend
,
@include
가 그룹화된 느낌과 다음 라인에 오는 속성의 가독성을 위해 빈 줄을 추가한다.
하위 선택자가 시작될 때 빈 줄을 추가하면 하위 선택자의 가독성이 높아진다.
속성 선언 순서를 컨벤션 따르면 다음 작업자가 속성을 쉽게 찾을 수 있다.
6. 띄워쓰기 [Spacing words]
가독성을 높이고 개발자도구와 코드 일관성을 유지하기 위해 아래와 같이 띄워쓰기를 권장한다.
연산자(Operator)와 연결자(Combinator)는 기호 좌/우측을 한 칸 띄운다.
예시 :
// - 와 * 앞/뒤를 한칸 띄운다.
$height - ($width * 2)
// > 와 + 앞/뒤를 한칸 띄운다.
.title > .tx:after
.title + div
7. 주석 [Comments]
CSS 주석표현인 /* 주석 */으로 import되는 파일상단에 파일명 표기
- 개발자도구로 디버깅 시(sass미사용자, 서비스 초기 투입 시) 선언위치 파악에 도움
예시 :
@charset "utf-8";
/* _layout.scss */
...
그 외 주석은 컴파일되지 않도록 //으로 표기
- 기능(mixin, 변수…) 대한 설명, UIO 등
- 이미 기존 CSS에 /* 주석 */ 이 선언되어있던 것을 굳이 //주석으로 수정할 필요는 없음
- CSS에 반드시 컴파일되어야 하는 주석이 있다면 /* */ 으로 표기 가능
예시 :
@charset "utf-8";
/* _layout.scss */
//Header
...
//Footer
...
주석 컴파일 테스트
_layout.scss
@charset "utf-8";
/* _layout.scss */
//Header
#header{background:#fff}
//Footer
...
서비스명.scss
@charset "utf-8";
@import "common/base";
@import "common/variables";
@import "common/mixins";
@import "common/placeholders";
@import "import/layout";
서비스명.css
@charset "utf-8";
/* _base.scss */
...
/* _variables.scss */
/* _mixin.scss */
/* _placeholders.scss */
...
/* _layout.scss */
#header{background:#fff}
...
8. 네이밍규칙 [Naming]
8.1. placeholder selector
- 문자: 소문자
- 연결자: _ (Underbar)
예시 :
%text_color
중복 class 처럼 활용할 수 있기 때문에 class명 네이밍(컨벤션) 처럼 연결자를 _ (Underbar)로 사용하는 것을 권장
8.2. mixin
- 문자 및 연결자: Camel Casing Notation
예시 :
@mixin testBox() {
...
}
@mixin testBox($test) {
...
}
mixin: 선언 시 class명(_ Underbar), css속성명(- Hyphen)과 다르게 눈에 들어올 수 있는 네이밍이 필요하여 Camel Casing Notation으로 사용하는 것을 권장
8.3. 변수
- 지역변수(로컬 변수): 소문자
- 전역변수(글로벌 변수): G-소문자
- 상수: 대문자
- 상수란? 선언 이후에는 변하지 않는 값 (자세한 개념파악은 생략)
- 상수는 CSS에서는 활용도가 낮은 편으로.. 굳이 사용한다면 대문자로 표기 권장 함
- 연결자: - (Hyphen)
- 네이밍 조합 : ${요소(Element, class) 이름} - {속성 이름} - {용도 및 역할}
네이밍의 조합은 상황에 맞게 재조합 혹은 생략가능
class명에 _ (underbar)가 있는 경우에는 underbar 와 hyphen의 혼용 허용. ex) $btn_more-color 등
'용도 및 역할'은 축약형 지양
네이밍 조합 케이스 |
예시 |
---|---|
$ {요소(E) 이름} - {속성 이름} |
$body-color, $body-background-color, $G-body-background-color 등} |
$ {요소(E) 이름} - {용도 및 역할} |
$body-horizental 등 |
$ {요소(E) 이름} - {속성 이름} - {용도 및 역할} |
$body-color-point, $body-background-color-point 등 |
$ {요소(class) 이름} - {속성 이름} |
$btn-border-color, $btn_more-border-color 등 |
$ {요소(class) 이름} - {속성 이름} - {용도 및 역할} |
$btn-border-color-hover, $btn_more-border-color-hover 등 |
$ {속성 이름} - {용도 및 역할} |
$color-point, $G-color-point, $margin-endpage, $margin-endpage-wide 등 |
$ {용도 및 역할} |
$index, $count, $length, $max-count 등 |
좋은 예 :
$G-body-color: #fff;
$G-font-family-base: Dotum,'돋움',Helvetica,AppleSDGothicNeo,sans-serif;
$G-font-family-tahoma: tahoma, sans-serif;
.test {
$color-point: #ff0078;
$margin-endpage: 15px;
}
나쁜 예 :
//BAD : 전역변수(글로벌 변수)에는 구분을 위해 'G-' 를 prefix로 사용
//(as-is: body-color / to-be: G-body-color)
$body-color: #fff;
.test {
//BAD: '용도 및 역할'의 변수명은 축약형을 지양하며,
//fullname 사용(as-is: color-pnt / to-be: color-point)
$color-pnt: #ff0078;
//BAD
//1. '용도 및 역할'의 변수명은 축약형을 지양하며,
//fullname 사용(as-is: endCtSide / to-be: end-content-side)
//2. 변수 네이밍은 카멜형식이 아닌 소문자, 연결자는 - (Hyphen)사용(참조: 표 - 네이밍 조합 케이스)
$endCtSide: 15px;
}
- 디렉토리 경로에 대한 변수
- 선택사항으로, 변수 선언시 아래와 같은 규칙으로 선언하도록 권장한다.
종류 |
변수이름 지정규칙 |
---|---|
프로젝트 루트 or 도메인 |
$G-path |
img 디렉토리 |
$G-path-img |
img 디렉토리 이하 |
$G-path-img-{서브 디렉토리 이름} |
- 아래 예제처럼 배경이미지 경로를 적용할 때 유용하다.
예시 :
$G-path: '../';
$G-path-img: $G-path + 'img/';
.class {
background-image: url($G-path-img + 'sp_service.png');
}
- 변수는 사용성을 위해 요소명, css속성명, 용도 및 역할 등 여러 조합형태로 쓰일 수 있고, mixin이 Camel Casing Notation을 사용하기로 하였으므로 구분을 위해 - (Hyphen)로 사용하는 것을 권장
- 로컬변수(지역변수)와 글로별변수(전역변수)를 'G-'와 같은 prefix 를 사용하여 구분한 이유
- 처음부터 로컬변수(지역변수)와 글로벌변수(전역변수)의 차이를 이해하고, 구분하여 선언해야 유시보수가 용이하기 때문
- 글로벌변수(전역변수)에 'G-' 를 붙인 이유
- 로컬변수(지역변수)의 사용양이 많으므로 글로벌변수(전역변수)에 붙임
- Global 의 약자인 G를 대문자로 사용하여 명확성을 더하고, 변수명의 연결자인 - (Hyphen)을 붙여 위에 약속한 조합의 변수명을 연결하여 사용하는 것을 권장
8.3.1. 지역변수(로컬변수)와 전역변수(글로벌 변수)
- 정의
- 지역변수 : 블록 내에서 선언 된 변수 (범위 : 블록 내에서만)
- 전역변수 : 블록 밖에서 선언 된 변수 (범위 : 전체)
- 사용
- 특정 요소 / 모듈의 속성 값을 사이트 전체에서 사용하는 경우 속성 값을 전역변수로 사용한다.
예시 :
$G-var: 10px; //전역변수
.foo {
$var: 5px; //지역변수
$body-width: 100px; //지역변수
...
}
@mixin sample($foo) {
...
//지역변수
}
8.3.2. 선언
- 1. 변수는 한 줄에 하나만 선언한다.
예시 :
$var1: value;
$var2: value;
- 2. _variables.scss 파일 내부에 선언한 변수들은 #표 - 네이밍 조합 케이스 에 따라 선언한다.
예시 :
@charset "utf-8";
/* _variables.scss */
//요소(Element, class) 이름 - 속성 이름
$G-header-background-color-point;
...
//속성 - 용도 및 역할 기준
$G-color-point: #ff0078
...
//용도 및 역할 기준
$G-path-img: "../im/";
...
//로컬변수
$btn_area-width: 10px;
...
- 3. 전역변수는 _variables.scss에 선언하거나, 별도의 import 파일을 사용하지 않는 경우 관련 scss파일의 상단에 정의한다.
9. 믹스인 [Mixin]
- 인자값 사용유무에 따라 mixin과 extend를 분리하여 사용
mixin
과 extend
을 어떻게 구분하여 사용해야 하는가?' 에 대한 고민
기준차이: 작업자 스타일에 따라 다름
성능차이: 거의 없음
용량차이: 상황에 따라 다름
개인취향에 따라 mixin과 extend의 사용이 혼돈된다.
하지만, mixin은 인자값을 활용할 수 있다는 큰 특징이 있으므로 이를 기준으로 분리하여 사용하는 것을 권장
인자값에 대한 네이밍은 #표 - 네이밍 조합 케이스을 참고한다.
기본 mixin 문법
@mixin border-radius($radius) {
-webkit-border-radius: $radius;
-moz-border-radius: $radius;
-ms-border-radius: $radius;
border-radius: $radius;
}
.box {
@include border-radius(10px);
}
.box {
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
-ms-border-radius: 10px;
border-radius: 10px;
}
- mixin의 다양한 선언방법
10. @extend [Extend]
- 선언방법
- %(place holder) 선택자를 사용
예시 :
%bar {
border:1px solid red;
}
- %(place holder)선택자를 사용하는 이유
- @extend로 쓰는 것인지 아닌지에 대한 사용 여부를 구분하기 위함
- 다른 선택자(class, id 등)와 구분하여 사용하기 때문에 의도하지 않거나 예상하기 힘든 코드를 만들어 내는 일을 최소화
- sass-lang.com의 Placeholder Selectors: %foo 상세페이지
%foo {
}
.bar {
@extend %foo;
}
.foo {
}
.bar {
@extend .foo;
}
기본 extend 문법
%layout {
border: 1px solid #ccc;
padding: 10px;
color: #333;
}
.success {
@extend %layout;
border-color: green;
}
.error {
@extend %layout;
border-color: red;
}
.warning {
@extend %layout;
border-color: yellow;
}
.success, .error, .warning {
border: 1px solid #cccccc;
padding: 10px;
color: #333;
}
.success {
border-color: green;
}
.error {
border-color: red;
}
.warning {
border-color: yellow;
}
주의사항
@media
와는 제대로 작동하지 않는다.
Sass 는 미디어 쿼리 안에서 외부의 선택자를 확장할 수 없다.
예시 :
.foo {
content: 'foo';
}
@media print {
.bar {
@extend .foo;
// !충돌. 컴파일러는 할 수 없는 일이라고 에러메세지를 출력한다.
// 에러메세지
// You may not @extend an outer selector from within @media.
// => @media 안에서 외부의 선택자를 @extend할 수 없다.
// You may only @extend selectors within the same directive.
// => 같은 지시어 안에 있는 선택자만 @extend할 수 있다.
}
}
10.1. %(place holder) 의 확장
- 규칙 세트 확장 가능
- 확장 시 고려사항
- 다른 모듈들에 걸치지 않게, 한 모듈 안에서 확장을 사용
- 오로지 % 에만 확장을 사용하고, 실제 선택자(class, id??)에는 사용X
- 확장하는 %가 가능한 한 적게 존재하도록 사용
HTML에 존재하지 않는 불필요한 선택자가 CSS에 출력되지 않도록 주의
예시 :
%foo {
//@extend안에 @include 가능
@include bar;
.baz {
width: 100px;
}
}
10.2. % 선언시, 축약형 지양
좋은 예 :
%sp_enter {
background-image: url($path-img + "sp_enter_10.png");
background-repeat: no-repeat;
background-position: -999px -999px;
}
나쁜 예 :
%sp_enter {
background: url($path-img + "sp_enter_10.png") no-repeat -999px -999px
}
11. 제어구문 (@if, @each, @for 등) [Control Statements]
- 시작 중괄호 : 문장과 같은 줄에 선언
- 닫는 중괄호 : 끝 빈줄에 선언
- 제어구문 다양한 예제보기
11.1. @if
예시 :
@if $foo{
...
}
@ else 와 @ else if : 이전 문장의 닫는 괄호와 같은 줄에 기술한다.
$type: monster;
p {
@if $type == ocean {
color: blue;
} @else if $type == matador {
color: red;
} @else if $type == monster {
color: green;
} @else {
color: black;
}
}
p {
color: green;
}
@if 기타 활용예시
@mixin foo($_imgsize, $_position: relative) {
@if $_position != absolute{
display: block;
}
position: $_position;
width: $_imgsize;
...
}
11.2. @each
- @each 반복문은 Sass가 제공하는 세 가지 반복문들 중에서 가장 많이 사용될 수 있다.
활용 예1 :
@each $animal in puma, sea-slug, egret, salamander {
.#{$animal}-icon {
background-image: url('/images/#{$animal}.png');
}
}
.puma-icon {
background-image: url('/images/puma.png');
}
.sea-slug-icon {
background-image: url('/images/sea-slug.png');
}
.egret-icon {
background-image: url('/images/egret.png');
}
.salamander-icon {
background-image: url('/images/salamander.png');
}
활용 예2 :
$map: (
key: #aaa,
value: #bbb
)
@each $key, $value in $map {
.section-#{$key} {
background-color: $value;
}
}
section-key {
background-color: #aaa;
}
.section-value {
background-color: #bbb;
}
...
활용 예3 :
.foo {
$_num: 0;
@each $name , $color in $menu {
.#{$name} &{
background-color: #{$color};
}
$_num: $_num + 1;
}
...
}
11.3. @for
@for
반복문은 CSS의 :nth-*
가상 클래스와 결합되었을 때 유용할 수 있다.
@for $i from 1 through 10 {
.foo:nth-of-type(#{$i}) {
border-color: hsl($i * 36, 50%, 50%);
}
}
.foo:nth-of-type(1) {
border-color: #bf8c40;
}
.foo:nth-of-type(2) {
border-color: #a6bf40;
}
.foo:nth-of-type(3) {
border-color: #59bf40;
}
...
@for 기타 활용예시 :
@for $i from 0 through 3 {
.no#{$i} {
background-position: -(15+12*$i)+px -200px
}
}
.no0 {
background-position: -15px -200px;
}
.no1 {
background-position: -27px -200px;
}
.no2 {
background-position: -39px -200px;
}
.no3 {
background-position: -51px -200px;
}
11.4. @while
@while
반복문은 내부에서 반복문을 중단시킬 방법이 없기 때문에 실제 Sass 프로젝트에서 사용할 일은 거의 없다.
12. 연산자 [Operators]
- 연산이 필요할 때는 변수를 활용한다.
- 연산이 필요한 숫자는 단위를 써준다. ex) px, em 등
- 한글주석을 기제하여 연산식을 알기 쉽게 사용한다.
@mixin halfHeight($height) {
position: absolute;
top: 50%;
height: $height; // 높이값
margin-top: - $height / 2; // 높이값의 반
}
.tit {
@include halfHeight(100px);
}
.tit {
position: absolute;
top: 50%;
height: 100px;
margin-top: -50px;
}
연산시 단위가 붙는 경우, 붙지 않는 경우
div {
// 연산시 1개이상의 값에 단위가 포함되어야 결과값에 단위가 자동으로 붙게 됩니다.
width: 100px + 10; // 110px
width: 100 + 10px; // 110px
width: 100px + 10px; // 110px
width: (100 + 10) * 1px; // 110px
width: 100 + 10; // 110
}