Design TokensP2 본문

머티리얼 테마

표면 머티리얼을 전환 가능한 테마 축(data-wds-material)으로 관리합니다. Solid(기본)·Liquid Glass(regular·clear 변형)와 향후 머티리얼. 컴포넌트는 중립 surface 계약(data-wds-surface)만 노출하고, 테마 레이어가 모양을 결정합니다.

마지막 업데이트 2026-06-14

머티리얼 테마#

표면 머티리얼을 전환 가능한 테마 축(data-wds-material)으로 관리합니다. light/dark(data-theme)와 직교하는 별도 축이며, 컴포넌트는 머티리얼을 모릅니다 — 표면에 중립 계약 data-wds-surface만 노출하고, 모양은 테마 레이어가 결정합니다(Radix panelBackground·Storybook data-attribute 모델).

미리보기 모드

Solid기본

자기 완결 표면

그림자와 불투명 surface만으로 깊이를 만드는 기본 머티리얼. 뒤 콘텐츠에 기대지 않아 어떤 배경 위에서도 대비가 일정합니다.

쓰임
패널 · 카드 · 시트 · 콘텐츠 기본 표면
표면그림자
레시피
surface-raised불투명shadow-lg

data-wds-material 미스코프 · 이미 불투명이라 reduced-transparency 영향 없음

Liquid Glass

비치는 깊이 표면

surface 틴트·backdrop blur에 채도(saturate)와 굴절(refraction)을 얹어 뒤 콘텐츠가 렌즈처럼 휘며 비치는 Liquid Glass 머티리얼. 표면 역할에 따라 두 변형으로 갈립니다.

쓰임
메뉴 · 팝오버 · 오버레이 · 떠 있는 시트
surface 틴트blur채도굴절
regular · 가독 우선
overlaysurface-container-low82%blur 16pxsaturate 1.6×굴절 13pxshadow-md
clear · 콘텐츠 위
floatingsurface-container-lowest60%blur 24pxsaturate 1.8×굴절 22pxshadow-sm

data-wds-material="liquid-glass" · reduced-transparency: 불투명 surface 폴백 + blur·굴절 제거

표면 변형 (regular · clear)#

한 머티리얼 테마는 **표면 역할별 변형(variant)**을 가질 수 있습니다 — 같은 머티리얼이 어떤 surface 계약에 붙느냐로 갈립니다. Liquid Glass는 두 변형을 가집니다.

  • regular (data-wds-surface="overlay") — 텍스트가 얹히는 패널·시트·고정 헤더. 틴트가 진해(82%) 배경 위에서도 가독을 우선하고, 채도 1.6×·굴절 13px로 절제합니다.
  • clear (data-wds-surface="floating") — 미디어·콘텐츠 위에 떠 배경이 더 비치는 표면. 틴트가 옅고(60%) blur가 강하며(24px), 채도 1.8×·굴절 22px(+미세 색수차)로 렌징이 또렷합니다. 60% 틴트라 본문·보조 텍스트(text-muted·text-subtle)는 금지 — full-strength text 또는 비텍스트 컨트롤만 얹습니다(가독 본문은 regular).

Solid은 단일 기본 표면이라 변형이 없습니다. 변형은 테마가 아니라 surface 계약의 차이이므로, 오버레이 컴포넌트는 자기 역할에 맞는 data-wds-surface 값만 고르면 테마 레이어가 알맞은 변형으로 칠합니다.

현재 배선 상태. regular(overlay)는 실물 오버레이 컴포넌트(Modal·Drawer·Popover·DropdownMenu)가 부착하고, clear(floating)는 Carousel의 오버레이 컨트롤 모드 (controls="overlay")가 슬라이드 위 컨트롤에 부착합니다. 위 갤러리의 두 패널은 각 계약을 미리 보여주는 견본입니다.

라이브 컨피규레이터#

컨트롤(배경·굴절·surface 티어·opacity·blur·saturate·shadow·모드)을 조작하면 프리뷰가 실시간으로 바뀌고, 아래 material.json 항목과 생성될 .wds-material-* CSS가 같은 값으로 갱신됩니다. 굴절 슬라이더는 feDisplacementMap의 변위 강도(scale)를 실시간으로 조절합니다 — 굴절은 디테일 있는 사진 배경에서 또렷이 보이므로(매끈한 그라데이션은 변위가 거의 안 보임) 배경 선택지에 사진을 두었습니다. tokens/core/material.json에 항목을 넣으면 그 값의 .wds-material-* 유틸 클래스가 자동 생성됩니다(직접 적용 경로). 이를 테마 스위처로 전환하려면 emit-cssMATERIAL_SURFACE_BINDINGS에 surface 계약 바인딩 한 줄을 더하세요.

