나는 최근 이 시리즈에서 공유한 많은 기술을 실행하면서 새로운 테마와 선구적인 캐릭터 그룹으로 내 웹 사이트의 애니메이션 그래픽을 새로 고쳤습니다. 내 애니메이션 중 일부는 누군가가 애니메이션과 상호 작용하거나 하루 중 다른 시간에 모양이 변경됩니다.

내 블로그 페이지 상단의 그래픽 색상은 매일 아침부터 밤까지 변경됩니다. 그런 다음 오버레이 레이어와 블렌딩 모드를 통해 차가운 ​​색상과 겨울 테마를 추가하는 눈 모드가 있습니다.

이 작업을 진행하면서 CSS 상대 색상 값을 통해 프로세스를 단순화하면서 더 많은 제어력을 얻을 수 있는지 궁금해지기 시작했습니다. 참고: 이 튜토리얼에서는 그래픽과 애니메이션 테마를 위한 상대 색상 값과 OKLCH 색상 공간에 중점을 둘 것입니다. 상대적 색상에 대해 자세히 알아보고 싶다면 Ahmad Shadeed가 훌륭한 대화형 가이드를 만들었습니다. 색 공간, 영역 및 OKLCH에 관해서는 Geoff Graham이 이에 대해 썼습니다.

요소를 반복적으로 사용하는 것이 핵심이었습니다. 동일한 아트워크에서 새로운 장면을 구성하는 데 도움이 되는 확대/축소 및 오버레이를 사용하여 가능할 때마다 배경을 재사용했습니다. 필요성에 의해 탄생했지만, 개별 장면보다는 시리즈적인 측면에서 사고를 장려하기도 했습니다. 색상 팔레트를 수동으로 업데이트할 때 발생하는 문제 바로 내 도전을 시작하겠습니다. 1959년 요기 베어 쇼(Yogi Bear Show) 에피소드 "자장가-안녕 곰"을 기반으로 한 이와 같은 툰 타이틀과 일반적으로 내 작업에서 팔레트는 선택된 몇 가지 색상으로 제한됩니다.

나는 색상을 더 추가하지 않고도 팔레트를 확장하기 위해 "파운데이션" 색상이라고 부르는 색상과 색조를 만듭니다.

Sketch에서는 HSL 색상 공간에서 작업하므로 이 프로세스에는 기초 색상의 밝기 값을 높이거나 낮추는 과정이 포함됩니다. 솔직히 말해서 어려운 작업은 아닙니다. 하지만 다른 파운데이션 색상을 선택하려면 완전히 새로운 색조와 색조 세트를 만들어야 합니다. 수동으로 계속 반복하면 금방 힘들어집니다.

HSL(H(색조), S(채도), L(밝기)) 색상 공간을 언급했지만 이는 색상을 설명하는 여러 방법 중 하나일 뿐입니다. RGB(R(빨간색), G(녹색), B(파란색))는 적어도 Hex 형태에서는 가장 친숙할 것입니다. LAB — L(밝기), A(녹색–빨간색), B(파란색–노란색) — 및 최신 버전도 있지만 현재 OKLCH 형식의 LCH — L(밝기), C(채도), H(색조) 모델이 널리 지원됩니다. LCH(특히 CSS의 OKLCH)를 사용하면 파운데이션 색상의 밝기 값을 조정할 수 있습니다.

아니면 채도를 변경할 수도 있습니다. LCH 채도와 HSL 채도는 모두 색상의 강도나 풍부함을 나타내지만 그 방식은 서로 다릅니다. LCH는 더 넓은 범위와 더 예측 가능한 색상 혼합을 제공합니다.

또한 색상을 변경하여 동일한 밝기와 채도 값을 공유하는 색상 팔레트를 만들 수도 있습니다. HSL과 LCH 모두에서 색상 스펙트럼은 빨간색에서 시작하여 녹색과 파란색을 거쳐 빨간색으로 돌아옵니다.

