CSS 사용자 정의 속성으로 응용 프로그램 색 구성표를 구성하는 방법

게시 됨: 2022-03-10
빠른 요약 ↬ 이 기사에서 Artur Basak은 응용 프로그램 색상에 응답하는 CSS 사용자 정의 속성을 설정하는 방법에 대한 현대적인 접근 방식을 소개합니다. 색상을 팔레트(또는 구성표), 기능 색상(또는 테마) 및 구성 요소 색상(로컬 범위)의 세 가지 수준으로 나누는 아이디어는 매우 유용할 수 있습니다.

변수는 프로젝트에서 색상을 구성하는 데 도움이 되는 기본 도구입니다. 오랫동안 프론트 엔드 엔지니어는 전처리기 변수를 사용하여 프로젝트의 색상을 구성했습니다. 그러나 이제 많은 개발자가 색상 변수를 구성하기 위한 최신 기본 메커니즘인 CSS 사용자 정의 속성을 선호합니다. 전처리기 변수에 비해 가장 중요한 이점은 프로젝트의 컴파일 단계가 아닌 실시간으로 작동하고 상속 및 값 재정의를 즉석에서 사용할 수 있는 캐스케이드 모델을 지원한다는 것입니다.

응용 프로그램 색 구성표를 구성하려고 할 때 항상 루트 섹션에 색과 관련된 모든 사용자 지정 속성을 배치하고 이름을 지정한 다음 필요한 모든 위치에서 사용할 수 있습니다.

