CSS Houdini의 실용적인 개요
게시 됨: 2022-03-10새로운 CSS 기능이나 개선 사항이 초기 초안에서 개발자가 사용할 수 있는 완전히 지원되고 안정적인 CSS 기능으로 진행되는 데 오랜 시간이 걸립니다. JavaScript 기반 폴리필은 공식적으로 구현되기 전에 새로운 CSS 기능을 사용하기 위해 브라우저 지원이 부족한 대신 사용할 수 있습니다. 그러나 대부분의 경우 결함이 있습니다. 예를 들어 scrollsnap-polyfill은 CSS 스크롤 스냅 사양에 대한 브라우저 지원 불일치를 수정하는 데 사용할 수 있는 여러 폴리필 중 하나입니다. 그러나 그 솔루션에도 몇 가지 제한 사항, 버그 및 불일치가 있습니다.
폴리필 사용의 잠재적인 단점은 성능에 부정적인 영향을 미칠 수 있고 제대로 구현하기 어렵다는 것입니다. 이 단점은 브라우저의 DOM 및 CSSOM과 관련이 있습니다. 브라우저는 HTML 마크업에서 DOM(Document Object Model) 을 생성하고, 마찬가지로 CSS 마크업에서 CSSOM(CSS Object Model) 을 생성합니다. 이 두 개체 트리는 서로 독립적입니다. JavaScript는 DOM에서 작동하며 CSSOM에 대한 액세스가 매우 제한적입니다.
JavaScript Polyfill 솔루션은 초기 렌더링 주기가 완료된 후에만 실행됩니다. 즉, DOM과 CSSOM이 모두 생성되고 문서 로드가 완료된 경우입니다. Polyfill이 인라인으로 DOM의 스타일을 변경한 후 렌더링 프로세스가 다시 실행되고 전체 페이지가 다시 렌더링됩니다. requestAnimationFrame
메서드에 의존하거나 스크롤 이벤트와 같은 사용자 상호 작용에 의존하는 경우 부정적인 성능 영향이 훨씬 더 분명해집니다.
웹 개발의 또 다른 장애물 은 CSS 표준에 의해 부과되는 다양한 제약 입니다. 예를 들어 기본적으로 애니메이션을 적용할 수 있는 CSS 속성은 제한되어 있습니다. CSS는 기본적으로 색상에 애니메이션을 적용하는 방법을 알고 있지만 그라디언트에 애니메이션을 적용하는 방법은 모릅니다. 기술의 한계에도 불구하고 한계를 뛰어넘어 인상적인 웹 경험을 혁신하고 생성할 필요가 항상 있었습니다. 그렇기 때문에 개발자는 벽돌 레이아웃, 고급 3D 효과, 고급 애니메이션, 유동적인 타이포그래피, 애니메이션 그라디언트, 스타일이 지정된 select
요소 등
CSS 사양이 애니메이션에 대한 더 많은 제어, 향상된 텍스트 잘림, input
및 select
요소에 대한 더 나은 스타일 옵션, 더 많은 display
옵션, 더 많은 filter
옵션 등과 같은 업계의 다양한 기능 요구 사항을 충족하는 것은 불가능해 보입니다.
잠재적인 해결책은 무엇입니까? 개발자에게 다양한 API를 사용하여 CSS를 확장하는 기본 방법을 제공 합니다. 이 기사에서는 프론트엔드 개발자가 Houdini API, JavaScript 및 CSS를 사용하여 이를 수행하는 방법을 살펴볼 것입니다. 각 섹션에서 우리는 각 API를 개별적으로 검사하고, 브라우저 지원 및 현재 사양 상태를 확인하고, Progressive 향상을 사용하여 오늘날 구현될 수 있는 방법을 확인할 것입니다.
후디니란?
브라우저 API 모음에 대한 포괄적인 용어인 Houdini는 웹 개발 프로세스와 일반적으로 CSS 표준 개발에 상당한 개선을 가져오는 것을 목표로 합니다. 개발자는 JavaScript를 사용하여 새로운 기능으로 CSS를 확장하고 CSS 렌더링 엔진에 연결하고 렌더링 프로세스 중에 CSS를 적용하는 방법을 브라우저에 알릴 수 있습니다. 이렇게 하면 일반 폴리필을 사용하는 것보다 훨씬 더 나은 성능과 안정성을 얻을 수 있습니다.
Houdini 사양은 상위 수준 API 와 하위 수준 API의 두 가지 API 그룹으로 구성됩니다.
고급 API 는 브라우저의 렌더링 프로세스(스타일 → 레이아웃 → 페인트 → 합성)와 밀접한 관련이 있습니다. 여기에는 다음이 포함됩니다.
- 페인트 API
시각적 속성(색상, 배경, 테두리 등)이 결정되는 브라우저의 페인트 렌더링 단계를 위한 확장점입니다. - 레이아웃 API
요소 치수, 위치 및 정렬이 결정되는 브라우저의 레이아웃 렌더링 단계를 위한 확장점입니다. - 애니메이션 API
레이어가 화면에 그려지고 애니메이션되는 브라우저의 합성 렌더링 단계를 위한 확장점입니다.
저수준 API는 고수준 API 의 기초를 형성합니다. 여기에는 다음이 포함됩니다.
- 형식화된 개체 모델 API
- 사용자 정의 속성 및 값 API
- 글꼴 메트릭 API
- 워크렛
일부 Houdini API는 출시 준비가 되었을 때 다른 API와 함께 일부 브라우저에서 이미 사용할 수 있습니다.
CSS의 미래
지금까지 소개된 일반 CSS 기능 사양과 달리 Houdini는 개발자가 CSS를 보다 네이티브 방식으로 확장할 수 있다는 점에서 두드러집니다. 이것은 CSS 사양이 더 이상 발전하지 않고 CSS 기능의 새로운 공식 구현이 출시되지 않을 것임을 의미합니까? 글쎄요, 그렇지 않습니다. Houdini의 목표는 개발자가 쉽게 표준화할 수 있는 작업 프로토타입을 만들 수 있도록 하여 CSS 기능 개발 프로세스를 지원하는 것입니다.
또한 개발자는 브라우저별 버그 수정이 덜 필요하고 더 쉽게 오픈 소스 CSS Worklet을 공유할 수 있습니다.
형식화된 개체 모델 API
Houdini가 도입되기 전에는 JavaScript가 CSS와 상호 작용할 수 있는 유일한 방법은 문자열 값으로 표시되는 CSS를 구문 분석하고 수정하는 것이었습니다. 스타일을 수동으로 구문 분석하고 재정의하는 것은 값 유형을 앞뒤로 변경해야 하고 값 단위를 새 값을 할당할 때 수동으로 추가해야 하기 때문에 어렵고 오류가 발생하기 쉽습니다.
selectedElement.style.fontSize = newFontSize + "px"; // newFontSize = 20 console.log(selectedElement.style.fontSize); // "20px"
Typed Object Model(Typed OM) API는 CSS 값을 유형이 지정된 JavaScript 개체로 노출하여 의미론적 의미를 추가합니다. 관련 코드를 크게 개선하고 성능, 안정성 및 유지 관리성을 향상시킵니다. CSS 값은 값과 단위 속성으로 구성된 CSSUnitValue
인터페이스로 표현됩니다.
{ value: 20, unit: "px" }
이 새 인터페이스는 다음과 같은 새 속성과 함께 사용할 수 있습니다.
-
computedStyleMap()
: 계산된(인라인이 아닌) 스타일을 구문 분석하기 위한 것입니다. 이것은 파싱이나 다른 메소드를 사용하기 전에 호출되어야 하는 선택된 요소의 메소드입니다. -
attributeStyleMap
: 인라인 스타일을 구문 분석하고 수정합니다. 선택한 요소에서 사용할 수 있는 속성입니다.
// Get computed styles from stylesheet (initial value) selectedElement.computedStyleMap().get("font-size"); // { value: 20, unit: "px"} // Set inline styles selectedElement.attributeStyleMap.set("font-size", CSS.em(2)); // Sets inline style selectedElement.attributeStyleMap.set("color", "blue"); // Sets inline style // Computed style remains the same (initial value) selectedElement.computedStyleMap().get("font-size"); // { value: 20, unit: "px"} // Get new inline style selectedElement.attributeStyleMap.get("font-size"); // { value: 2, unit: "em"}
새 숫자 값을 설정할 때 특정 CSS 유형이 어떻게 사용되는지 확인하십시오. 이 구문을 사용하면 많은 잠재적인 유형 관련 문제를 피할 수 있으며 결과 코드는 더 안정적이고 버그가 없습니다.
get
및 set
메서드는 Typed OM API에서 정의한 사용 가능한 모든 메서드의 작은 하위 집합일 뿐입니다. 그 중 일부는 다음과 같습니다.
-
clear
: 모든 인라인 스타일을 제거합니다. -
delete
: 인라인 스타일에서 지정된 CSS 속성과 해당 값을 제거합니다. -
has
: 지정된 CSS 속성이 설정된 경우 부울을 반환합니다. -
append
: 여러 값을 지원하는 속성에 추가 값을 추가합니다. - 등.
특징 감지
var selectedElement = document.getElementById("example"); if(selectedElement.attributeStyleMap) { /* ... */ } if(selectedElement.computedStyleMap) { /* ... */ }
W3C 사양 상태
- 작업 초안: 커뮤니티의 검토를 위해 게시됨
브라우저 지원
구글 크롬 | 마이크로소프트 엣지 | 오페라 브라우저 | 파이어폭스 | 원정 여행 |
---|---|---|---|---|
지원 | 지원 | 지원 | 지원되지 않음 | 부분 지원(*) |
* "실험적 웹 플랫폼 기능" 또는 기타 기능 플래그가 활성화된 상태에서 지원됩니다.
데이터 출처: Houdini는 아직 준비되었습니까?
사용자 정의 속성 및 값 API
CSS 속성 및 값 API를 사용하면 개발자가 유형, 초기 값을 추가하고 상속을 정의하여 CSS 변수를 확장할 수 있습니다. 개발자는 브라우저에 전환 방법과 오류 발생 시 폴백 처리 방법을 알려주는 registerProperty
메서드를 사용하여 CSS 사용자 정의 속성을 등록하여 CSS 사용자 정의 속성을 정의할 수 있습니다.
CSS.registerProperty({ name: "--colorPrimary", syntax: "<color>", inherits: false, initialValue: "blue", });
이 메서드는 다음 속성을 가진 개체인 입력 인수를 받습니다.
-
name
: 사용자 정의 속성의 이름 -
syntax
: 사용자 정의 속성을 구문 분석하는 방법을 브라우저에 알려줍니다.<color>
,<integer>
,<number>
,<length>
,<percentage>
등과 같이 미리 정의된 값입니다. -
inherits
: 사용자 정의 속성이 부모의 값을 상속하는지 여부를 브라우저에 알려줍니다. -
initialValue
: 재정의될 때까지 사용되는 초기 값을 알려주며 이는 오류 발생 시 폴백으로 사용됩니다.
다음 예에서는 <color>
유형 사용자 정의 속성이 설정됩니다. 이 사용자 정의 속성은 그라디언트 전환에 사용됩니다. 현재 CSS가 배경 그라디언트에 대한 전환을 지원하지 않는다고 생각할 수 있으며 맞을 것입니다. 일반 background-color
전환에 사용되는 background
속성 대신 사용자 정의 속성 자체가 transition
에서 어떻게 사용되는지 주목하십시오.
.gradientBox { background: linear-gradient(45deg, rgba(255,255,255,1) 0%, var(--colorPrimary) 60%); transition: --colorPrimary 0.5s ease; /* ... */ } .gradientBox:hover { --colorPrimary: red /* ... */ }
브라우저는 그라디언트 전환을 처리하는 방법을 알지 못하지만 사용자 정의 속성이 <color>
유형으로 지정되기 때문에 색상 전환을 처리하는 방법을 알고 있습니다. Houdini를 지원하는 브라우저에서 요소를 가리키면 그래디언트 전환이 발생합니다. 그라디언트 위치 백분율은 CSS 사용자 정의 속성( <percentage>
유형으로 등록됨)으로 교체하고 예제와 동일한 방식으로 전환에 추가할 수도 있습니다.
registerProperty
가 제거되고 일반 CSS 사용자 정의 속성이 :root
선택기에 등록되면 그래디언트 전환이 작동하지 않습니다. 브라우저가 이를 색상으로 처리해야 함을 알 수 있도록 registerProperty
를 사용해야 합니다.
이 API의 향후 구현에서는 CSS에 직접 사용자 정의 속성을 등록할 수 있습니다.
@property --colorPrimary { syntax: "<color>"; inherits: false; initial-value: blue; }
예시
이 간단한 예는 색상 및 위치에 대해 각각 등록된 CSS 사용자 정의 속성을 사용하여 호버 이벤트에서 그라디언트 색상 및 위치 전환을 보여줍니다. 전체 소스 코드는 예제 리포지토리에서 사용할 수 있습니다.