OKLCH가 색상에 대한 생각을 바꾼 이유 Sketch를 포함한 디자인 도구가 따라잡지 못하더라도 OKLCH 색상 공간에 대한 브라우저 지원은 이제 널리 보급되었습니다. 다행히도 OKLCH 사용이 중단되지는 않습니다. 브라우저는 Hex, HSL, LAB 및 RGB 값을 OKLCH로 변환해 줍니다. Hex를 포함한 모든 공간에서 기초 색상을 사용하여 CSS 사용자 정의 속성을 정의할 수 있습니다. /* 기초 색상 */ --기초: #5accd6;

여기에서 파생된 모든 색상은 자동으로 OKLCH로 변환됩니다. --foundation-light: oklch(var(--foundation) [...]; } --foundation-mid: oklch(var(--foundation) [...]; } --foundation-dark: oklch(var(--foundation) [...]; }

디자인 시스템으로서의 상대 색상 상대 색상을 "이 색상을 선택하고 조정한 다음 결과를 알려주세요."라고 말하는 것으로 생각하세요. 색상을 조정하는 방법에는 절대 변경과 비례 변경의 두 가지가 있습니다. 코드상으로는 비슷해 보이지만 파운데이션 색상을 바꾸기 시작하면 매우 다르게 동작합니다. 그 차이를 이해하는 것이 상대적인 색상을 시스템으로 바꿀 수 있는 것입니다. /* 기초 색상 */ --기초: #5accd6;

예를 들어 내 기초 색상의 밝기 값은 0.7837이고 더 어두운 버전의 밝기 값은 0.5837입니다. 차이를 계산하려면 높은 값에서 낮은 값을 빼고 calc() 함수를 사용하여 결과를 적용합니다. --기초-다크: oklch(var(--foundation)에서) 계산치(1 - 0.20) c h);

더 밝은 색상을 얻기 위해 대신 차이점을 추가합니다. --기초 조명: oklch(var(--foundation)에서) 계산치(1 + 0.10) c h);

크로마조정은 동일한 프로세스를 따릅니다. 파운데이션 색상의 강도를 0.1035에서 0.0035로 줄이기 위해 한 값을 다른 값에서 뺍니다. oklch(var(--foundation)에서) 내가 계산(c - 0.10) h);

색상 팔레트를 만들기 위해 기본 색상(200)의 색상 값과 새 색상(260) 간의 차이를 계산합니다. oklch(var(--foundation)에서) l c 계산(h + 60));

그 계산은 절대적입니다. 일정한 금액을 빼면 “항상 이만큼 빼세요”라는 뜻이 됩니다. 고정 값을 추가할 때도 마찬가지입니다. 계산(c - 0.10) 계산(c + 0.10)

저는 이 접근 방식의 한계를 힘들게 배웠습니다. 고정 채도 값을 빼는 방식에 의존하면 기초를 바꾸자마자 색상이 회색 쪽으로 무너졌습니다. 한 가지 색상에 효과가 있었던 팔레트가 다른 색상에서는 무너졌습니다. 곱셈은 ​​다르게 동작합니다. 채도를 곱하면 브라우저에 "이 색상의 강도를 일정 비율로 줄이세요."라고 말하는 것입니다. 기초가 변경되더라도 색상 간의 관계는 그대로 유지됩니다. 계산(c * 0.10)

내 이동, 크기 조정, 회전 규칙

밝기 이동(더하기 또는 빼기), 스케일 크로마(곱하기), 색조를 회전합니다(도를 더하거나 뺍니다).

강도 변화가 기본 색상에 비례하여 유지되기를 원하기 때문에 채도의 크기를 조정합니다. 색조 관계는 회전식이므로 색조를 곱하는 것은 의미가 없습니다. 가벼움은 지각적이고 절대적입니다. 이를 곱하면 이상한 결과가 나오는 경우가 많습니다.

한 가지 색상부터 전체 테마까지 상대 색상을 사용하면 기초 색상을 정의하고 이 색상에서 채우기, 획, 그라데이션 중지, 그림자 등 필요한 다른 모든 색상을 생성할 수 있습니다. 그 시점에서 색상은 팔레트가 아닌 시스템이 되기 시작합니다. SVG 일러스트레이션은 채우기, 획 및 그라디언트 전체에서 동일한 몇 가지 색상을 재사용하는 경향이 있습니다. 상대 색상을 사용하면 이러한 관계를 한 번 정의하고 어디에서나 재사용할 수 있습니다. 마치 애니메이터가 배경을 재사용하여 새로운 장면을 만드는 것과 같습니다.