Artur Basak의 Pen [Custom Properties for Colors](https://codepen.io/smashingmag/pen/RwaNqxW)를 참조하십시오.

Artur Basak의 색상에 대한 펜 사용자 정의 속성을 참조하십시오.

그것은 선택 사항이지만 응용 프로그램 테마, 화이트 라벨링, 브랜드 새로 고침 또는 밝은 모드 또는 어두운 모드 구성 문제를 해결하는 데 도움이 됩니까? 대비를 높이기 위해 색 구성표를 조정해야 하는 경우 어떻게 해야 합니까? 현재 접근 방식에서는 변수의 각 값을 업데이트해야 합니다.

이 기사에서는 이러한 많은 문제를 해결할 수 있는 사용자 지정 속성을 사용하여 색상 변수를 분할하는 방법에 대해 보다 유연하고 내성적인 접근 방식을 제안하고자 합니다.

점프 후 더! 아래에서 계속 읽기 ↓

색상 팔레트 설정

모든 웹사이트의 채색은 색 구성표의 설정으로 시작됩니다. 이러한 구성표는 색상환을 기반으로 합니다. 일반적으로 몇 가지 기본 색상만 팔레트의 기초를 형성하고 나머지는 파생 색상(톤 및 중간톤)입니다. 대부분의 경우 팔레트는 정적이며 웹 응용 프로그램이 실행되는 동안 변경되지 않습니다.

색 이론에 따르면 색 구성표에는 몇 가지 옵션만 있습니다.

  • 단색 구성표(원색 1개)
  • 보색 구성표(2가지 기본 색상)
  • 트라이어드 방식(삼원색)
  • Tetradic 방식(4가지 기본 색상)
  • 인접 패턴(2개 또는 3개의 기본 색상)

예를 들어 Paletton 서비스를 사용하여 트라이어드 색 구성표를 생성하겠습니다.

녹색, 파란색 및 빨간색의 변형: 확립된 삼중 체계가 있는 색상환.
Paletton 서비스: Triadic 색 구성표. (큰 미리보기)

이제 세 가지 주요 색상이 있습니다. 이를 기반으로 톤과 중간 톤을 계산합니다( calc 기능과 결합된 HSL 형식은 이를 위한 매우 유용한 도구입니다). 밝기 값을 변경하여 팔레트에 대해 몇 가지 추가 색상을 생성할 수 있습니다.

Artur Basak의 Pen [HSL Palette](https://codepen.io/smashingmag/pen/OJNPaQW)을 참조하십시오.

Artur Basak의 Pen HSL 팔레트를 참조하십시오.

이제 팔레트가 수정되면 기본 색상 값만 변경해야 합니다. 나머지는 자동으로 다시 계산됩니다.

HEX 또는 RGB 형식을 선호하는 경우 중요하지 않습니다. 팔레트는 전처리기의 해당 기능(예: SCSS 및 color-adjust 기능)으로 프로젝트를 컴파일하는 단계에서 형성될 수 있습니다. 이전에 언급했듯이 이 레이어는 대부분 정적입니다. 팔레트가 실행 중인 응용 프로그램에서 변경될 수 있는 경우는 극히 드뭅니다. 그렇기 때문에 전처리기로 계산할 수 있습니다.

참고 : 각 색상에 대해 HEX 리터럴과 RGB를 모두 생성하는 것이 좋습니다. 이렇게 하면 나중에 알파 채널을 사용할 수 있습니다.

Artur Basak의 Pen [SCSS Palette](https://codepen.io/smashingmag/pen/oNxgQqv)을 참조하십시오.

Artur Basak의 Pen SCSS 팔레트를 참조하십시오.

팔레트 수준은 색상이 변수 이름에 직접 인코딩되는 유일한 수준입니다. 즉, 이름을 읽어 색상을 고유하게 식별할 수 있습니다.

테마 또는 기능 색상 정의

팔레트가 완성되면 다음 단계는 기능적인 색상 의 수준입니다. 이 수준에서 색상의 가치는 목적, 수행하는 기능, 정확히 무엇을 색칠하는지만큼 중요하지 않습니다. 예를 들어 기본 또는 앱 브랜드 색상, 테두리 색상, 어두운 배경의 텍스트 색상, 밝은 배경의 텍스트 색상, 버튼 배경 색상, 링크 색상, 호버 링크 색상, 힌트 텍스트 색상 등 .

이것은 거의 모든 웹 사이트 또는 응용 프로그램에서 매우 일반적인 사항입니다. 이러한 색상은 응용 프로그램의 특정 색상 테마를 담당한다고 말할 수 있습니다. 또한 이러한 변수의 값은 팔레트에서 엄격하게 가져옵니다. 따라서 단순히 다른 색상 팔레트를 사용하여 응용 프로그램 테마를 쉽게 변경할 수 있습니다.

아래에서 버튼, 링크 및 입력 필드의 세 가지 일반적인 UI 컨트롤을 만들었습니다. 위에서 생성한 팔레트의 값을 포함하는 기능 변수를 사용하여 색상을 지정합니다. 애플리케이션 테마(조건부 브랜드)를 담당하는 주요 기능 변수는 기본 색상 변수입니다.

상단에 있는 세 개의 버튼을 사용하여 테마를 전환할 수 있습니다(컨트롤의 브랜드 색상 변경). 변경은 적절한 CSSOM API(setProperty)를 사용하여 발생합니다.

Artur Basak의 Pen [Functional Colors](https://codepen.io/smashingmag/pen/poyvQLL)를 참조하십시오.

Artur Basak의 펜 기능 색상을 참조하십시오.

이 접근 방식은 테마 지정뿐만 아니라 개별 웹 페이지 구성에도 편리합니다. 예를 들어, zubry.by 웹사이트에서 공통 스타일시트와 기능적 변수 --page-color 를 사용하여 모든 페이지의 로고, 제목, 컨트롤 및 텍스트 선택에 색상을 지정했습니다. 그리고 각 페이지의 고유한 스타일에서 이 변수를 재정의하여 페이지의 개별 기본 색상을 설정했습니다.

ZUBRY.BY 웹사이트의 3개 웹페이지: 우표 페이지, 엽서 페이지 및 카드 페이지.
각 페이지에 개별 기본 색상이 있는 ZUBRY.BY 웹사이트. (큰 미리보기)

구성 요소 색상 사용

대규모 웹 프로젝트에는 항상 분해가 포함됩니다. 우리는 모든 것을 작은 구성 요소로 나누고 여러 곳에서 재사용합니다. 각 구성 요소에는 일반적으로 고유한 스타일이 있습니다. 즉, BEM 또는 CSS 모듈을 분해하는 데 사용한 항목 또는 다른 접근 방식은 중요하지 않습니다. 이러한 각 코드 조각을 로컬 범위라고 하고 재사용할 수 있다는 것이 중요합니다.

일반적으로 두 가지 경우에 구성 요소 수준 에서 색상 변수를 사용하는 것이 포인트라고 봅니다.

첫 번째는 응용 프로그램 스타일 가이드에 따라 구성 요소가 다른 설정으로 반복되는 경우입니다(예: 기본(브랜드) 버튼, 보조 버튼, 삼차 등과 같은 다양한 요구에 대한 버튼).

Tispr 응용 프로그램에 대한 다양한 버튼 스타일.
Tispr 애플리케이션 스타일 가이드. 버튼. (큰 미리보기)

두 번째는 버튼 호버, 활성 및 포커스 상태와 같이 색상이 다른 여러 상태를 가진 구성 요소일 때입니다. 입력 또는 선택 필드에 대한 정상 및 유효하지 않은 상태 등.

구성 요소 변수가 유용할 수 있는 보다 드문 경우는 "화이트 라벨"의 기능입니다. "화이트 라벨"은 사용자가 사용자 인터페이스의 일부를 사용자 지정하거나 브랜드화하여 고객과의 상호 작용 경험을 개선할 수 있는 서비스 기능입니다. 예를 들어 사용자가 서비스 또는 이메일 템플릿을 통해 고객과 공유하는 전자 문서입니다. 이 경우 구성 요소 수준의 변수는 응용 프로그램의 나머지 색상 테마와 별도로 특정 구성 요소를 구성하는 데 도움이 됩니다.

아래 예에서 이제 기본(브랜드) 버튼의 색상을 사용자 정의하기 위한 컨트롤을 추가했습니다. 구성 요소 수준의 색상 변수를 사용하여 UI 컨트롤을 서로 별도로 구성할 수 있습니다.

Artur Basak의 Pen [Component Colors](https://codepen.io/smashingmag/pen/LYNEXdw)를 참조하십시오.

Artur Basak의 Pen Component Colors를 참조하십시오.

변수의 수준을 결정하는 방법은 무엇입니까?

루트(테마 또는 기능 수준)에 무엇을 넣을 수 있는지, 구성 요소 수준에서는 무엇을 남겨야 하는지 이해하는 방법에 대한 질문을 접했습니다. 이것은 당신이 일하는 상황을 보지 않고는 대답하기 어려운 훌륭한 질문입니다.

불행히도 프로그래밍에서와 같은 접근 방식은 색상과 스타일에서 작동하지 않습니다. 동일한 코드 조각이 세 개 보이면 리팩토링해야 합니다.

색상은 구성 요소에서 구성 요소로 반복될 수 있지만 이것이 규칙이라는 의미는 아닙니다. 이러한 구성 요소 간에는 관계가 있을 수 없습니다. 예를 들어, 입력 필드의 테두리와 기본 버튼의 배경. 예, 위의 예에서 그렇습니다. 그러나 다음 예를 확인해 보겠습니다.

Artur Basak의 Pen [Color Split: Only Palette](https://codepen.io/smashingmag/pen/YzqPRLX)를 참조하십시오.

Artur Basak의 Pen Color Split: Only Palette를 참조하십시오.

짙은 회색이 반복됩니다. 이것은 입력 필드의 테두리, 닫기 아이콘의 채우기 색상 및 보조 버튼의 배경입니다. 그러나 이러한 구성 요소는 서로 연결되어 있지 않습니다. 입력 필드의 테두리 색상이 변경되면 보조 버튼의 배경은 변경되지 않습니다. 이러한 경우 팔레트의 변수만 여기에 유지해야 합니다.

UI 컨트롤: 버튼, 링크, 헤드 및 일반 텍스트, 입력 필드
애플리케이션 스타일 가이드 예시. (큰 미리보기)

녹색은 어떻습니까? 기본 또는 브랜드 색상으로 명확하게 정의할 수 있습니다. 기본 버튼의 색상이 변경되면 첫 번째 수준의 링크 및 헤더 색상도 변경될 가능성이 큽니다.

빨간색은 어떻습니까? 입력 필드, 오류 메시지 및 파괴적인 버튼의 잘못된 상태는 전체 응용 프로그램 수준에서 동일한 색상을 갖습니다. 이것은 패턴입니다. 이제 루트 섹션에서 몇 가지 공통 기능 변수를 정의할 수 있습니다.

Artur Basak의 Pen [Color Split: Functional Level](https://codepen.io/smashingmag/pen/MWyYzGX)을 참조하십시오.

Artur Basak의 Pen Color Split: Functional Level을 참조하십시오.

구성 요소 색상의 수준과 관련하여 사용자 정의 속성을 사용하여 사용자 정의할 수 있는 구성 요소를 쉽게 식별할 수 있습니다.

버튼은 다른 설정으로 반복되며, 다른 사용 사례에 대한 배경색과 텍스트가 변경됩니다(기본, 이차, 삼차, 파괴적 또는 부정적인 경우).

입력 필드에는 배경과 테두리 색상이 다른 두 가지 상태(잘못됨 및 정상)가 있습니다. 따라서 이러한 설정을 해당 구성 요소 수준의 색상 변수에 넣습니다.

나머지 구성 요소의 경우 로컬 색상 변수를 정의할 필요가 없으며 이는 중복됩니다.

Artur Basak의 Pen [Color Split: Component Level](https://codepen.io/smashingmag/pen/BaKyGVR)을 참조하십시오.

Artur Basak의 Pen Color Split: Component Level을 참조하십시오.

디자인 팀과 UX에서 개발 중인 프로젝트의 패턴 언어에 대해 자세히 알아보아야 합니다. 엔지니어는 시각적 언어의 전체 개념을 완전히 이해해야만 공통적인 것과 기능적 수준에서 살아야 하는 것과 지역적 가시성 범위에 남아 있어야 하는 것을 결정할 수 있습니다.

그러나 모든 것이 그렇게 복잡하지 않고 분명한 것이 있습니다. 페이지의 일반적인 배경, 기본 텍스트의 배경 및 색상, 대부분의 경우 이것이 애플리케이션의 테마를 설정하는 것입니다. 특정 모드(예: 어둡거나 밝은 모드)의 구성을 담당하는 항목을 수집하는 것은 매우 편리합니다.

루트 섹션에 모든 것을 넣지 않는 이유는 무엇입니까?

나는 그런 경험이 있었다. Lition 프로젝트에서 우리 팀과 저는 웹 애플리케이션에 대해 IE11을 지원해야 하지만 웹사이트와 랜딩에 대해서는 지원하지 않아야 한다는 사실에 직면했습니다. 프로젝트 간에 공통 UI 키트가 사용되었으며 모든 변수를 루트에 두기로 결정했습니다. 이렇게 하면 모든 수준에서 변수를 재정의할 수 있습니다.

또한 웹 애플리케이션 및 IE11 사례에 대한 이러한 접근 방식을 사용하여 다음 포스트 프로세서 플러그인을 통해 코드를 전달하고 이러한 변수를 프로젝트의 모든 UI 구성 요소에 대한 리터럴로 변환했습니다. 이 트릭은 모든 변수가 루트 섹션에 정의된 경우에만 가능합니다. 포스트 프로세서가 캐스케이드 모델의 세부 사항을 이해할 수 없기 때문입니다.

브라우저 개발 도구가 열린 Lition 웹사이트의 메인 페이지
Lition SSR 웹사이트. 루트 섹션의 모든 변수. (큰 미리보기)

이제 나는 이것이 올바른 방법이 아니라는 것을 이해합니다. 첫째, 구성 요소 색상을 루트 섹션에 넣으면 관심사 분리 원칙을 깨는 것입니다. 결과적으로 스타일시트에 CSS가 중복될 수 있습니다. 예를 들어, 각 구성 요소에 고유한 스타일이 있는 구성 요소 폴더가 있습니다. 또한 루트 섹션에서 색상 변수를 설명하는 공통 스타일시트가 있습니다. 버튼 구성 요소를 제거하기로 결정했습니다. 이 경우 공통 스타일 파일에서 버튼과 관련된 변수도 제거해야 합니다.

둘째, 이것은 성능 면에서 최상의 솔루션이 아닙니다. 예, 색상 변경은 리플로우/레이아웃이 아닌 다시 그리기 프로세스만 발생합니다. 자체적으로 비용이 많이 들지는 않지만 최고 수준에서 일부 변경을 수행할 때 전체 트리를 확인하는 데 더 많은 리소스를 사용하게 됩니다. 변경 사항은 작은 지역에 있습니다. 자세한 내용은 Lisi Linhart에서 CSS 변수의 성능 벤치마크를 읽는 것이 좋습니다.

내 현재 프로젝트 Tispr에서 팀과 나는 split을 사용하고 루트에 있는 모든 것을 버리지 않고 상위 수준에서는 팔레트와 기능적 색상만 사용합니다. 또한 이 문제는 해당 폴리필로 해결되기 때문에 IE11을 두려워하지 않습니다. npm 모듈 ie11-custom-properties를 설치하고 라이브러리를 애플리케이션 JS 번들로 가져오기만 하면 됩니다.

 // Use ES6 syntax import "ie11-custom-properties"; // or CommonJS require('ie11-custom-properties');

또는 스크립트 태그로 모듈을 추가하십시오.

 <script async src="./node_modules/ie11-custom-properties/ie11CustomProperties.js">

또한 CDN을 통해 npm 없이 라이브러리를 추가할 수 있습니다. 이 폴리필의 작업은 IE11이 캐스케이드를 기반으로 속성을 정의하고 읽을 수 있는 사용자 정의 속성에 대한 지원을 최소화한다는 사실을 기반으로 합니다. 이는 이중 대시로 시작하는 속성에서는 불가능하지만 단일 대시(공급업체 접두사와 유사한 메커니즘)로 시작하는 것은 가능합니다. 저장소 문서에서 이에 대한 자세한 내용을 읽고 몇 가지 제한 사항에 대해 알아볼 수 있습니다. 다른 브라우저는 이 폴리필을 무시합니다.

아래는 Tispr 웹 애플리케이션의 팔레트와 전자 문서(예: 사용자 계약서, 송장 또는 제안서)에 대한 "화이트 라벨" 기능의 제어입니다.

색상, 색상 이름, 색상 HEX, 색상 RGB 열이 있는 그리드.
Tispr 스타일 가이드: 색상 팔레트. (큰 미리보기)
사용자 정의 색상 선택기 UI 구성요소
Tispr Styleguide: 화이트 라벨 기능을 위한 브랜드 선택기. (큰 미리보기)

JavaScript 측에 색상 변수를 저장하지 않는 이유는 무엇입니까?

또 다른 합리적인 질문: 팔레트와 함수 변수를 JavaScript 코드에 저장하지 않는 이유는 무엇입니까? 이것은 또한 인라인 스타일을 통해 동적으로 변경되고 나중에 색상을 재정의할 수 있습니다. 이것은 옵션일 수 있지만 특정 요소에 액세스하고 색상 속성을 변경해야 하기 때문에 이 접근 방식은 덜 최적일 가능성이 높습니다. CSS 변수를 사용하면 단일 속성, 즉 변수 값만 변경할 수 있습니다.

JavaScript에는 색상 작업을 위한 기본 함수나 API가 없습니다. CSS 색상 모듈 5에는 파생 색상을 만들거나 어떻게든 계산할 수 있는 많은 기회가 있습니다. 미래의 관점에서 CSS 사용자 정의 속성은 JS 변수보다 더 풍부하고 유연합니다. 또한 JS 변수를 사용하면 캐스케이드에서 상속을 사용할 가능성이 없으며 이것이 주요 단점입니다.

결론

색상을 세 가지 수준(팔레트, 기능 및 구성 요소)으로 분할하면 프로젝트 작업 중에 변경 사항과 새로운 요구 사항에 보다 잘 적응할 수 있습니다. CSS 사용자 정의 속성은 색상 분할을 구성하는 데 적합한 도구라고 생각합니다. 스타일 지정에 무엇을 사용하든 상관 없습니다. 순수 CSS, 전처리기 또는 CSS-in-JS 접근 방식입니다.

나는 내 자신의 경험을 통해 이 접근 방식에 도달했지만 혼자가 아닙니다. Sara Soueidan은 그녀의 기사에서 변수를 전역 및 구성 요소 수준으로 분할하는 유사한 접근 방식을 설명했습니다.

나는 또한 Lea Verou가 CSS 변수를 적용할 수 있는 가능한 사례를 설명하는 기사를 읽는 것을 제안하고 싶습니다(색상 측면 뿐만 아니라).