CSS 코드를 깔끔하고 효율적으로 작성하는 것은 웹 개발에서 중요한 부분을 차지합니다. 여기 몇 가지 기본적인 규칙들을 정리해 보았습니다.
1. 기본 규칙
- 들여쓰기는 2개의 공백 문자(소프트탭)을 사용하세요: 이는 코드를 더 읽기 쉽게 만듭니다. 만약 다른 규칙을 사용한다면, 그 규칙에 따라 일관성 있게 작성하는 것이 중요합니다.
- 프로퍼티는 한 줄에 하나씩 작성하세요: 이 방식 역시 코드의 가독성을 높여줍니다. 프로퍼티를 작성할 때에는 다른 규칙으로 통일하여 작성해도 괜찮습니다. 또한 프로퍼티는 영문 소문자로 작성하는 것이 좋습니다. 이는 일반적인 규칙으로 널리 받아들여지고 있는 규칙입니다.
- 가능한 따옴표를 생략하세요: 가능한 한 따옴표를 생략하는 것이 가장 좋습니다. 따옴표를 사용해야 하는 경우, 일반적으로 작은 따옴표(‘)를 사용하는 것이 좋고, @charset 선언과 타입 선택자에는 큰 따옴표(“)를 사용해야 합니다.
이런 기본 규칙들을 따르면, CSS 코드를 더 깔끔하고 효율적으로 관리할 수 있습니다. 코드의 가독성과 유지 보수성을 높이는 것은 웹 개발의 중요한 부분이므로, 이러한 규칙들을 잘 숙지하고 적용해 보시기 바랍니다.
2. Charset
웹 페이지나 문서를 작성할 때, 문자 인코딩은 매우 중요한 부분입니다. 여기에 해당하는 간단하지만 중요한 규칙이 있습니다.
문서의 언어셋은 UTF-8로 최상위에 선언하세요. 이는 국제적으로 가장 널리 사용되는 인코딩 방식이며, 다양한 언어와 특수 문자를 지원합니다. 이 규칙은 웹 페이지가 다양한 언어의 텍스트를 정확하게 표시할 수 있도록 보장합니다.
다음은 언어셋을 선언하는 방법입니다:
@charset "UTF-8";
만약 문서가 이미 언어셋이 정해진 번들링 파일로 제공된다면, 별도로 선언할 필요가 없습니다. 이는 파일이 이미 적절한 인코딩을 가지고 있다는 것을 의미합니다.
UTF-8 인코딩을 사용함으로써, 웹 개발자는 전 세계 사용자들이 자신의 웹 사이트나 애플리케이션을 원활하게 이용할 수 있도록 할 수 있습니다. 이는 국제적인 웹 표준을 따르면서, 사용자 경험을 크게 향상시키는 방법 중 하나입니다.
3. Selectors
CSS 선택자를 사용할 때는 몇 가지 중요한 점을 기억해야 합니다. 이러한 원칙들은 깔끔하고 효율적인 스타일 시트를 작성하는 데 도움이 됩니다.
- 선택자는 가급적 중첩하지 마세요: 선택자의 중첩을 최소화함으로써, 나중에 추가적인 코드가 필요한 경우를 줄일 수 있습니다. 이는 또한 구성 요소의 명확성을 강화하고, 스타일의 영향 범위를 제한하는 데 도움이 됩니다.
- 렌더링 성능 최적화를 위해 클래스, 가상 선택자 외의 선택자는 사용을 피하세요: 너무 복잡한 선택자는 렌더링 성능에 부정적인 영향을 줄 수 있습니다.
- 너무 많은 캐스케이딩 스타일을 가진 시스템을 구축하는 것은 해로울 수 있습니다: 이는 코드의 복잡성을 증가시키고, 유지보수를 어렵게 만들 수 있습니다.
다음은 나쁜 예와 좋은 예를 보여주는 예시입니다:
<div class="modal"> <div class="modal-header"> <h3>모달 제목</h3> </div> <div class="modal-body"> <h3>모달 부제목</h3> <p>모달에 대한 내용, 추가 텍스트 및 폼 등이 여기에 들어갑니다.</p> </div> <div class="modal-footer"> <button class="btn">완료</button> </div> </div>
/* Bad */ .modal h3 { text-align: center; } .modal .modal-header h3 { text-align: left; } /* Good */ .modal-header h3 { text-align: center; }
4. z-index
CSS에서 z-index
를 관리하는 방법은 웹 페이지의 다양한 요소들 사이의 시각적 계층을 결정하는 데 중요한 역할을 합니다. 잘 관리되지 않은 z-index
값은 요소들의 렌더링 순서를 혼란스럽게 만들 수 있습니다. 따라서, z-index
를 체계적으로 관리하는 것이 중요한데, 여기에 몇 가지 팁과 방법을 소개합니다.
CSS 전처리기의 믹스인을 활용하여 z-index
스택을 체계적으로 관리할 수 있습니다. 이 방법을 통해 코드를 간결하게 유지하면서도, 필요한 z-index
값을 쉽게 조정할 수 있습니다.
참고로, SCSS에서는 다음과 같이 사용할 수 있습니다:
// 이 코드는 .foo 클래스에 z-index: 203000을 적용합니다. .foo { position: absolute; @include layer-index('floating', 3000); }
다음은 z-index
를 활용하여 구분할 수 있는 엘리먼트 층의 예시입니다.
- 1. Normal
- 평범한 엘리먼트입니다.
- Value: -1 ~ 99999
- 2. Inline-popover
- 마우스 오버 또는 클릭 등의 이벤트로 특정 상황에서 상위에 노출되어야 하는 엘리먼트입니다.
- Preset Value: 10 ~ 19
- Value Range: 1000000 ~ 1999999
- 3. Floating
- 플로팅 레이어는 항상 상위에 떠있어야 하기 때문에, Inline-popover 보다 높은 범위를 적용합니다.
- Preset Value: 20 ~ 29
- Value: 2000000 ~ 2999999
- 4. Dialog
- 다이얼로그는 본문보다 위에 노출되어야 하기 때문에, Floating 보다 높은 범위를 적용합니다.
- Preset Value: 30 ~ 39
- Value: 3000000 ~ 3999999
- 5. Popover
- 이벤트 트리거링으로 상위에 노출되어야 하는 엘리먼트 층으로,
position: fixed;
이거나<body>
의 자식으로 존재하는 경우 사용합니다. - Preset Value: 40 ~ 49
- Value: 4000000 ~ 4999999
- 6. Toast
- 토스트는 사용자가 확인할 수 있도록 항상 페이지의 최상위에 노출되어야 하는 엘리먼트입니다.
- Preset Value: 50 ~ 59
- Value: 5000000 ~ 5999999
- 7. Super
- 무조건 최상위에 노출되어야 하는 엘리먼트 층으로, 정말 필요할 때만 사용하는 특수 레이어 층입니다.
- Preset Value: 60 ~ 69
- Value: 6000000 ~ 6999999
- 8. Skip
- 스킵 네비게이션은 어디서든 접근 가능해야 하므로 다른 레이어에 절대 가려지지 않아야 합니다.
- Preset Value: 70 ~ 79
- Value: 7000000 ~ 7999999
이런 분류는 요소들의 시각적 계층을 명확히 구분하는 데 도움이 되며, 각 요소의 특성에 맞는 z-index
값을 할당함으로써, 웹 페이지의 시각적 구성을 보다 효과적으로 관리할 수 있습니다. 이 방법을 통해, 요소들 사이의 상호작용을 명확하게 하고, 사용자 경험을 개선할 수 있습니다.
5. Import
CSS에서 스타일시트를 로드하는 방법은 웹 페이지의 로딩 속도와 직접적으로 연관이 있습니다. CSS의
다음은 CSS를 효율적으로 로드하는 몇 가지 권장되는 방법입니다:
- 여러 개의 <link> 엘리먼트로 작성하기: 이 방식은 각 스타일시트가 병렬로 로드되게 하여 로딩 시간을 단축할 수 있습니다.
- 하나의 CSS 파일로 작성하기: 모든 스타일시트를 하나의 파일로 병합하여 요청 수를 줄이는 것이 좋습니다. 이는 서버와 클라이언트 간의 통신 부담을 줄여줍니다.
- CSS 전처리기의 import 문법 사용하기: CSS 전처리기를 사용하면, 개발 시에는 여러 파일로 작업할 수 있지만, 최종적으로는 하나의 파일로 병합하여 배포할 수 있습니다.
- 번들러 등의 도구를 이용하여 하나의 CSS 파일로 병합하기: 웹팩이나 걸프 같은 도구를 사용하여 개발 과정에서 여러 CSS 파일을 하나로 병합할 수 있습니다.
Bad Case
<!-- Too Bad --> <style> @import url("style1.css"); @import url("style2.css"); @import url("style3.css"); </style>
Good Case
<!-- Good --> <!-- 각 파일이 병렬로 로드되어 성능이 개선됩니다. --> <link rel="stylesheet" href="style1.css"> <link rel="stylesheet" href="style2.css"> <link rel="stylesheet" href="style3.css"> <!-- Very Nice --> <!-- 모든 CSS를 하나의 요청으로 로드하여 성능을 최적화합니다. --> <link rel="stylesheet" href="bundle.css">
스타일시트를 효율적으로 관리하고 로드하는 것은 웹 사이트의 성능을 크게 향상시킬 수 있습니다. 가능한 방법을 적절히 활용하여 사용자의 웹 사이트 경험을 개선해 보시기 바랍니다.
6. Media Query
미디어 쿼리를 사용하는 것은 웹사이트의 반응형 디자인을 구현하는 데 중요한 역할을 합니다. 다음은 미디어 쿼리를 효과적으로 관리하는 방법에 대한 몇 가지 권장 사항입니다.
미디어 쿼리는 컴포넌트 단위로 분류하여 관련 규칙 바로 뒤에 작성하세요. 이 방법을 사용하면, 관련 스타일 규칙이 한 곳에 모이게 되어, 코드의 가독성이 크게 향상됩니다. 이는 개발자가 각 컴포넌트의 스타일을 더 쉽게 찾고 이해할 수 있게 해줍니다.
예를 들어, .foo-a
와 .foo-b
클래스에 대한 스타일이 있고, 이들에 대한 미디어 쿼리 규칙을 추가하려고 한다면, 각 컴포넌트의 스타일 정의 바로 뒤에 미디어 쿼리를 위치시키는 것이 좋습니다:
.foo-a {} .foo-b {} @media (min-width: 768px) { .foo-a {} .foo-b {} } .bar {}
만약 이 방법이 어렵거나, 특정 사정으로 불가능하다면, 문서의 마지막에 모든 미디어 쿼리를 모아서 작성하는 것도 하나의 방법입니다. 이렇게 하면 모든 반응형 디자인 관련 스타일이 한 곳에 모이게 되어, 관리하기가 더 용이해집니다.
.foo-a {} .foo-b {} .bar {} @media (min-width: 768px) { .foo-a {} .foo-b {} }
이러한 접근 방식은 미디어 쿼리를 활용하여 웹사이트의 반응형 디자인을 더 효과적으로 구현할 수 있도록 도와주는 방법으로, 코드의 구조를 명확하게 하고, 관리를 용이하게 하는 것은 웹 개발에서 매우 중요한 요소입니다. 이를 통해 웹사이트의 유지보수가 용이해지고, 다양한 화면 크기와 디바이스에 대응하는 능력이 향상될 수 있습니다.
7. Nesting
중첩은 매우 유용하지만, 이를 사용함에 있어 주의가 필요합니다. 너무 많은 선택자의 중첩은 피해야 하는데, 이는 코드의 복잡성을 증가시키고, 컴파일된 CSS가 비효율적이고 관리하기 어려운 형태로 변할 수 있기 때문입니다. 선택자의 중첩을 피하는 것은 코드의 가독성과 유지보수성을 높이는 데 중요한 역할을 합니다.
다음은 선택자 중첩의 나쁜 예와 좋은 예를 보여줍니다:
/* Bad */ .foo.bar { color: #abc; } /* Good */ .foo__bar { color: #abc; }
이 예에서는 BEM(Block, Element, Modifier) 방법론과 같은 명명 규칙을 사용하여 .foo
와 .bar
를 하나의 클래스로 결합했습니다. 이 방법은 중첩을 피하면서도, 관련 요소 간의 관계를 명확하게 표현할 수 있게 해줍니다.
8. Reset
CSS를 작성할 때 초기화 스타일의 설정은 웹 개발의 기본이지만 중요한 단계입니다. 초기화 스타일은 브라우저 간의 일관성을 유지하고, 예상치 못한 스타일링 문제를 방지하기 위해 사용됩니다. 그러나 초기화 방법을 선택할 때는 몇 가지 고려해야 할 사항이 있습니다.
- 초기화 스타일은 서비스에 맞게 정의하세요: 이는 각 프로젝트의 요구 사항과 사용되는 기술 스택에 따라 달라질 수 있으며, 가장 적합한 초기화 방식을 선택하는 것이 중요합니다. 예를 들어, 사이트의 디자인이 복잡하고 많은 커스텀 스타일을 포함한다면, 더 세밀한 초기화가 필요할 수 있습니다.
- normalize.css 또는 Bootstrap 등의 프레임워크를 사용한다면 초기화를 생략하세요: 이러한 프레임워크들은 이미 일반적인 초기화 스타일을 포함하고 있어서 별도로 초기화 스타일을 정의할 필요가 없습니다.
초기화 스타일은 웹 개발의 첫걸음으로, 일관된 스타일링과 예상 가능한 레이아웃을 보장하는 데 필수적입니다. 프로젝트를 시작하기 전에 적절한 초기화를 선택하고 적용하는 것이 중요합니다.
9. Vendor Prefix
CSS를 작성할 때, 벤더 프리픽스를 사용하는 것은 브라우저 호환성을 확보하기 위한 중요한 방법으로, 이 프리픽스들은 특정 브라우저에서만 사용되는 CSS 속성에 대해, 그 속성이 완전히 표준화되기 전에 실험적으로 사용될 수 있게 해줍니다. 그렇지만 이를 사용함에 있어서 주의해야 할 부분도 있습니다.
벤더 프리픽스 프로퍼티는 일반 프로퍼티보다 먼저 선언해야 합니다. 이 규칙은 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); }
예시와 같이 -webkit-box-shadow가 먼저 선언되고, 이어서 표준 box-shadow 속성이 선언되어야 합니다. 이런 구조는 브라우저가 표준 속성을 우선적으로 사용하도록 하며, 필요한 경우에만 벤더 프리픽스를 활용하게 하는 방법으로, 웹 사이트가 다양한 환경에서 일관된 사용자 경험을 제공할 수 있도록 할 수 있습니다.
10. Naming
CSS에서 네이밍 규칙을 잘 정의하고 사용하는 것은 프로젝트의 유지보수성, 확장성, 그리고 가독성을 크게 향상시킬 수 있습니다. 이와 관련하여, BEM(Block, Element, Modifier)과 ITCSS(Inverted Triangle CSS)를 결합한 BEMIT 방법론은 강력한 네이밍 전략이 될 수 있습니다.
다음은 강력한 네이밍 전략을 위한 몇 가지 유의사항입니다:
- 스타일 제어를 위해 아이디 선택자의 사용을 피하세요: 아이디 선택자는 스펙이피시티(specificity) 문제를 야기할 수 있으며, 재사용성이 떨어집니다.
- 클래스명은 반드시 엘리먼트의 의미를 전부 담아서 네이밍하세요: 이는 해당 클래스가 어떤 목적을 가지고 있는지 명확하게 표현해야 함을 의미합니다.
- 클래스명은 페이지에 상속받지 않으며, 디자인보다는 구조, 기능, 목적을 나타내는 이름으로 네이밍해야 합니다.: 이는 클래스명을 통해 해당 스타일의 목적이나 역할을 쉽게 이해할 수 있도록 돕습니다.
BEM 네이밍 규칙
BEM 방법론에 따른 기본 네이밍 규칙은 다음과 같습니다:
- Syntax: <BLOCK>[__<ELEMENT>][–<MODIFIER>][.is|has-<STATE>]
- BLOCK: 독립적인 구성요소를 나타냅니다.
- ELEMENT: BLOCK 내부의 구성요소를 나타냅니다.(__, Double Underbar를 사용하여 BLOCK과 연결)
- MODIFIER: BLOCK 또는 ELEMENT의 변형을 나타냅니다. (–, Double Hyphen을 사용하여 연결)
- STATE: 상태 클래스는 modifier에서 분리하여 따로 관리합니다. (.is- 또는 .has-를 사용하여 상태를 표현)
예를 들어, 다음과 같은 HTML 구조와 CSS 네이밍을 구성할 수 있습니다:
<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>
여기서 사용된 클래스명은 다음과 같은 구조를 가집니다:
.widget
는 BLOCK을 나타냅니다..widget__wrapper
는 BLOCK 내부의 ELEMENT를 나타냅니다..widget__wrapper--dark
는 ELEMENT의 MODIFIER를 나타냅니다..btn.is-disabled
는 BLOCK의 STATE를 나타냅니다..btn--submit
은 BLOCK의 다른 MODIFIER를 나타냅니다..btn--submit.is-disabled
는 MODIFIER가 특정 STATE에 있는 BLOCK을 나타냅니다.
이렇게 BEMIT 방법론을 적용함으로써, CSS 클래스의 의도와 구조를 명확하게 표현할 수 있습니다. 이 접근 방식은 코드의 재사용성과 유지보수성을 높이며, 대규모 프로젝트에서도 효과적인 스타일 관리를 가능하게 합니다.
참고 자료
- choegyumin, “markup-coding-conventions”
- Naver, “NHN Coding Convention”