머티리얼
모드
미리보기
surface-container-low42%blur 9pxsaturate 1.7×shadow md굴절 135
배경 — 굴절은 사진에서 또렷이 보임
굴절 — feDisplacementMap scale 135 (Chromium)
surface 티어
opacity — 틴트 42%
blur — 9px
saturate — 비브런시 1.7×
shadow
접근성 적응 — prefers-reduced-transparency
생성 코드
// tokens/core/material.json — 새 변형
"my-material": {
  "$value": {
    "surface": "{color.surface-container-low}",
    "shadow": "{shadow.md}",
    "blur": "9px",
    "opacity": 0.42,
    "saturate": 1.7,
    "refraction": 135
  }
}

/* emit-css 산출 — .wds-material-my-material (P0 채도 = base) */
.wds-material-my-material {
  background-color: color-mix(in srgb, var(--wds-color-surface-container-low) 42%, transparent);
  -webkit-backdrop-filter: blur(9px) saturate(1.7);
  backdrop-filter: blur(9px) saturate(1.7);
  box-shadow: var(--wds-shadow-md);
}

/* P1 굴절+반사 림광 — refraction(feDisplacementMap scale)을 SVG 필터로 굴절. opt-in 스코프
   ([data-wds-glass='refraction']) + @supports(SVG def 필요). 더 맑은 Apple 렌즈 = blur 0.55×·채도
   강화. 투명도 감소·고대비 미설정 시에만 — 둘 중 하나라도 켜지면 복합 미디어가 자동 해제. */
