Zeno ZENO

[Part 7] Web Components — 고급 스타일링 전략

CSS 변수, ::part(), constructable stylesheets, adoptedStyleSheets로 Shadow DOM 안팎을 우아하게 스타일링하는 방법을 실전 코드로 정리합니다.

[Part 7] Web Components — 고급 스타일링 전략

Part 6에서는 Custom Events를 사용해서 컴포넌트 내부에서 발생한 일을 외부로 전달하는 방법을 알아봤다.

이번 글에서는 Web Components의 스타일링 전략을 알아본다.

Web Components에서 스타일링은 일반 CSS와 조금 다르다.

특히 Shadow DOM을 사용하면 외부 CSS가 내부로 쉽게 들어오지 못하고, 내부 CSS도 외부에 영향을 주지 않는다.

이것은 장점이지만 동시에 외부에서 디자인을 수정하기 어렵게 만들 수도 있다.

그래서 Web Components에서는 CSS 변수, :host, ::part, ::slotted 같은 개념을 함께 이해해야 한다.

1. 기본 스타일 작성

Shadow DOM 내부에 style 태그를 넣으면 컴포넌트 내부에만 적용되는 CSS를 만들 수 있다.

class MyButton extends HTMLElement {
  connectedCallback() {
    const shadow = this.attachShadow({
      mode: 'open'
    });

    shadow.innerHTML = `
      <style>
        button {
          background: black;
          color: white;
          padding: 10px 16px;
          border: none;
          border-radius: 6px;
        }
      </style>

      <button>
        <slot></slot>
      </button>
    `;
  }
}

customElements.define('my-button', MyButton);

이 CSS는 Shadow DOM 내부의 button에만 적용된다.

외부에 있는 다른 button에는 영향을 주지 않는다.

2. 외부 CSS가 적용되지 않는 이유

일반 CSS는 페이지 전체에 영향을 줄 수 있다.

button {
  background: red;
}

하지만 Shadow DOM 내부 button에는 이 전역 CSS가 쉽게 적용되지 않는다.

Shadow DOM은 스타일을 격리하기 때문이다.

이 덕분에 컴포넌트 디자인이 외부 CSS 때문에 깨지는 문제를 줄일 수 있다.

3. :host란?

:host는 Shadow DOM을 가진 커스텀 요소 자기 자신을 선택하는 CSS 선택자다.

예를 들어 <my-button> 자체에 스타일을 적용하고 싶을 때 사용한다.

class MyButton extends HTMLElement {
  connectedCallback() {
    const shadow = this.attachShadow({
      mode: 'open'
    });

    shadow.innerHTML = `
      <style>
        :host {
          display: inline-block;
        }

        button {
          background: black;
          color: white;
          padding: 10px 16px;
        }
      </style>

      <button>
        <slot></slot>
      </button>
    `;
  }
}

customElements.define('my-button', MyButton);

:host는 여기서 <my-button> 요소 자체를 의미한다.

4. :host()로 속성별 스타일 주기

:host()를 사용하면 host 요소의 attribute에 따라 스타일을 바꿀 수 있다.

<my-button variant="primary">저장</my-button>
<my-button variant="danger">삭제</my-button>

컴포넌트 내부 CSS에서는 이렇게 작성할 수 있다.

<style>
  button {
    color: white;
    padding: 10px 16px;
    border: none;
  }

  :host([variant="primary"]) button {
    background: blue;
  }

  :host([variant="danger"]) button {
    background: red;
  }
</style>

:host([variant="primary"])는 커스텀 요소에 variant="primary"가 있을 때 적용된다.

버튼 종류, 크기, 상태를 나눌 때 유용하다.

5. CSS 변수란?

CSS 변수는 CSS 값을 이름으로 저장해두고 재사용하는 기능이다.

:root {
  --primary-color: blue;
}

button {
  background: var(--primary-color);
}

--primary-color가 CSS 변수다.

var(--primary-color)는 해당 변수 값을 사용한다는 뜻이다.

6. Shadow DOM에서 CSS 변수 사용하기

AD

제휴 광고 · 일부 링크는 수수료를 받을 수 있습니다

톨루나 팝업패널리워드 회원가입

CSS 변수는 Shadow DOM 내부 스타일을 외부에서 조절할 때 매우 유용하다.

class MyButton extends HTMLElement {
  connectedCallback() {
    const shadow = this.attachShadow({
      mode: 'open'
    });

    shadow.innerHTML = `
      <style>
        button {
          background: var(--button-bg, black);
          color: var(--button-color, white);
          padding: 10px 16px;
        }
      </style>

      <button>
        <slot></slot>
      </button>
    `;
  }
}

customElements.define('my-button', MyButton);

외부에서는 다음처럼 값을 바꿀 수 있다.

my-button {
  --button-bg: green;
  --button-color: white;
}

var(--button-bg, black)에서 black은 기본값이다.

외부에서 --button-bg를 지정하지 않으면 black이 사용된다.

7. ::part란?

::part는 Shadow DOM 내부의 특정 요소를 외부에서 스타일링할 수 있게 해주는 기능이다.

먼저 내부 요소에 part 속성을 지정한다.

shadow.innerHTML = `
  <button part="button">
    <slot></slot>
  </button>
`;

외부에서는 다음처럼 스타일을 적용할 수 있다.

my-button::part(button) {
  background: purple;
  color: white;
}

part="button"으로 공개한 요소만 외부에서 스타일링할 수 있다.

즉 컴포넌트 제작자가 수정 가능 영역을 직접 열어주는 방식이다.

8. ::slotted란?

::slotted는 slot으로 들어온 외부 콘텐츠를 스타일링할 때 사용한다.

shadow.innerHTML = `
  <style>
    ::slotted(span) {
      font-weight: bold;
    }
  </style>

  <button>
    <slot></slot>
  </button>
`;

사용 예시는 다음과 같다.

<my-button>
  <span>저장</span>
</my-button>

::slotted(span)은 slot으로 들어온 span 요소에 스타일을 적용한다.

9. 스타일링 전략 정리

Web Components에서 스타일링 방법은 상황에 따라 다르게 선택한다.

  • 기본 내부 스타일은 Shadow DOM 내부 style 태그로 작성한다.
  • 커스텀 요소 자체 스타일은 :host를 사용한다.
  • attribute 상태별 스타일은 :host([속성])을 사용한다.
  • 외부에서 색상이나 간격을 조절하려면 CSS 변수를 사용한다.
  • 특정 내부 요소를 외부에 열어주려면 ::part를 사용한다.
  • slot으로 들어온 콘텐츠를 스타일링하려면 ::slotted를 사용한다.

10. 정리

Web Components의 스타일링은 Shadow DOM의 격리 특성을 이해하는 것이 중요하다.

  • Shadow DOM 내부 CSS는 외부에 영향을 주지 않는다.
  • 외부 CSS도 Shadow DOM 내부에 쉽게 영향을 주지 못한다.
  • :host는 커스텀 요소 자기 자신을 선택한다.
  • :host()는 attribute 조건에 따라 스타일을 바꿀 수 있다.
  • CSS 변수는 외부에서 스타일 값을 주입할 때 유용하다.
  • ::part는 내부 요소 일부를 외부 스타일링 대상으로 공개한다.
  • ::slotted는 slot으로 들어온 콘텐츠를 스타일링한다.

다음 Part에서는 form과 Web Components를 연동하는 방법을 알아본다.

AD

제휴 광고

일부 링크는 제휴 링크이며, 구매 또는 가입 시 일정 수수료를 받을 수 있습니다.

AD

'Web components' 카테고리의 다른 글

전체보기