기초 색상을 한 번 변경하면 파생된 모든 색상이 수동으로 다시 계산할 필요 없이 자동으로 업데이트됩니다. 애니메이션 그래픽 외에도 이와 동일한 접근 방식을 사용하여 버튼 및 링크와 같은 대화형 요소의 상태에 대한 색상을 정의할 수 있습니다. 제가 "자장가-안녕 곰" 툰 타이틀에 사용한 기초 색상은 하늘색처럼 보이는 파란색입니다. 배경은 내 기초와 더 어두운 버전 사이의 방사형 그라데이션입니다.

완전히 다른 분위기의 대체 버전을 만들려면 기초 색상만 변경하면 됩니다. --기초: #5accd6; --grad-end: var(--foundation); --grad-start: oklch(var(--foundation)에서) 계산(l - 0.2357) 계산(c * 0.833) h);

색상 값을 복제하지 않고 해당 사용자 정의 속성을 SVG 그라데이션에 바인딩하기 위해 하드 코딩된 중지 색상 값을 인라인 스타일로 대체했습니다.

다음으로, 내 툰 텍스트가 내가 선택한 기본 색상과 항상 대비되는지 확인해야 했습니다. 180도 색조 회전은 확실히 눈에 띄는 보색을 생성하지만 불편하게 진동할 수 있습니다. .text-라이트 { 채우기: oklch(var(--foundation)에서) l c 계산(h + 180)); }

90° 이동하면 완전히 보색되지 않고 생생한 보조 색상이 생성됩니다. .text-라이트 { 채우기: oklch(var(--foundation)에서) l c 계산(h - 90)); }

Quick Draw McGraw의 1959년 툰 타이틀 "El Kabong"을 재현한 것은 동일한 기술을 사용하지만 더 다양한 팔레트를 사용합니다. 예를 들어, 기초 색상과 더 어두운 색상 사이에는 또 다른 방사형 그라데이션이 있습니다.

배경의 건물과 나무는 동일한 기초 색상의 다른 색조일 뿐입니다. 해당 경로에는 두 가지 추가 채우기 색상이 필요했습니다. .bg-중간 { 채우기: oklch(var(--foundation)에서) calc(l - 0.04) calc(c * 0.91) h); }

.bg-어두운 { 채우기: oklch(var(--foundation)에서) calc(l - 0.12) calc(c * 0.64) h); }

기초가 움직이기 시작할 때 지금까지 제가 보여준 모든 것은 정적인 것이었습니다. 누군가가 색상 선택기를 사용하여 파운데이션 색상을 변경하더라도 해당 변경은 즉시 발생합니다. 그러나 애니메이션 그래픽은 가만히 있는 경우가 거의 없습니다. 단서는 이름에 있습니다. 따라서 색상이 시스템의 일부라면 애니메이션을 적용하지 못할 이유가 없습니다. 기초 색상에 애니메이션을 적용하려면 먼저 해당 색상을 OKLCH 채널로 분할해야 합니다.— 밝기, 채도 및 색상. 하지만 중요한 추가 단계가 있습니다. 해당 값을 입력된 사용자 정의 속성으로 등록해야 합니다. 그런데 그게 무슨 뜻인가요? 기본적으로 브라우저는 CSS 사용자 정의 속성 값이 색상, 길이, 숫자 또는 다른 것을 완전히 나타내는지 여부를 알 수 없습니다. 이는 종종 애니메이션 중에 원활하게 보간될 수 없고 한 값에서 다음 값으로 이동할 수 없음을 의미합니다. 사용자 정의 속성을 등록하면 해당 속성이 나타내는 값의 유형과 시간이 지남에 따라 어떻게 작동해야 하는지 브라우저에 알려줍니다. 이 경우 브라우저가 색상 채널을 숫자로 처리하여 원활하게 애니메이션을 적용할 수 있기를 원합니다. @property --f-l { 구문: "<번호>"; 상속: 사실; 초기값: 0.40; }

