SCSS 스타일 가이드

유틸리티 클래스

사이트가 성장함에 따라 CSS의 생성량을 줄이기 위해, 새로운 CSS를 추가하는 대신 유틸리티 클래스를 사용하는 것을 권장합니다. 복잡한 경우에는 CSS를 처리하기 위해 컴포넌트 클래스를 추가할 수 있습니다.

CSS 유틸리티 클래스는 어디에 정의되어 있나요?

유틸리티 클래스는 Tailwind CSS에 의해 생성됩니다. 사용 가능한 CSS 유틸리티 클래스는 Tailwind CSS 자동완성이나 구성 뷰어를 사용하여 확인할 수 있습니다.

utilities.scsscommon.scss에 있는 클래스들은 곧 폐기될 예정입니다. 디자인 시스템 값이 아닌 common.scss의 클래스는 피해야 합니다. 대신, 일치하는 값을 가진 클래스를 사용하세요.

Bootstrap의 유틸리티 클래스는 피해야 합니다.

참고: Bootstrap의 유틸리티 클래스GitLab UI 유틸리티 클래스로 이관할 때, 여백과 안쪽 여백에 대한 클래스가 다른 점에 유의하세요. GitLab에서 사용하는 크기 척도는 Bootstrap 라이브러리에서 사용하는 척도와 다릅니다. Bootstrap의 패딩이나 여백 유틸리티의 경우, 동일한 시각적 결과를 얻으려면 적용한 유틸리티의 크기를 두 배로 해야 할 수도 있습니다(예: ml-1gl-ml-2가 됨).

Tailwind CSS

2024년 8월 현재, 우리는 Tailwind CSS를 CSS 유틸리티 제공자로 사용하고 있습니다. 이는 이전에 사용하던 사용자 지정 솔루션을 대체했습니다. 동기, 제안 및 구현에 대한 자세한 내용은 Tailwind CSS 설계 문서를 참조하세요.

Tailwind CSS 기본 사항

아래에서는 Tailwind CSS 기본 사항 및 파자마 디자인 시스템을 사용하도록 구성된 내용에 대해 설명합니다. 더 자세한 가이드는 공식 Tailwind CSS 문서를 참조하세요.

접두사

모든 유틸리티 클래스에 gl- 접두사를 사용하도록 Tailwind CSS를 구성했습니다. 반응형 유틸리티나 상태 수정자를 사용할 때는 접두사가 콜론 뒤에 옵니다.

예시: gl-mt-5, lg:gl-mt-5

반응형 CSS 유틸리티 클래스

반응형 CSS 유틸리티 클래스는 브레이크포인트 이름으로 접두사를 붙인 후 : 문자를 사용합니다. 사용 가능한 브레이크포인트는 tailwind.defaults.js#L44에서 구성되어 있습니다.

예시: lg:gl-mt-5

호버, 포커스 및 다른 상태 수정자

상태 수정자는 Tailwind CSS 클래스를 조건부로 적용할 수 있습니다. CSS 유틸리티 클래스 앞에 수정자의 이름을 접두사로 붙인 후 : 문자를 사용하세요.

예시: hover:gl-underline

!important 수정자

CSS 유틸리티 클래스의 시작에 !를 추가하여 중요한 수정자를 사용할 수 있습니다. 반응형 유틸리티 클래스나 상태 수정자와 함께 사용할 때는 !를 콜론 뒤에 붙입니다.

예시: !gl-mt-5, lg:!gl-mt-5, hover:!gl-underline

여백 및 크기 CSS 유틸리티 클래스

여백과 크기 CSS 유틸리티 클래스(예: margin, padding, width, height)는 src/tokens/build/tailwind/tokens.cjs에서 정의된 우리의 여백 척도를 사용합니다. 이는 공식 Tailwind CSS 문서에서 문서화된 네이밍 규칙을 따르지만 척도가 일치하지는 않습니다. Tailwind CSS 자동완성을 사용할 때, 구성된 여백 척도가 표시됩니다.

예시: gl-mt-5margin-top: 1rem;입니다.

색상 CSS 유틸리티 클래스