@media (prefers-reduced-transparency: no-preference) and (prefers-contrast: no-preference) {
  [data-wds-glass='refraction'] .wds-material-my-material {
    box-shadow: var(--wds-shadow-md), inset 0 1px 0 0 color-mix(in srgb, white 55%, transparent), inset 0 0 0 1px color-mix(in srgb, white 10%, transparent);
  }
  @supports (backdrop-filter: url('#wds-glass-refraction-regular')) {
    [data-wds-glass='refraction'] .wds-material-my-material {
      backdrop-filter: url(#wds-glass-refraction-regular) blur(5px) saturate(1.9);
    }
  }
}

/* 접근성 적응 — 투명도 감소: 불투명 폴백 + blur·채도·굴절 제거(같은 backdrop-filter라 한 번에) */
@media (prefers-reduced-transparency: reduce) {
  .wds-material-my-material {
    background-color: var(--wds-color-surface-container-low);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}
/* 고대비: 틴트 대비 보강 보더 */
@media (prefers-contrast: more) {
  .wds-material-my-material { outline: 1px solid var(--wds-color-border); outline-offset: -1px; }
}

작동 방식#

세 조각으로 분리됩니다.

  1. surface 계약 — 컴포넌트는 표면에 data-wds-surface="overlay" 같은 중립 훅만 부착합니다(머티리얼·blur 무지).
  2. 테마 레이어(codegen) — emit-css[data-wds-material="liquid-glass"] [data-wds-surface="overlay"](regular)·[…="floating"](clear) 스코프 규칙을 머티리얼 토큰에서 생성합니다. solid(기본)는 컴포넌트 표면이 담당하므로 emit하지 않습니다(미스코프 = 기본).
  3. 스코프 적용 — 조상에 data-wds-material을 세팅하면 그 하위 surface가 해당 머티리얼로 전환됩니다. specificity로 컴포넌트 기본 표면을 덮어씁니다.
<div data-wds-material="liquid-glass">
  <!-- 이 안의 data-wds-surface 표면이 글래스로 전환 -->
  <Modal />
  <DropdownMenu />
</div>

구현 규칙 — 둥근 모서리 위 글래스 합성#

글래스 표면의 엣지 라이트(반사 림)는 backdrop blur·border-radius와 _같은 요소_의 box-shadow 그립니다. 별도 ::before나 오버레이 레이어로 림을 그리면, 그 레이어의 안티앨리어싱된 둥근 가장자리가 카드의 backdrop 클립 가장자리와 모서리에서 1px 미만으로 어긋나 두 개의 호("이중 모서리")로 보입니다 — 마스크든 box-shadow든 별도 레이어이면 동일합니다. 직선 변에서는 묻히고 곡률이 집중되는 모서리에서만 드러나므로 고배율(5–6×) 영역 캡처로만 검출됩니다(요소만 찍으면 박스 밖 겹침이 잘려 안 보입니다). 같은 요소에 통합하면 가장자리가 하나라 겹침이 원천적으로 없습니다.

모서리 반지름·곡률파운데이션 라운딩(radius 토큰·동심·연속 곡률)이 정의하는 _기하_의 규칙입니다. 위 규칙은 그와 직교하는 _합성_의 규칙입니다 — 같은 곡률을 몇 개의 레이어로 그리느냐. 곡률 공식이 옳아도 합성이 어긋나면 모서리가 겹쳐 보입니다.

플레이그라운드에서 적용#

오버레이 컴포넌트(Modal·Drawer·Popover·DropdownMenu) 플레이그라운드의 "테마 미리보기" 스위처에서 Solid ↔ Liquid Glass를 바꿔 바로 확인할 수 있습니다. 스위처는 data-wds-material을 문서 루트에 적용해, 포털로 렌더되는 오버레이(Modal·Drawer)까지 전환합니다. 이 컴포넌트들은 모두 data-wds-surface="overlay"라 플레이그라운드에서는 regular 변형만 미리보입니다(clearCarousel 오버레이 컨트롤·위 갤러리 견본 참고).

새 머티리얼·변형 추가#

토큰 등록과 surface 바인딩은 별개입니다 — material.json 항목만으로 .wds-material-* 유틸 클래스는 자동으로 생기고(직접 적용), 테마 스위처로 전환하려면 바인딩이 추가로 필요합니다.

  • 새 머티리얼(테마)tokens/core/material.json에 변형을 정의하고 emit-cssMATERIAL_SURFACE_BINDINGS에 한 줄(머티리얼 × surface → 토큰)을 추가합니다.
  • 기존 테마의 새 변형 — 같은 머티리얼에 다른 surface 계약을 한 줄 더 바인딩합니다(예: liquid-glass × floating → material.clear). 새 data-wds-surface 계약명은 오버레이 컴포넌트가 붙이는 공개 계약이므로 한 번 정하면 신중히 유지합니다.

컴포넌트 변경 0 — 바인딩이 늘면 해당 surface 계약을 쓰는 모든 표면에 자동 적용됩니다.

접근성#

테마 레이어에 적응이 내장됩니다. prefers-reduced-transparency에서 불투명 surface로 폴백하며 blur·채도 ·굴절을 모두 제거하고(같은 backdrop-filter 선언이라 한 번에), prefers-contrast: more에서 보더를 추가합니다(Apple "머티리얼이 접근성 설정에 적응" 모델). 채도 강화(saturate)는 기본 frosted floor에 얹혀 모든 글래스에 적용되지만, 굴절(refraction)과 반사 림광은 비필수 장식이라 [data-wds-glass="refraction"] opt-in 스코프 + @supports로만 활성화됩니다 — SVG 필터 def가 주입된 곳에서만 켜지고(미존재 def가 backdrop-filter를 무효화하는 함정 차단), 투명도 감소·고대비 어느 쪽이든 켜져 있으면 자동 해제됩니다. 미지원 엔진(Safari·Firefox)은 굴절 없이 frosted+채도로 곱게 폴백합니다. 머티리얼은 어느 적응에서도 콘텐츠 가독성을 우선합니다. 라이브 컨피규레이터의 접근성 적응 토글로 폴백을 직접 미리볼 수 있습니다.

플랫폼 범위#

머티리얼 테마 축은 현재 웹 전용입니다 — backdrop-filter blur와 color-mix 틴트, 그리고 prefers-reduced-transparency/prefers-contrast 적응이 웹 플랫폼에 특화되어 있기 때문입니다. material.json이 토큰 SSOT지만 Flutter(wiz_ui)로는 emit되지 않습니다(elevation Phase 1과 동일한 경계). Flutter 글래스 등가물(BackdropFilter)은 실제 모바일 제품 표면이 글래스를 요구하거나 B5-4 P5 (elevation+material 합동 포팅)에 도달할 때 포팅합니다 — BackdropFilter는 saveLayer 성능 비용이 크고, Flutter엔 prefers-reduced-transparency 등가가 없어 a11y 계약을 새로 설계해야 하므로 단순 포팅이 아닙니다.