특징 감지
if (CSS.registerProperty) { /* ... */ }
W3C 사양 상태
- 작업 초안: 커뮤니티의 검토를 위해 게시됨
브라우저 지원
구글 크롬 | 마이크로소프트 엣지 | 오페라 브라우저 | 파이어폭스 | 원정 여행 |
---|---|---|---|---|
지원 | 지원 | 지원 | 지원되지 않음 | 지원되지 않음 |
데이터 출처: Houdini는 아직 준비되었습니까?
글꼴 메트릭 API
Font Metrics API는 아직 개발 초기 단계이므로 사양이 향후 변경될 수 있습니다. 현재 초안에서 Font Metrics API 는 개발자가 화면에서 텍스트 요소가 렌더링되는 방식에 영향을 줄 수 있도록 화면에 렌더링되는 텍스트 요소의 치수를 측정하는 방법을 제공합니다. 이러한 값은 현재 기능으로 측정하기 어렵거나 불가능하므로 이 API를 사용하면 개발자가 텍스트 및 글꼴 관련 CSS 기능을 보다 쉽게 만들 수 있습니다. 여러 줄 동적 텍스트 잘림은 이러한 기능 중 하나의 예입니다.
W3C 사양 상태
- 아이디어 수집: 현재 제출된 사양 초안 없음
브라우저 지원
구글 크롬 | 마이크로소프트 엣지 | 오페라 브라우저 | 파이어폭스 | 원정 여행 |
---|---|---|---|---|
지원되지 않음 | 지원되지 않음 | 지원되지 않음 | 지원되지 않음 | 지원되지 않음 |
데이터 출처: Houdini는 아직 준비되었습니까?
워크렛
다른 API로 이동하기 전에 Worklets 개념을 설명하는 것이 중요합니다. Worklet 은 렌더링 중에 실행되고 기본 JavaScript 환경과 독립적인 스크립트입니다. 렌더링 엔진의 확장점입니다. 병렬 처리(2개 이상의 인스턴스 포함) 및 스레드 불가지론을 위해 설계되었으며 전역 범위에 대한 액세스가 감소했으며 필요할 때 렌더링 엔진에 의해 호출됩니다. Worklet은 HTTPS(프로덕션 환경) 또는 localhost(개발 목적)에서만 실행할 수 있습니다.
Houdini는 브라우저 렌더 엔진을 확장하기 위해 다음 Worklet을 도입했습니다.
- 페인트 워크렛 - 페인트 API
- 애니메이션 워크렛 - 애니메이션 API
- 레이아웃 워크렛 - 레이아웃 API
페인트 API
Paint API를 사용하면 개발자가 JavaScript 기능을 사용하여 HTML5 Canvas API의 하위 집합인 2D 렌더링 컨텍스트를 사용하여 요소의 배경, 테두리 또는 콘텐츠에 직접 그릴 수 있습니다. Paint API는 Paint Worklet을 사용하여 CSS의 변경 사항(예: CSS 변수의 변경 사항)에 동적으로 응답하는 이미지를 그립니다. Canvas API에 익숙한 사람은 Houdini의 Paint API를 사용하면 집과 같은 편안함을 느낄 것입니다.
Paint Worklet을 정의하는 데 필요한 몇 가지 단계가 있습니다.
-
registerPaint
함수를 사용하여 Paint Worklet 작성 및 등록 -
CSS.paintWorklet.addModule
함수를 사용하여 HTML 파일 또는 기본 JavaScript 파일에서 Worklet 호출 - Worklet 이름 및 선택적 입력 인수와 함께 CSS에서
paint()
함수를 사용하십시오.
Paint Worklet을 등록하고 기능을 정의하는 데 사용되는 registerPaint
함수를 살펴보겠습니다.
registerPaint("paintWorketExample", class { static get inputProperties() { return ["--myVariable"]; } static get inputArguments() { return ["<color>"]; } static get contextOptions() { return {alpha: true}; } paint(ctx, size, properties, args) { /* ... */ } });
registerPaint
함수는 여러 부분으로 구성됩니다.
-
inputProperties
:
Worklet이 추적할 CSS 사용자 정의 속성의 배열입니다. 이 배열은 페인트 워크렛의 종속성을 나타냅니다. -
inputArguments
:
CSS 내부의paint
함수에서 전달할 수 있는 입력 인수의 배열입니다. -
contextOptions
: 색상의 불투명도를 허용하거나 허용하지 않습니다.false
로 설정하면 모든 색상이 완전히 불투명하게 표시됩니다. -
paint
: 다음 인수를 제공하는 주 함수:-
ctx
: 2D 드로잉 컨텍스트로 Canvas API의 2D 드로잉 컨텍스트와 거의 동일합니다. -
size
: 요소의 너비와 높이를 포함하는 객체. 값은 레이아웃 렌더링 프로세스에 의해 결정됩니다. 캔버스 크기는 요소의 실제 크기와 동일합니다. -
properties
:inputProperties
에 정의된 입력 변수 -
args
: CSS의paint
함수에 전달된 입력 인수의 배열
-
Worklet이 등록된 후에는 단순히 파일 경로를 제공하여 HTML 파일에서 호출해야 합니다.
CSS.paintWorklet.addModule("path/to/worklet/file.js");
모든 Worklet은 모듈화되고 재사용 가능하게 만드는 외부 URL(예: Content Delivery Network)에서 추가할 수도 있습니다.
CSS.paintWorklet.addModule("https://url/to/worklet/file.js");
Worklet이 호출된 후 paint
기능을 사용하여 CSS 내에서 사용할 수 있습니다. 이 함수는 Worklet의 등록된 이름을 첫 번째 입력 인수로 받아들이고 그 뒤에 오는 각 입력 인수는 Worklet에 전달할 수 있는 사용자 지정 인수입니다( Worklet의 inputArguments
내부에 정의됨). 이 시점부터 브라우저는 Worklet을 호출할 시기와 응답하도록 변경되는 사용자 작업 및 CSS 사용자 정의 속성 값을 결정합니다.