색상 CSS 유틸리티 클래스(예: colorbackground-color)는 src/tokens/build/tailwind/tokens.cjs에 정의된 색상을 사용합니다. 이는 공식 Tailwind CSS 문서에서 문서화된 네이밍 규칙을 따르지만 색상 이름이 일치하지 않습니다. Tailwind CSS 자동완성을 사용할 때, 구성된 색상이 표시됩니다.

예시: gl-text-red-500color: var(--red-500, #dd2b0e);입니다.

Tailwind CSS 번들 만들기

GitLab 개발 키트와 함께 Vite 또는 Webpack을 사용할 때, Tailwind CSS는 파일 변경을 감지하여 필요한 유틸리티를 실시간으로 빌드합니다.

새로운 Tailwind CSS 번들을 만들려면 yarn tailwindcss:build를 실행하세요. 이 스크립트는 bundle exec rake gitlab:assets:compile을 사용하여 프로덕션 자산을 빌드할 때 내부적으로 호출되는 스크립트입니다.

번들이 어떻게 만들어지든, 출력물은 app/assets/builds/tailwind.css에 저장됩니다.

Tailwind CSS 자동완성

Tailwind CSS 자동완성은 코드 편집기에서 사용 가능한 모든 클래스를 나열합니다.

VS Code

Tailwind CSS IntelliSense 확장을 설치하세요. HAML 및 사용자 정의 *-class 프로퍼티를 지원하기 위해 다음과 같은 권장 설정이 있습니다:

{
  "tailwindCSS.experimental.classRegex": [
    ["class: [\"|']+([^\"|']*)[\"|']+", "([a-zA-Z0-9\\-:!/]+)"],
    ["(\\.[\\w\\-.]+)[\\n\\=\\{\\s]", "([\\w\\-]+)"],
    ["[a-z]+-class(?:es)?=\"([^'\"]*)\""]
  ],
  "tailwindCSS.emmetCompletions": true
}
RubyMine

Tailwind CSS 자동완성은 기본적으로 활성화되어 있습니다. HAML 및 사용자 정의 *-class 프로퍼티를 완전히 지원하기 위해 기본 설정을 다음과 같이 업데이트하는 것이 권장됩니다:

{
  "includeLanguages": {
    "haml": "html"
  },
  "emmetCompletions": true,
  "experimental": {
    "classRegex": [
      ["class: [\"|']+([^\"|']*)[\"|']+", "([a-zA-Z0-9\\-:!/]+)"],
      ["(\\.[\\w\\-.]+)[\\n\\=\\{\\s]", "([\\w\\-]+)"],
      ["[a-z]+-class(?:es)?=\"([^'\"]*)\""]
    ]
  }
}

Config viewer

GitLab은 자체 Tailwind CSS 구성을 tailwind.defaults.js에서 정의하고 Pajamas 디자인 시스템과 일치하도록 CSS 유틸리티 클래스에 gl- 접두사를 추가합니다. 따라서 공식 Tailwind CSS 문서에서는 간격, 크기 및 색상 CSS 유틸리티 클래스가 일치하지 않을 수 있습니다. 또한 gl- 접두사는 표시되지 않습니다. 우리는 Tailwind Config Viewer의 인스턴스를 호스팅하고 있으며, 이를 통해 구성에서 커스터마이즈한 내용에 대한 개요를 제공합니다. 어쨌든, Tailwind CSS 유틸리티에 대한 자동완성을 얻으려면 IDE를 설정하는 것을 권장합니다. 이렇게 하면 최신 및 포괄적인 데이터 소스를 활용할 수 있으므로 궁극적으로 좋은 영향을 미칩니다.

새 유틸리티 클래스는 어디에 넣어야 하는가?

유틸리티 클래스는 대부분의 CSS 기능을 지원하는 Tailwind CSS에서 생성됩니다. 만약 사용할 수 없는 것이 있다면, 우리는 GitLab UI의 tailwind.defaults.js를 업데이트해야 합니다.

컴포넌트 클래스를 만드는 시점은 언제인가?

“유틸리티 우선” 접근 방식을 권장합니다. 1. 유틸리티 클래스부터 시작합니다. 1. 유틸리티 클래스를 컴포넌트 클래스로 결합하여 코드 중복을 제거하고 명확한 책임을 캡슐화할 수 있다면 그렇게 하세요.

이렇게 하면 컴포넌트 클래스가 유기적으로 성장하고 일회성으로 재사용할 수 없는 클래스가 생성되는 것을 방지합니다. 또한 “유틸리티 우선”에서 나오는 클래스 유형은 주로 디자인 중심(예: .button, .alert, .card)이며 도메인 중심(예: .security-report-widget, .commit-header-icon)보다 좋습니다.

영감:

HTML 및 스타일시트에서 Tailwind CSS 활용

컴포넌트 클래스를 작성할 때, Tailwind CSS의 유틸리티 클래스를 효과적으로 통합하여 디자인 시스템과 일관성을 유지하고 CSS 번들을 작게 유지하는 것이 중요합니다.

HTML에서 유틸리티 CSS 클래스와 스타일시트에서의 유틸리티 CSS 클래스 비교:

HTML에서 유틸리티 클래스를 직접 사용함으로써 CSS 파일 크기를 작게 유지하고 유틸리티 우선 철학을 따를 수 있습니다. 유틸리티 클래스와 사용자 정의 스타일을 하나의 컴포넌트 클래스에 합치는 것을 피함으로써 혼란과 잠재적인 충돌을 방지할 수 있습니다.

  • 선호하는 접근 방식에 대한 이유:
    • 더 작은 CSS 파일 크기: 직접적으로 유틸리티 클래스를 활용함으로써 더 작은 CSS 파일이 생성되고 더 일관된 디자인 시스템이 유도됩니다.
    • 명확성과 유지보수성: HTML에서 유틸리티 클래스를 사용하면 어떻게 스타일이 적용되는지 명확해지며 충돌 및 회귀의 위험을 줄일 수 있습니다.
  • 스타일 결합의 잠재적인 문제점:
    • 충돌: 유틸리티 클래스와 사용자 정의 스타일을 하나의 클래스에 결합하면 특히 스타일이 상호 의존적인 경우 충돌이 발생할 수 있습니다.
    • 회귀: 스타일이 어떻게 해결되어야 하는지 명확하지 않아지며 잠재적인 회귀나 예상치 못한 동작이 발생할 수 있습니다.

이러한 지침을 따르면 Tailwind CSS를 효과적으로 활용한 깨끗하고 유지보수 가능한 스타일시트를 만들 수 있습니다.

1. HTML에서 유틸리티 클래스 직접 사용 (선호하는 접근 방식)

유틸리티 우선 원칙을 따르고 유지보수성을 높이기 위해 HTML 요소에 유틸리티 클래스를 직접 추가하세요. 컴포넌트 클래스는 주로 유틸리티가 아닌 CSS 스타일만 포함해야 합니다. 다음 예제에서 SCSS 파일에 position: fixed; right: 0; left: 0;를 추가하는 대신, gl-fixedgl-inset-x-0 유틸리티 클래스를 추가하세요:

<!-- 나쁜 예 -->
<div class="my-class"></div>

<style>
  .my-class {
    top: $header-height;
    z-index: 999;
    position: fixed;
    left: 0px;
    right: 0px;
 }
</style>

<!-- 좋은 예 -->
<div class="my-class gl-fixed gl-inset-x-0"></div>

<style>
  .my-class {
    top: $header-height;
    z-index: 999;
  }
</style>

2. 컴포넌트 클래스에서 유틸리티 클래스 적용 (필요한 경우)

HTML에서 유틸리티 클래스를 직접적으로 사용할 수 없을 때, 사용자 정의 SCSS 파일에 포함해야 하는 경우가 있습니다. 이럴 때, 디자인 시스템에서 스타일 정의를 상속받고 불필요한 속성이나 값에 대한 정보를 파악하지 않아도 되도록, Tailwind CSS의 @apply 지시어를 사용할 수 있습니다.

@apply를 사용하는 것은 CSS 속성(예: margin, padding)을 적용하기 위해 _권장_됩니다. 단위가 없는 CSS 속성(예: display: flex)은 직접적으로 사용해도 괜찮습니다.

// 나쁜 예
.my-class {
  margin-top: 0.5rem;
}

// 괜찮은 예
.my-class {
  display: flex;
}

// 좋은 예
.my-class {
  @apply gl-mt-5 gl-flex;
}

네이밍

파일 이름은 snake_case를 사용해야 합니다.

CSS 클래스는 snake_casecamelCase 대신 lowercase-hyphenated 형식을 사용해야 합니다.

// 나쁨
.class_name {
  color: #fff;
}

// 나쁨
.className {
  color: #fff;
}

// 좋음
.class-name {
  color: #fff;
}

SCSS의 & 기능을 사용하여 복합 클래스 이름을 만드는 것을 피하세요. 이는 사용 사례를 찾기 어렵게 만들며 제한된 이점을 제공합니다.

// 나쁨
.class {
  &-name {
    color: orange;
  }
}

// 좋음
.class-name {
  color: #fff;
}

태그 이름 셀렉터 대신 클래스 이름을 사용해야 합니다. 태그 이름 셀렉터는 의도하지 않은 하위 요소에 영향을 줄 수 있기 때문에 권장되지 않습니다.

// 나쁨
ul {
  color: #fff;
}

// 좋음
.class-name {
  color: #fff;
}

// Best
// 기존 유틸리티 클래스를 추가하는 대신 기존 스타일을 사용하세요

클래스 이름은 ID보다 선호됩니다. ID를 사용하는 규칙은 재사용이 불가능합니다. 페이지에서 영향을 받는 요소는 하나뿐이기 때문입니다.

// 나쁨
#my-element {
  padding: 0;
}