@property --f-c { 구문: "<번호>"; 상속: 사실; 초기값: 0.11; }

@property --f-h { 구문: "<번호>"; 상속: 사실; 초기값: 305; }

일단 등록되면 이러한 사용자 정의 속성은 기본 CSS처럼 작동합니다. 브라우저는 이를 프레임별로 보간할 수 있습니다. 그런 다음 해당 채널에서 기초 색상을 다시 작성합니다. --foundation: oklch(var(--f-l) var(--f-c) var(--f-h));

이렇게 하면 다른 숫자 값과 마찬가지로 기초 색상을 애니메이션할 수 있게 됩니다. 다음은 시간이 지남에 따라 밝기가 부드럽게 변하는 간단한 "호흡" 애니메이션입니다. @keyframes 호흡 { 0%, 100% { --f-l: 0.36; } 50% { --f-l: 0.46; } }

.toon-제목 { 애니메이션: 호흡 10초 이지인아웃 무한; }

채우기, 그라디언트 및 획의 다른 모든 색상은 --foundation에서 파생되므로 모두 함께 애니메이션화되며 수동으로 업데이트할 필요가 없습니다. 하나의 애니메이션 색상, 다양한 효과 이 프로세스를 시작할 때 CSS 상대 색상 값이 더 많은 가능성을 제공하는 동시에 구현을 더 쉽게 만들 수 있는지 궁금했습니다. 저는 최근에 제 웹사이트의 연락처 페이지에 새로운 금광 배경을 추가했는데, 첫 번째 반복에는 빛나고 흔들리는 석유 램프가 포함되었습니다.

저는 CSS 상대 색상에 애니메이션을 적용하여 램프의 색상으로 광산 내부를 더욱 사실적으로 만들 수 있는 방법을 탐구하고 싶었습니다. 나는 실제 빛이 그러는 것처럼 주변 세계에 영향을 미치기를 원했습니다. 그래서 여러 색상에 애니메이션을 적용하는 대신 단 하나의 색상에 애니메이션을 적용하는 작은 조명 시스템을 구축했습니다.

첫 번째 작업은 배경과 램프 사이에 오버레이 레이어를 배치하는 것이었습니다. <경로 id="오버레이" fill="var(--overlay-tint)" [...] style="mix-blend-mode: 색상" />

저는 mix-blend-mode: color를 사용했습니다. 그 이유는 기본 휘도를 유지하면서 그 아래에 있는 것에 색조를 주기 때문입니다. 애니메이션이 켜져 있을 때만 오버레이가 표시되기를 원하므로 오버레이를 옵트인으로 설정했습니다. .svg-광산 #오버레이 { 디스플레이: 없음; }

