CSS Houdini는 웹 개발자에게 브라우저의 스타일링 파이프라인에 대한 직접적인 접근을 허용하는 새로운 API 집합입니다. 이 기술은 CSS의 기능을 확장하고, 웹에서 보다 복잡하고 맞춤화된 스타일링을 가능하게 합니다. CSS Houdini는 브라우저 성능을 유지하면서도, 개발자가 창의적인 디자인을 구현할 수 있도록 돕습니다. 이 글에서는 CSS Houdini의 주요 기능과 이를 활용한 고급 스타일링 기술을 소개하겠습니다.

1. CSS Houdini란?

CSS Houdini는 브라우저의 CSS 파싱 엔진에 접근할 수 있는 API 모음으로, CSS에 대한 새로운 확장성을 제공합니다. 이를 통해 개발자는 브라우저가 스타일을 렌더링하는 방법을 제어할 수 있으며, 사용자 정의 CSS 속성, 레이아웃, 애니메이션 등을 만들 수 있습니다. 주요 API로는 CSS Painting API, CSS Properties and Values API, CSS Layout API, CSS Typed OM 등이 있습니다.

2. CSS Painting API - 사용자 정의 배경과 패턴

CSS Painting API를 사용하면 캔버스처럼 브라우저의 렌더링 파이프라인에 접근하여 사용자 정의 배경이나 패턴을 생성할 수 있습니다. 이를 통해 CSS에서 복잡한 그래픽 효과를 직접 구현할 수 있습니다.

2.1 Painting API 사용 예시

먼저, JavaScript에서 registerPaint를 사용하여 사용자 정의 페인트 클래스를 등록합니다.

// custom-paint.js
class DotsPainter {
    static get inputProperties() {
        return ['--dot-color', '--dot-size'];
    }

    paint(ctx, geom, properties) {
        const color = properties.get('--dot-color').toString() || 'black';
        const size = parseInt(properties.get('--dot-size')) || 10;

        ctx.fillStyle = color;
        for (let y = 0; y < geom.height; y += size * 2) {
            for (let x = 0; x < geom.width; x += size * 2) {
                ctx.beginPath();
                ctx.arc(x + size / 2, y + size / 2, size / 2, 0, 2 * Math.PI);
                ctx.fill();
            }
        }
    }
}

registerPaint('dots', DotsPainter);

이제 CSS에서 paint() 함수를 사용하여 해당 배경을 적용합니다.

/* styles.css */
@paint-worklet add-module('custom-paint.js');

.custom-background {
    width: 300px;
    height: 300px;
    --dot-color: red;
    --dot-size: 15px;
    background-image: paint(dots);
}
<div class="custom-background"></div>

설명:

  • registerPaint: DotsPainter 클래스를 등록하여 사용자 정의 페인트를 생성합니다.
  • paint(dots): CSS에서 background-image 속성에 사용자 정의 페인트를 적용합니다.

3. CSS Properties and Values API - 사용자 정의 CSS 속성

CSS Properties and Values API는 사용자 정의 속성을 생성하고, 그 속성에 대한 기본값과 데이터 유형을 설정할 수 있습니다. 이를 통해 사용자 정의 속성을 더 안전하게 관리하고, CSS 코드의 재사용성을 높일 수 있습니다.

3.1 사용자 정의 속성 사용 예시

먼저, 사용자 정의 속성을 등록합니다.

// custom-properties.js
CSS.registerProperty({
    name: '--main-color',
    syntax: '<color>',
    inherits: false,
    initialValue: 'black'
});

이제 CSS에서 이 속성을 사용하여 스타일을 정의할 수 있습니다.

/* styles.css */
@import 'custom-properties.js';

.custom-box {
    width: 100px;
    height: 100px;
    background-color: var(--main-color);
    transition: background-color 0.5s ease;
}

.custom-box:hover {
    --main-color: blue;
}
<div class="custom-box"></div>