.exampleElement { /* paintWorkletExample - name of the worklet blue - argument passed to a Worklet */ background-image: paint(paintWorketExample, blue); }
예시
다음 예는 Paint API와 일반적인 Worklet 재사용성 및 모듈성을 보여줍니다. Google Chrome Labs 저장소에서 직접 ripple Worklet을 사용하고 있으며 다른 스타일의 다른 요소에서 실행됩니다. 전체 소스 코드는 예제 리포지토리에서 사용할 수 있습니다.

특징 감지
if ("paintWorklet" in CSS) { /* ... */ } @supports(background:paint(paintWorketExample)){ /* ... */ }
W3C 사양 상태
- 후보자 추천: 안정적인 작업 초안 구현 준비
브라우저 지원
구글 크롬 | 마이크로소프트 엣지 | 오페라 브라우저 | 파이어폭스 | 원정 여행 |
---|---|---|---|---|
지원 | 지원 | 지원 | 지원되지 않음 | 지원되지 않음 |
데이터 출처: Houdini는 아직 준비되었습니까?
애니메이션 API
Animation API는 다양한 이벤트(스크롤, 호버, 클릭 등)를 수신하는 옵션으로 웹 애니메이션을 확장하고 Animation Worklet을 사용하여 자체 전용 스레드에서 애니메이션을 실행하여 성능을 향상시킵니다. 이를 통해 사용자 작업은 성능이 뛰어나고 차단되지 않는 방식으로 실행되는 애니메이션의 흐름을 제어할 수 있습니다.
다른 Worklet과 마찬가지로 Animation Worklet도 먼저 등록해야 합니다.
registerAnimator("animationWorkletExample", class { constructor(options) { /* ... */ } animate(currentTime, effect) { /* ... */ } });
이 클래스는 두 가지 기능으로 구성됩니다.
-
constructor
: 새 인스턴스가 생성될 때 호출됩니다. 일반 설정에 사용됩니다. -
animate
: 애니메이션 로직을 담고 있는 메인 함수. 다음 입력 인수를 제공합니다.-
currentTime
: 정의된 타임라인의 현재 시간 값 -
effect
: 이 애니메이션이 사용하는 효과의 배열
-
Animation Worklet이 등록된 후에는 메인 JavaScript 파일 에 포함되어야 하고, 애니메이션(요소, 키프레임, 옵션)이 정의되어야 하고 애니메이션은 선택된 타임라인으로 인스턴스화되어야 합니다. 타임라인 개념과 웹 애니메이션 기본 사항은 다음 섹션에서 설명합니다.
/* Include Animation Worklet */ await CSS.animationWorklet.addModule("path/to/worklet/file.js");; /* Select element that's going to be animated */ const elementExample = document.getElementById("elementExample"); /* Define animation (effect) */ const effectExample = new KeyframeEffect( elementExample, /* Selected element that's going to be animated */ [ /* ... */ ], /* Animation keyframes */ { /* ... */ }, /* Animation options - duration, delay, iterations, etc. */ ); /* Create new WorkletAnimation instance and run it */ new WorkletAnimation( "animationWorkletExample" /* Worklet name */ effectExample, /* Animation (effect) timeline */ document.timeline, /* Input timeline */ {}, /* Options passed to constructor */ ).play(); /* Play animation */
타임라인 매핑
웹 애니메이션은 타임라인을 기반으로 하며 현재 시간을 효과의 현지 시간 타임라인에 매핑합니다 . 예를 들어 페이지가 로드된 후 1초(지연)되고 4초 동안 실행되는 3개의 키프레임(시작, 중간, 마지막)이 있는 반복되는 선형 애니메이션을 살펴보겠습니다.
예제의 효과 타임라인은 다음과 같습니다(지연 없이 4초 지속 시간 포함).
효과 타임라인(4초 지속 시간) | 키프레임 |
---|---|
0ms | 첫 번째 키프레임 - 애니메이션 시작 |
2000ms | 중간 키프레임 - 애니메이션 진행 중 |
4000ms | 마지막 키프레임 - 애니메이션이 종료되거나 첫 번째 키프레임으로 재설정됩니다. |
effect.localTime
을 더 잘 이해하기 위해 값을 3000ms로 설정하면(1000ms 지연 고려) 결과 애니메이션은 효과 타임라인의 중간 키프레임에 고정됩니다(1000ms 지연 + 중간 키프레임의 경우 2000ms). 애니메이션이 4000ms 간격(애니메이션 지속 시간)으로 반복되기 때문에 값을 7000ms와 11000ms로 설정해도 동일한 효과가 발생합니다.
animate(currentTime, effect) { effect.localTime = 3000; // 1000ms delay + 2000ms middle keyframe }
애니메이션이 특정 키프레임에 잠겨 있기 때문에 일정한 effect.localTime
값을 가질 때 애니메이션이 발생하지 않습니다. 요소에 제대로 애니메이션을 적용하려면 해당 effect.localTime
이 동적이어야 합니다. 값이 currentTime
입력 인수 또는 다른 변수에 의존하는 함수여야 합니다.
다음 코드는 현지 시간에 영향을 미치는 타임라인의 1:1(선형 함수) 매핑의 기능적 표현을 보여줍니다.
animate(currentTime, effect) { effect.localTime = currentTime; // y = x linear function }
타임라인( document.timeline ) | 매핑된 효과 현지 시간 | 키프레임 |
---|---|---|
startTime + 0ms(경과 시간) | 시작 시간 + startTime | 첫 번째 |
시작 시간 + startTime (경과 시간) | 시작 시간 + startTime (지연) + 0ms | 첫 번째 |
시작 시간 + startTime (경과 시간) | 시작 시간 + startTime (지연) + 2000ms | 가운데 |
시작 시간 + startTime (경과 시간) | 시작 시간 + 1000ms(지연) + startTime | 마지막 / 처음 |
시작 시간 + startTime (경과 시간) | 시작 시간 + 1000ms(지연) + startTime | 가운데 |
시작 시간 + startTime (경과 시간) | 시작 시간 + 1000ms(지연) + startTime | 마지막 / 처음 |
타임라인은 효과의 현지 시간에 대한 1:1 매핑으로 제한되지 않습니다. Animation API를 사용하면 개발자가 표준 JavaScript 기능을 사용하여 복잡한 타임라인을 생성함으로써 animate
기능에서 타임라인 매핑을 조작할 수 있습니다. 애니메이션은 또한 각 반복에서 동일하게 동작할 필요가 없습니다(애니메이션이 반복되는 경우).
애니메이션은 로드된 순간부터 밀리초를 계산하기 시작하는 문서의 타임라인에 의존할 필요가 없습니다. ScrollTimeline
개체를 사용하여 스크롤 이벤트와 같은 사용자 작업을 애니메이션의 타임라인으로 사용할 수 있습니다. 예를 들어 애니메이션은 사용자가 화면에서 200픽셀로 스크롤했을 때 시작되고 사용자가 화면에서 800픽셀로 스크롤했을 때 끝날 수 있습니다.
const scrollTimelineExample = new ScrollTimeline({ scrollSource: scrollElement, /* DOM element whose scrolling action is being tracked */ orientation: "vertical", /* Scroll direction */ startScrollOffset: "200px", /* Beginning of the scroll timeline */ endScrollOffset: "800px", /* Ending of the scroll timeline */ timeRange: 1200, /* Time duration to be mapped to scroll values*/ fill: "forwards" /* Animation fill mode */ }); ...
애니메이션은 자동으로 사용자 스크롤 속도에 맞게 조정되고 부드럽고 반응성이 유지됩니다. Animation Worklet은 메인 스레드에서 실행되고 브라우저의 렌더링 엔진에 연결되기 때문에 사용자 스크롤에 의존하는 애니메이션은 원활하게 실행될 수 있고 매우 성능이 좋습니다.
예시
다음 예는 비선형 타임라인 구현 방법을 보여줍니다. 수정된 가우스 함수를 사용하여 동일한 타임라인으로 이동 및 회전 애니메이션을 적용합니다. 전체 소스 코드는 예제 리포지토리에서 사용할 수 있습니다.

특징 감지
if (CSS.animationWorklet) { /* ... */ }
W3C 사양 상태
- 첫 번째 공개 작업 초안: 커뮤니티 검토 준비, 사양 변경 가능성 있음
브라우저 지원
구글 크롬 | 마이크로소프트 엣지 | 오페라 브라우저 | 파이어폭스 | 원정 여행 |
---|---|---|---|---|
부분 지원(*) | 부분 지원(*) | 부분 지원(*) | 지원되지 않음 | 지원되지 않음 |
* "실험적 웹 플랫폼 기능" 플래그가 활성화된 상태에서 지원됩니다.
데이터 출처: Houdini는 아직 준비되었습니까?
레이아웃 API
Layout API를 사용하면 개발자가 display
CSS 속성에서 사용할 수 있는 새로운 레이아웃 모드를 정의하여 브라우저의 레이아웃 렌더링 프로세스를 확장할 수 있습니다. Layout API는 새로운 개념을 도입하고 매우 복잡하며 사용자 정의 레이아웃 알고리즘을 개발하기 위한 많은 옵션을 제공합니다.
다른 Worklet과 마찬가지로 레이아웃 Worklet을 먼저 등록하고 정의해야 합니다.
registerLayout('exampleLayout', class { static get inputProperties() { return ['--exampleVariable']; } static get childrenInputProperties() { return ['--exampleChildVariable']; } static get layoutOptions() { return { childDisplay: 'normal', sizing: 'block-like' }; } intrinsicSizes(children, edges, styleMap) { /* ... */ } layout(children, edges, constraints, styleMap, breakToken) { /* ... */ } });
Worklet 레지스터에는 다음 메소드가 포함됩니다.
-
inputProperties
:
Worklet이 추적할 CSS 사용자 정의 속성의 배열은 상위 레이아웃 요소, 즉 이 레이아웃을 호출하는 요소에 속합니다. 이 배열은 Layout Worklet의 종속성을 나타냅니다. -
childrenInputProperties
:
부모 레이아웃 요소의 자식 요소, 즉 이 레이아웃을 설정하는 요소의 자식에 속하는 Worklet이 추적할 CSS 사용자 정의 속성의 배열입니다. -
layoutOptions
: 다음 레이아웃 속성을 정의합니다.-
childDisplay
: 미리 정의된block
또는normal
값을 가질 수 있습니다. 상자를 블록으로 표시할지 인라인으로 표시할지 결정합니다. -
sizing
: 미리 정의된block-like
또는manual
값을 가질 수 있습니다. 크기를 미리 계산하거나 미리 계산하지 않도록 브라우저에 지시합니다(크기가 명시적으로 설정되지 않은 경우).
-
-
intrinsicSizes
: 상자 또는 그 내용이 레이아웃 컨텍스트에 맞는 방법을 정의합니다.-
children
: 상위 레이아웃 요소의 하위 요소, 즉 이 레이아웃을 호출하는 요소의 하위 요소입니다. -
edges
: 상자의 레이아웃 가장자리 -
styleMap
: 상자의 입력된 OM 스타일
-
-
layout
: 레이아웃을 수행하는 주요 기능입니다.-
children
: 상위 레이아웃 요소의 하위 요소, 즉 이 레이아웃을 호출하는 요소의 하위 요소입니다. -
edges
: 상자의 레이아웃 가장자리 -
constraints
: 상위 레이아웃의 제약 조건 -
styleMap
: 상자의 입력된 OM 스타일 -
breakToken
: 페이지 매김 또는 인쇄의 경우 레이아웃을 재개하는 데 사용되는 브레이크 토큰.
-
Paint API의 경우와 마찬가지로 브라우저 렌더링 엔진은 페인트 Worklet이 호출되는 시기를 결정합니다. HTML 또는 기본 JavaScript 파일에만 추가하면 됩니다.
CSS.layoutWorklet.addModule('path/to/worklet/file.js');
그리고 마지막으로 CSS 파일에서 참조해야 합니다.
.exampleElement { display: layout(exampleLayout); }
Layout API가 레이아웃을 수행하는 방법
이전 예제에서는 Layout API를 사용하여 exampleLayout
을 정의했습니다.
.exampleElement { display: layout(exampleLayout); }
이 요소는 패딩, 테두리 및 스크롤 막대로 구성된 레이아웃 가장자리 로 둘러싸인 상위 레이아웃 이라고 합니다. 상위 레이아웃은 현재 레이아웃 이라고 하는 하위 요소로 구성됩니다. 현재 레이아웃은 레이아웃 API를 사용하여 레이아웃을 사용자 지정할 수 있는 실제 대상 요소입니다. 예를 들어 display: flex;
요소에서 자식은 플렉스 레이아웃을 형성하기 위해 재배치됩니다. 이는 Layout API로 수행되는 작업과 유사합니다.
각 Current Layout 은 LayoutChild(요소, ::before
및 ::after
의사 요소)에 대한 레이아웃 알고리즘인 Child Layout 으로 구성되며 LayoutChild 는 스타일 데이터(레이아웃 데이터 없음)만 포함하는 CSS 생성 상자입니다. LayoutChild 요소는 스타일 단계에서 브라우저 렌더링 엔진에 의해 자동으로 생성됩니다. Layout Child는 실제로 레이아웃 렌더 작업을 수행하는 Fragment 를 생성할 수 있습니다.
예시
Paint API 예제와 유사하게 이 예제는 Google Chrome Labs 저장소에서 직접 벽돌 레이아웃 Worklet을 가져오지만 이 예제에서는 텍스트 대신 이미지 콘텐츠와 함께 사용됩니다. 전체 소스 코드는 예제 리포지토리에서 사용할 수 있습니다.

특징 감지
if (CSS.layoutWorklet) { /* ... */ }
W3C 사양 상태
- 첫 번째 공개 작업 초안: 커뮤니티 검토 준비, 사양 변경 가능성 있음
브라우저 지원
구글 크롬 | 마이크로소프트 엣지 | 오페라 브라우저 | 파이어폭스 | 원정 여행 |
---|---|---|---|---|
부분 지원(*) | 부분 지원(*) | 부분 지원(*) | 지원되지 않음 | 지원되지 않음 |
* "실험적 웹 플랫폼 기능" 플래그가 활성화된 상태에서 지원됩니다.
데이터 출처: Houdini는 아직 준비되었습니까?
Houdini 및 점진적 향상
CSS Houdini는 아직 최적의 브라우저 지원을 제공하지 않지만 현재 점진적인 향상을 염두에 두고 사용할 수 있습니다. 프로그레시브 향상에 익숙하지 않은 경우 정말 잘 설명하는 이 편리한 기사를 확인하는 것이 좋습니다. 오늘 프로젝트에서 Houdini를 구현하기로 결정했다면 염두에 두어야 할 몇 가지 사항이 있습니다.
- 기능 감지를 사용하여 오류를 방지합니다.
각 Houdini API 및 Worklet은 브라우저에서 사용 가능한지 확인하는 간단한 방법을 제공합니다. 기능 감지를 사용하여 Houdini 개선 사항을 지원하고 오류를 방지하는 브라우저에만 적용하십시오. - 프레젠테이션 및 시각적 향상용으로만 사용하십시오.
아직 Houdini를 지원하지 않는 브라우저에서 웹사이트를 탐색하는 사용자는 웹사이트의 콘텐츠와 핵심 기능에 액세스할 수 있어야 합니다. 사용자 경험과 콘텐츠 프레젠테이션은 Houdini 기능에 의존해서는 안 되며 안정적인 폴백이 있어야 합니다. - 표준 CSS 폴백을 사용합니다.
예를 들어 일반 CSS 사용자 정의 속성은 사용자 정의 속성 및 값 API를 사용하여 정의된 스타일에 대한 대체로 사용될 수 있습니다.
먼저 성능이 뛰어나고 안정적인 웹사이트 사용자 경험을 개발하는 데 집중한 다음 Houdini 기능을 장식용으로 사용하여 점진적인 개선을 하십시오.
결론
Houdini API는 마침내 개발자가 스타일 조작 및 장식에 사용되는 JavaScript 코드를 브라우저의 렌더링 파이프라인에 더 가깝게 유지하여 성능과 안정성을 향상시킬 수 있도록 합니다. 개발자가 브라우저 렌더링 프로세스에 연결할 수 있도록 함으로써 쉽게 공유, 구현 및 잠재적으로 CSS 사양 자체에 추가할 수 있는 다양한 CSS 폴리필을 개발할 수 있습니다. 또한 Houdini는 개발자와 디자이너가 스타일, 레이아웃 및 애니메이션 작업 시 CSS 제한에 덜 제약을 받도록 하여 새롭고 즐거운 웹 경험을 제공합니다.
CSS Houdini 기능은 현재 프로젝트에 추가할 수 있지만 엄격하게는 점진적인 향상을 염두에 두고 있습니다. 이렇게 하면 Houdini 기능을 지원하지 않는 브라우저가 오류 없이 웹사이트를 렌더링하고 최적의 사용자 경험을 제공할 수 있습니다.
Houdini가 견인력을 얻고 브라우저 지원이 향상됨에 따라 개발자 커뮤니티에서 무엇을 내놓을지 지켜보는 것은 흥미로울 것입니다. 다음은 커뮤니티의 Houdini API 실험의 멋진 예입니다.
- CSS 후디니 실험
- CSS Houdini에 대한 대화형 소개
- Google Chrome Labs의 Houdini 샘플
참고문헌
- W3C Houdini 사양 초안
- 후디니 주(Chrome Dev Summit 2018)
- Houdini의 애니메이션 워크렛 - Google Developers
- CSS Houdini에 대한 대화형 소개