@media (prefers-reduced-motion: no-preference) { .svg-mine[data-animations=on] #overlay { 디스플레이: 블록; 불투명도: 0.5; } }

오버레이가 제자리에 있었지만 아직 램프에 연결되지 않았습니다. 광원이 필요했어요. 내 램프는 단순하며 각 램프에는 필터로 흐리게 처리한 원 요소가 포함되어 있습니다. 필터는 원 전체에 걸쳐 매우 부드러운 흐림 효과를 생성합니다.

오버레이와 램프를 별도로 애니메이션화하는 대신 단일 "불꽃" 색상 토큰을 애니메이션화하고 그로부터 다른 모든 것을 파생시킵니다. 먼저 OKLCH 채널에 대해 세 가지 유형의 사용자 지정 속성을 등록합니다. @property --fl-l { 구문: "<번호>"; 상속: 사실; 초기값: 0.86; } @property --fl-c { 구문: "<번호>"; 상속: 사실; 초기값: 0.12; } @property --fl-h { 구문: "<번호>"; 상속: 사실; 초기값: 95; }

깜박임이 불빛처럼 명확하게 읽힐 수 있도록 일부 프레임을 의도적으로 주황색으로 밀어서 해당 채널에 애니메이션을 적용했습니다.

@keyframes 불꽃 { 0%, 100% { --fl-l: 0.86; --fl-c: 0.12; --fl-h: 95; } 6% { --fl-l: 0.91; --fl-c: 0.10; --fl-h: 92; } 12% { --fl-l: 0.83; --fl-c: 0.14; --fl-h: 100; } 18% { --fl-l: 0.88; --fl-c: 0.11; --fl-h: 94; } 24% { --fl-l: 0.82; --fl-c: 0.16; --fl-h: 82; } 30% { --fl-l: 0.90; --fl-c: 0.12; --fl-h: 90; } 36% { --fl-l: 0.79; --fl-c: 0.17; --fl-h: 76; } 44% { --fl-l: 0.87; --fl-c: 0.12; --fl-h: 96; } 52% { --fl-l: 0.81; --fl-c: 0.15; --fl-h: 102; } 60% { --fl-l: 0.89; --fl-c: 0.11; --fl-h: 93; } 68% { --fl-l: 0.83; --fl-c: 0.16; --fl-h: 85; } 76% { --fl-l: 0.91; --fl-c: 0.10; --fl-h: 91; } 84% { --fl-l: 0.85; --fl-c: 0.14; --fl-h: 98; } 92% {--fl-l: 0.80; --fl-c: 0.17; --fl-h: 74; } }

그런 다음 해당 애니메이션의 범위를 SVG로 지정하여 공유 변수를 램프와 오버레이 모두에서 사용할 수 있도록 했습니다.

@media (prefers-reduced-motion: no-preference) { .svg-mine[데이터-애니메이션=on] { 애니메이션: 불꽃 3.6s 무한 선형; 격리: 격리하다;

/* 애니메이션 채널에서 불꽃 색상 만들기 */ --flame: oklch(var(--fl-l) var(--fl-c) var(--fl-h));

/* 불꽃에서 파생된 램프 색상 */ --램프 코어: oklch(var(--flame)에서 calc(l + 0.05) calc(c * 0.70) h);

/* 동일한 불꽃에서 파생된 오버레이 색조 */ --overlay-tint: oklch(var(--flame)에서) calc(l + 0.06) calc(c * 0.65) calc(h - 10)); } }

마지막으로 파생된 색상을 빛나는 램프와 영향을 미치는 오버레이에 적용했습니다. @media (prefers-reduced-motion: no-preference) { .svg-mine[data-animations=on] #mine-lamp-1 > 원, .svg-mine[data-animations=on] #mine-lamp-2 > 원 { 채우기: var(--lamp-core); }

.svg-mine[data-animations=on] #overlay { 디스플레이: 블록; 채우기: var(--overlay-tint); 불투명도: 0.5; } }

불꽃이 주황색으로 바뀌면 램프도 따뜻해지고 장면도 함께 따뜻해집니다. 불꽃이 식으면 모든 것이 안정됩니다. 가장 좋은 점은 아무것도 수동으로 작성되지 않는다는 것입니다. 기초 색상을 변경하거나 불꽃 애니메이션 범위를 조정하면 전체 조명 시스템이 동시에 업데이트됩니다. 내 웹 사이트에서 최종 결과를 볼 수 있습니다. 재사용, 용도 변경, 재검토 Hanna-Barbera 애니메이터들은 필요에 따라 요소의 용도를 변경해야 했지만 저는 작업을 보다 일관되고 유지 관리하기 쉽게 만들기 위해 색상을 재사용했습니다. CSS 상대 색상 값을 사용하면 다음을 수행할 수 있습니다.

단일 파운데이션 컬러를 정의하고, 다른 색상이 그것과 어떤 관련이 있는지 설명하십시오. 이러한 관계를 어디에서나 재사용하고 하나의 값을 변경하여 시스템에 애니메이션을 적용합니다.

상대 색상은 단지 테마 설정을 더 쉽게 만들어주는 것이 아닙니다. 이는 모션과 같은 색상이 의도적인 사고 방식을 장려하며, 하나의 값을 변경하면 그 아래의 작업을 다시 작성하지 않고도 전체 장면을 변화시킬 수 있다는 사고 방식을 장려합니다.

You May Also Like

Enjoyed This Article?

Get weekly tips on growing your audience and monetizing your content — straight to your inbox.

No spam. Join 138,000+ creators. Unsubscribe anytime.

Create Your Free Bio Page

Join 138,000+ creators on Seemless.

Get Started Free