// 좋음
.my-element {
  padding: 0;
}

중첩

불필요한 중첩을 피하세요. 래퍼 컴포넌트의 추가적인 명시성은 오버라이드를 어렵게 만듭니다.

// 나쁨
.component-container {
  .component-header {
    /* ... */
  }

  .component-body {
    /* ... */
  }
}

// 좋음
.component-container {
  /* ... */
}

.component-header {
  /* ... */
}

.component-body {
  /* ... */
}

js- 접두어가 있는 셀렉터

스타일링 목적으로 js-로 접두어가 있는 셀렉터를 사용하지 마세요. 이러한 셀렉터는 JavaScript에서만 사용되도록 의도되었으며, 제거하거나 이름을 바꾸어도 스타일이 깨지지 않도록 합니다.

Util CSS 클래스가 있는 셀렉터

스타일시트에서 유틸리티 CSS 클래스를 셀렉터로 사용하지 마세요. 이러한 클래스는 변경될 가능성이 높으며, 이에 따른 셀렉터의 업데이트를 요구하며 구현을 유지하기 어렵게 만듭니다. 대신, 기존의 다른 CSS 클래스를 사용하거나 새로운 사용자 정의 CSS 클래스를 추가하세요. 이 접근 방식은 유지 관리성을 향상시키고 버그의 위험을 줄입니다.