설명:

  • CSS.registerProperty: --main-color라는 사용자 정의 CSS 속성을 등록합니다. 이 속성은 색상(<color>) 유형을 가지며, 기본값은 black입니다.
  • var(--main-color): 사용자 정의 속성을 CSS에서 사용하여 요소의 스타일을 정의합니다.

4. CSS Typed OM - 성능 최적화된 스타일 계산

CSS Typed Object Model (Typed OM)은 스타일 속성을 JavaScript에서 보다 효율적으로 조작할 수 있도록 돕습니다. Typed OM을 사용하면 속성 값을 파싱하지 않고 직접 객체로 다룰 수 있어 성능이 향상됩니다.

4.1 Typed OM 사용 예시

다음은 CSS Typed OM을 사용해 요소의 스타일을 동적으로 변경하는 예시입니다.

const box = document.querySelector('.custom-box');

// 현재 배경 색상 가져오기
const styleMap = box.computedStyleMap();
const backgroundColor = styleMap.get('background-color');
console.log(backgroundColor.toString()); // "rgb(0, 0, 0)"

// 배경 색상을 동적으로 변경
box.attributeStyleMap.set('background-color', CSS.rgb(255, 0, 0));

설명:

  • computedStyleMap: 요소의 계산된 스타일을 가져와서 특정 스타일 속성을 객체로 반환합니다.
  • attributeStyleMap.set: 요소의 스타일 속성을 객체로 설정하여 스타일을 동적으로 변경합니다.

5. CSS Layout API - 사용자 정의 레이아웃

CSS Layout API를 사용하면 브라우저의 기본 레이아웃 엔진을 확장하여 복잡한 사용자 정의 레이아웃을 구현할 수 있습니다. 예를 들어, 고유한 레이아웃 알고리즘을 만들어 원하는 방식으로 요소를 배치할 수 있습니다.

5.1 Layout API 사용 예시

// custom-layout.js
class MyLayout {
    static get inputProperties() {
        return ['--columns'];
    }

    *intrinsicSizes() {
        return { minContent: 0, maxContent: 1000 };
    }

    *layout(children, edges, constraints, styleMap) {
        const columns = parseInt(styleMap.get('--columns')) || 3;
        const childInlineSize = constraints.fixedInlineSize / columns;

        let availableBlockSize = constraints.fixedBlockSize;
        let childBlockSize = 0;

        for (const child of children) {
            const childFragment = yield child.layoutNextFragment({
                inlineSize: childInlineSize,
                blockSize: availableBlockSize
            });
            availableBlockSize -= childFragment.blockSize;
            childBlockSize = Math.max(childBlockSize, childFragment.blockSize);
        }

        return { inlineSize: constraints.fixedInlineSize, blockSize: childBlockSize };
    }
}

registerLayout('my-layout', MyLayout);

이제 CSS에서 해당 레이아웃을 적용합니다.

/* styles.css */
@layout-worklet add-module('custom-layout.js');

.custom-layout-container {
    display: block;
    --columns: 4;
    layout: my-layout;
}
<div class="custom-layout-container">
    <div>Item 1</div>
    <div>Item 2</div>
    <div>Item 3</div>
    <div>Item 4</div>
</div>

설명:

  • registerLayout: MyLayout이라는 사용자 정의 레이아웃 클래스를 등록합니다. 이 클래스는 요소를 지정된 열(--columns) 수에 따라 배치합니다.
  • layout: my-layout: 사용자 정의 레이아웃을 CSS에서 사용하여 요소의 배치를 제어합니다.

결론

CSS Houdini는 웹 개발자에게 놀라운 가능성을 제공하는 미래의 CSS 기술입니다. Painting API, Properties and Values API, Typed OM, Layout API 등 다양한 API를 통해 CSS 스타일링의 한계를 넘어서 창의적이고 성능 최적화된 웹 디자인을 구현할 수 있습니다. 이 글에서 소개한 예시를 통해 CSS Houdini의 강력한 기능을 미리 체험하고, 여러분의 웹 프로젝트에 적용해보세요. CSS Houdini를 활용하면 웹 디자인의 미래를 선도할 수 있습니다.

+ Recent posts