// ❌ 나쁨
.gl-mb-5 {
  /* ... */
}

// ✅ 좋음
.component-header {
  /* ... */
}

ARIA 속성과 함께하는 셀렉터

스타일링 목적으로 ARIA와 관련된 어트리뷰트 셀렉터를 사용하지 마세요. 이러한 어트리뷰트와 롤은 보조 기술을 지원하기 위해 의도되었습니다. ARIA로 주석이 지정된 컴포넌트의 구조가 변경될 수 있으므로 스타일도 변경될 수 있습니다. 스타일링이 깨지지 않고 이러한 롤과 어트리뷰트를 다른 요소로 옮길 수 있어야 합니다.

// 나쁨
&[aria-expanded=false] &-header {
  border-bottom: 0;
}

// 좋음
&.is-collapsed &-header {
  border-bottom: 0;
}

extend at-rule 사용

extend at-rule 사용은 메모리 누수올바르게 동작하지 않는 문제 때문에 금지됩니다.

린팅

우리는 스타일 가이드 규칙을 확인하기 위해 stylelint를 사용합니다. 이는 프로젝트의 홈 디렉토리에 있는 .stylelintrc우리의 SCSS 구성의 규칙을 사용합니다. .stylelintrc는 프로젝트의 홈 디렉토리에 있습니다.

귀하의 변경 사항으로 경고가 발생하는지 확인하려면 GitLab 디렉토리에서 yarn lint:stylelint를 실행하세요. 또한 Stylelint는 GitLab CI/CD에서 모든 경고를 잡습니다.

이해하지 못하는 경고가 Rake 작업을 발생시키는 경우, SCSS Lint의 문서에 있는 모든 규칙의 전체 목록을 참조하세요.