탐색

스타일 작성

스타일 재사용

함께 바뀌어야 할 내용에 따라 토큰, 컴포넌트 클래스, 유틸리티, 믹스인을 선택하고 로컬 변형은 쉽게 표현할 수 있게 유지합니다.

이 페이지의 내용

두 화면이 저장 버튼을 공유하면서 한 인스턴스에 더 넓은 간격을 줄 수 있습니다. 버튼의 공유 외형은 컴포넌트 클래스에 두고 로컬 조정은 마크업에 유지하세요. 더 작은 단위에도 같은 방법이 적용됩니다. 사용 측이 함께 바뀌어야 하는 값에는 이름을 붙이고 여러 규칙에 필요한 CSS 조각은 공유합니다.

먼저 설치와 문법 튜토리얼을 완료하세요. 아래 각 예제는 자체 CSS와 마크업을 제공합니다. 앱 스타일시트의 기존 프리셋 가져오기 뒤에 CSS를 추가하고 통합이 스캔하는 소스 파일에 마크업을 넣으세요:

app.css
@import '@master/css';

#컴포넌트의 공유 외형을 한곳에 유지하기

동작 버튼 같은 제품 역할에는 어디서 사용해도 알아볼 수 있는 외형이 필요합니다. @layer components의 네이티브 클래스로 역할을 정의하고 모든 인스턴스에 속하는 상태도 포함하세요.

같은 버튼의 로컬 간격 조정

@theme {  --spacing-action-x: 1rem;  --color-action: var(--color-surface-raised);}@layer components {  .action {    display: inline-flex;    align-items: center;    justify-content: center;    min-height: 2.375rem;    padding: .5rem var(--spacing-action-x);    border: 1px solid var(--color-line-divider);    border-radius: var(--radius-md);    background-color: var(--color-action);    color: var(--color-text-strong);    box-shadow: var(--shadow-sm);    font: inherit;    font-size: var(--font-size-sm);    font-weight: 400;    line-height: 1.2;    &:is(:hover, :focus-visible) {      box-shadow: var(--shadow-md);    }    &:active {      background-color: var(--color-surface-inset);      box-shadow: none;    }    &:focus-visible {      outline: 2px solid var(--color-text-strong);      outline-offset: 3px;    }  }}
생성된 CSS
@layer components {  .action {    min-height: 2.375rem;    padding: .5rem var(--spacing-action-x);    border: 1px solid var(--color-line-divider);    border-radius: var(--radius-md);    background-color: var(--color-action);    color: var(--color-text-strong);    box-shadow: var(--shadow-sm);    font: inherit;    font-size: var(--font-size-sm);    justify-content: center;    align-items: center;    font-weight: 400;    line-height: 1.2;    display: inline-flex;    &:is(:hover, :focus-visible) {      box-shadow: var(--shadow-md);    }    &:active {      background-color: var(--color-surface-inset);      box-shadow: none;    }    &:focus-visible {      outline: 2px solid var(--color-text-strong);      outline-offset: 3px;    }  }}@layer theme {  :root,  :host {    --color-zinc-5: oklch(96.5% .0011 265);    --color-zinc-40: oklch(68.6% .0028 265);    --color-zinc-60: oklch(48.6% .003 265);    --color-zinc-90: oklch(24.6% .0022 265);    --color-zinc-100: oklch(15% .0016 265)  }  :root,  :host {    --color-surface-inset: light-dark(var(--color-zinc-5), var(--color-zinc-100));    --color-surface-raised: light-dark(var(--color-white), var(--color-zinc-90));    --color-line-divider: light-dark(oklch(0% 0 none / .12), oklch(100% 0 none / .12));    --color-text-strong: light-dark(var(--color-zinc-100), var(--color-white));    --color-text-muted: light-dark(var(--color-zinc-60), var(--color-zinc-40))  }  :root,  :host {    --color-white: oklch(100% 0 none)  }  :root,  :host {    --font-size-xs: .75rem;    --font-size-sm: .875rem;    --text-xs: var(--font-size-xs);    --text-xs--line-height: 1.5;    --text-xs--letter-spacing: 0;    --radius-md: .375rem;    --spacing-sm: .75rem;    --spacing-lg: 1.5rem  }  :root,  :host {    --shadow-sm: 0 0 0 1px light-dark(oklch(0% 0 none / .04), oklch(100% 0 none / .05)), 0 1px 1px -.5px light-dark(oklch(0% 0 none / .045), oklch(0% 0 none / .3)), 0 2px 2px -1px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .26)), 0 4px 4px -2px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .24));    --shadow-md: 0 0 0 1px light-dark(oklch(0% 0 none / .05), oklch(100% 0 none / .06)), 0 1px 1px -.5px light-dark(oklch(0% 0 none / .045), oklch(0% 0 none / .3)), 0 2px 2px -1px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .26)), 0 4px 4px -2px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .24)), 0 8px 8px -4px light-dark(oklch(0% 0 none / .045), oklch(0% 0 none / .26))  }  :root,  :host {    --spacing-action-x: 1rem;    --color-action: var(--color-surface-raised)  }}@layer utilities {  .text-xs {    font-size: var(--text-xs);    line-height: var(--text-xs--line-height, normal);    letter-spacing: var(--text-xs--letter-spacing, normal)  }  .items-start {    align-items: start  }  .fg-text-muted {    color: var(--color-text-muted)  }  .flex {    display: flex  }  .flex-col {    flex-direction: column  }  .flex-wrap {    flex-wrap: wrap  }  .gap-lg {    gap: var(--spacing-lg)  }  .gap-sm {    gap: var(--spacing-sm)  }  .m\(0\) {    margin: calc(0 * 1px)  }  .px-lg {    padding-inline: var(--spacing-lg)  }}
가로 안쪽 여백을 비교하고 각 버튼에 마우스를 올리거나 Tab으로 이동하세요. 두 버튼은 동작 상태를 공유하며 두 번째만 px-lg를 사용합니다. 이 버튼은 스타일 예제이며 데이터를 저장하지 않습니다.

프리셋이 utilities 레이어를 components 뒤에 두므로 px-lg의 일반 유틸리티 선언이 컴포넌트 안쪽 여백보다 우선합니다. HTML 클래스 순서가 우선순위를 결정하지는 않습니다. 로컬 조정은 두 번째 버튼에 유지하고 모든 인스턴스에 필요할 때만 .action에 넣으세요. 경쟁 선언은 캐스케이드 레이어를 참고하세요.

하나의 정의와 두 사용처

두 버튼은 .action을 공유합니다. 안내선은 가로 안쪽 여백을 표시하며 컴포넌트는 양쪽 각각 1rem, px-lg는 1.5rem입니다. 파란 안내선은 주석이며 버튼 스타일이 아닙니다.

텍스트 설명
  1. 공유 정의. components 레이어의 네이티브 .action 규칙이 두 버튼에 외형, 상호작용 상태, 기본 안쪽 여백을 제공합니다.
  2. 첫 인스턴스. class="action"은 컴포넌트의 양쪽 각각 1rem인 가로 안쪽 여백을 사용합니다.
  3. 두 번째 인스턴스. class="action px-lg"는 양쪽 각각 1.5rem의 가로 안쪽 여백을 요청합니다. utilities 레이어는 components 뒤에 있으므로 px-lg가 이 인스턴스의 가로 안쪽 여백을 덮어쓰고 다른 컴포넌트 스타일은 유지됩니다. 그림의 파란 띠와 눈금은 안쪽 여백을 표시하는 검사 주석이며 유틸리티가 추가한 스타일이 아닙니다.

네이티브 컴포넌트 규칙은 기본적으로 스타일시트와 함께 출력되며 네이티브 가지치기는 명시적으로 활성화해야 합니다. 컴포넌트 상태는 CSS 규칙 안에 작성하세요. 네이티브 .action 정의는 action:hover 유틸리티를 등록하지 않습니다.

공유 외형과 공유 전달은 별도 결정입니다. 재사용 컴포넌트 때문에 관련 없는 페이지도 규칙을 불러온다면 CSS 전달 최적화를 참고하세요.

#함께 바뀌어야 할 내용 선택하기

반복되는 클래스 목록을 추출하기 전에 공유 결정을 파악하세요. 비슷하게 보이는 요소가 항상 함께 바뀌어야 하는 것은 아닙니다.

공유 대상사용 방식
스타일 간 값테마 토큰
제품 역할과 상태네이티브 컴포넌트 클래스
마크업에서 조합하는 기능유틸리티
CSS 안의 선언이나 래퍼믹스인

첫 예제는 동작 색상과 안쪽 여백에 각각 토큰을 줍니다. 다른 컴포넌트는 버튼 배경, 모양, 상태를 함께 가져오지 않고 CSS의 var() 또는 마크업의 px-action-x로 --spacing-action-x를 읽을 수 있습니다. 두 사용 측이 함께 바뀌어야 할 때 토큰을 수정하고 값만 우연히 같고 목적이 다르다면 별도 토큰을 사용하세요. 테마 토큰은 명명, 별칭, 범위별 재정의를 다룹니다.

반복되는 컴포넌트의 클래스 목록을 프레임워크 컴포넌트 내부에 유지할 수도 있습니다. 유용한 공유 스타일 계약을 제공할 때 CSS 이름을 도입하세요. 클래스 속성이 길다는 이유만으로 추출하지 마세요.

#스타일 기능을 위한 유틸리티 등록하기

여러 컨트롤이 내용이 가운데 정렬되고 작은 간격이 있는 인라인 행을 필요로 하지만 각자 외형과 여백을 유지한다고 가정해 보세요. 공유 레이아웃만 @utility로 등록합니다:

같은 레이아웃과 다른 컨트롤

@utility action-row {  display: inline-flex;  align-items: center;  justify-content: center;  gap: var(--spacing-xs);}
생성된 CSS
@layer theme {  :root,  :host {    --color-zinc-5: oklch(96.5% .0011 265);    --color-zinc-30: oklch(78% .0025 265);    --color-zinc-70: oklch(39.8% .0028 265);    --color-zinc-90: oklch(24.6% .0022 265);    --color-zinc-100: oklch(15% .0016 265)  }  :root,  :host {    --color-surface-inset: light-dark(var(--color-zinc-5), var(--color-zinc-100));    --color-surface-raised: light-dark(var(--color-white), var(--color-zinc-90));    --color-line-divider: light-dark(oklch(0% 0 none / .12), oklch(100% 0 none / .12));    --color-text-body: light-dark(var(--color-zinc-70), var(--color-zinc-30));    --color-text-strong: light-dark(var(--color-zinc-100), var(--color-white))  }  :root,  :host {    --color-white: oklch(100% 0 none)  }  :root,  :host {    --font-size-sm: .875rem;    --text-sm: var(--font-size-sm);    --text-sm--line-height: 1.5;    --text-sm--letter-spacing: 0;    --radius-md: .375rem;    --spacing-xs: .5rem;    --spacing-sm: .75rem;    --spacing-md: 1rem  }  :root,  :host {    --shadow-sm: 0 0 0 1px light-dark(oklch(0% 0 none / .04), oklch(100% 0 none / .05)), 0 1px 1px -.5px light-dark(oklch(0% 0 none / .045), oklch(0% 0 none / .3)), 0 2px 2px -1px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .26)), 0 4px 4px -2px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .24));    --shadow-md: 0 0 0 1px light-dark(oklch(0% 0 none / .05), oklch(100% 0 none / .06)), 0 1px 1px -.5px light-dark(oklch(0% 0 none / .045), oklch(0% 0 none / .3)), 0 2px 2px -1px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .26)), 0 4px 4px -2px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .24)), 0 8px 8px -4px light-dark(oklch(0% 0 none / .045), oklch(0% 0 none / .26))  }}@layer utilities {  .text-sm {    font-size: var(--text-sm);    line-height: var(--text-sm--line-height, normal);    letter-spacing: var(--text-sm--letter-spacing, normal)  }  .action-row {    display: inline-flex;    align-items: center;    justify-content: center;    gap: var(--spacing-xs)  }  .items-center {    align-items: center  }  .bg-surface-raised {    background-color: var(--color-surface-raised)  }  .b-line-divider {    border-color: var(--color-line-divider)  }  .r-md {    border-radius: var(--radius-md)  }  .b-solid {    border-style: solid  }  .b\(1\) {    border-width: calc(1 * 1px)  }  .shadow-sm {    box-shadow: var(--shadow-sm)  }  .fg-text-body {    color: var(--color-text-body)  }  .fg-text-strong {    color: var(--color-text-strong)  }  .flex {    display: flex  }  .flex-wrap {    flex-wrap: wrap  }  .gap-md {    gap: var(--spacing-md)  }  .py-xs {    padding-block: var(--spacing-xs)  }  .px-md {    padding-inline: var(--spacing-md)  }  .px-sm {    padding-inline: var(--spacing-sm)  }  .underline {    text-decoration-line: underline  }  .shadow-md\:hover:hover {    box-shadow: var(--shadow-md)  }  .fg-text-strong\:hover:hover {    color: var(--color-text-strong)  }  .bg-surface-inset\:active:active {    background-color: var(--color-surface-inset)  }}
action-row는 두 컨트롤에 같은 정렬과 간격을 줍니다. 다른 클래스는 외형을 제공합니다. Add note는 스타일 예제이고 Choose tokens는 테마 가이드를 엽니다.

완전한 클래스가 요청할 때 유틸리티가 규칙을 생성합니다. action-row@sm처럼 프리셋 유틸리티와 같은 선택자 및 조건 접미사도 받습니다. 이름은 레이아웃 기능을 설명하며 버튼 전체를 규정하지 않습니다.

기존 프리셋 유틸리티가 공유 결정을 표현한다면 그대로 사용하세요. 예를 들어 간격만 바꾸려면 gap-sm이나 gap(8)이면 되며 별도 사용자 지정 유틸리티는 필요하지 않습니다. 선언들이 호출자가 함께 재사용해야 할 유용한 기능을 이룰 때 레시피를 정의하세요. 유틸리티 계약은 등록과 교체를 정의합니다.

#믹스인으로 CSS 재사용하기

네이티브 CSS 규칙에 같은 행 레이아웃이 필요하면 믹스인을 정의하고 @apply로 확장하세요. 이 예제는 동작 버튼과 도구 모음 링크를 별도 컴포넌트 역할로 유지하면서 정렬을 공유합니다:

@mixin --action-row {  display: inline-flex;  align-items: center;  justify-content: center;  gap: var(--spacing-xs);}@layer components {  .action {    @apply --action-row;    padding: .5rem 1rem;    border: 1px solid var(--color-line-divider);    border-radius: var(--radius-md);    background-color: var(--color-surface-raised);    color: var(--color-text-strong);    box-shadow: var(--shadow-sm);    font: inherit;    font-size: var(--font-size-sm);  }  .toolbar-link {    @apply --action-row;    color: var(--color-text-body);    font: inherit;    font-size: var(--font-size-sm);    text-decoration-line: underline;  }}
<button type="button" class="action"><span aria-hidden="true">+</span> Add note</button><a href="/guide/theme" class="toolbar-link">Choose tokens <span aria-hidden="true">→</span></a>
생성된 CSS
@layer components {  .action {    display: inline-flex;    align-items: center;    justify-content: center;    gap: var(--spacing-xs);    padding: .5rem 1rem;    border: 1px solid var(--color-line-divider);    border-radius: var(--radius-md);    background-color: var(--color-surface-raised);    color: var(--color-text-strong);    box-shadow: var(--shadow-sm);    font: inherit;    font-size: var(--font-size-sm)  }  .toolbar-link {    display: inline-flex;    align-items: center;    justify-content: center;    gap: var(--spacing-xs);    color: var(--color-text-body);    font: inherit;    font-size: var(--font-size-sm);    text-decoration-line: underline  }}@layer theme {  :root,  :host {    --color-zinc-30: oklch(78% .0025 265);    --color-zinc-70: oklch(39.8% .0028 265);    --color-zinc-90: oklch(24.6% .0022 265);    --color-zinc-100: oklch(15% .0016 265)  }  :root,  :host {    --color-surface-raised: light-dark(var(--color-white), var(--color-zinc-90));    --color-line-divider: light-dark(oklch(0% 0 none / .12), oklch(100% 0 none / .12));    --color-text-body: light-dark(var(--color-zinc-70), var(--color-zinc-30));    --color-text-strong: light-dark(var(--color-zinc-100), var(--color-white))  }  :root,  :host {    --color-white: oklch(100% 0 none)  }  :root,  :host {    --font-size-sm: .875rem;    --radius-md: .375rem;    --spacing-xs: .5rem  }  :root,  :host {    --shadow-sm: 0 0 0 1px light-dark(oklch(0% 0 none / .04), oklch(100% 0 none / .05)), 0 1px 1px -.5px light-dark(oklch(0% 0 none / .045), oklch(0% 0 none / .3)), 0 2px 2px -1px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .26)), 0 4px 4px -2px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .24))  }}

생성된 CSS를 여세요. 행 선언은 두 네이티브 규칙에 모두 나타나고 각 규칙은 나머지 자체 선언을 유지합니다. --action-row를 정의해도 마크업 클래스는 생성되지 않습니다. @apply는 믹스인을 지정하며 유틸리티 클래스 목록을 받지 않습니다.

CSS와 마크업 모두 같은 기능이 필요하면 믹스인을 선언 소스로 유지하고 이를 호출하는 유틸리티를 추가하세요:

@utility action-row {  @apply --action-row;}

이 정의를 믹스인 예제의 스타일시트에 추가하세요. 앞의 독립 유틸리티 본문을 교체하므로 이제 --action-row 수정이 네이티브 컴포넌트와 유틸리티에 모두 전달됩니다. 전역 스타일에 따라 앱 진입점 그래프에서 정의를 정리하세요.

클래스를 소유하는 유틸리티와 선택자를 채우는 믹스인

상자는 CSS 산출물입니다. @apply 확장은 또 다른 마크업 클래스를 등록하지 않습니다.

텍스트 설명

stack 유틸리티를 요청하면 display:grid를 가진 .stack이 출력됩니다. .card 안에서 --stack 믹스인을 적용하면 같은 선언이 .card 아래 출력되며 선택자는 호출자가 소유합니다.

#contents로 래퍼 공유하기

반복되는 부분이 서로 다른 선언을 감싸는 조건인 경우도 있습니다. 호버 및 키보드 초점 믹스인이 선택자를 제공하고 각 호출자가 @contents로 스타일을 제공할 수 있습니다:

하나의 상호작용 래퍼와 두 호출 지점

@mixin --hocus {  &:is(:hover, :focus-visible) {    @contents;  }}@layer components {  .action {    @apply --hocus {      text-decoration-line: underline;    }  }}
생성된 CSS
@layer components {  .action:is(:hover, :focus-visible) {    text-decoration-line: underline  }}@layer theme {  :root,  :host {    --color-zinc-90: oklch(24.6% .0022 265);    --color-zinc-100: oklch(15% .0016 265)  }  :root,  :host {    --color-surface-raised: light-dark(var(--color-white), var(--color-zinc-90));    --color-line-divider: light-dark(oklch(0% 0 none / .12), oklch(100% 0 none / .12));    --color-text-strong: light-dark(var(--color-zinc-100), var(--color-white))  }  :root,  :host {    --color-white: oklch(100% 0 none)  }  :root,  :host {    --font-size-sm: .875rem;    --text-sm: var(--font-size-sm);    --text-sm--line-height: 1.5;    --text-sm--letter-spacing: 0;    --radius-md: .375rem;    --spacing-xs: .5rem;    --spacing-md: 1rem  }  :root,  :host {    --shadow-sm: 0 0 0 1px light-dark(oklch(0% 0 none / .04), oklch(100% 0 none / .05)), 0 1px 1px -.5px light-dark(oklch(0% 0 none / .045), oklch(0% 0 none / .3)), 0 2px 2px -1px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .26)), 0 4px 4px -2px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .24))  }}@layer utilities {  .text-sm {    font-size: var(--text-sm);    line-height: var(--text-sm--line-height, normal);    letter-spacing: var(--text-sm--letter-spacing, normal)  }  .underline\@apply\(--hocus\):is(:hover, :focus-visible) {    text-decoration-line: underline  }  .bg-surface-raised {    background-color: var(--color-surface-raised)  }  .b-line-divider {    border-color: var(--color-line-divider)  }  .r-md {    border-radius: var(--radius-md)  }  .b-solid {    border-style: solid  }  .b\(1\) {    border-width: calc(1 * 1px)  }  .shadow-sm {    box-shadow: var(--shadow-sm)  }  .fg-text-strong {    color: var(--color-text-strong)  }  .flex {    display: flex  }  .flex-wrap {    flex-wrap: wrap  }  .gap-md {    gap: var(--spacing-md)  }  .outline-offset\(3\) {    outline-offset: calc(3 * 1px)  }  .py-xs {    padding-block: var(--spacing-xs)  }  .px-md {    padding-inline: var(--spacing-md)  }  .outline-solid\:focus-visible:focus-visible {    outline-style: solid  }  .outline\(2\)\:focus-visible:focus-visible {    outline-width: calc(2 * 1px)  }}
어느 버튼이든 마우스를 올리거나 Tab으로 이동하면 레이블에 밑줄이 생깁니다. 첫 번째는 네이티브 CSS 안에서 선언을 제공하고 두 번째는 underline 유틸리티를 감쌉니다. 초점 외곽선은 별도로 지정됩니다.

CSS에서는 @apply --hocus 뒤의 블록이 @contents를 채웁니다. 마크업에서는 @apply(--hocus)가 해당 클래스에서 생성된 선언을 감쌉니다. 래퍼는 토큰을 등록하거나 인접 클래스를 본문에 모으지 않습니다. 선언 집합을 재사용하려면 유틸리티나 믹스인을 사용하세요. 공유 선택자나 조건 안에 넣을 내용을 호출자가 선택해야 할 때 contents를 사용합니다. 전달과 폴백 동작은 믹스인 contents를 참고하세요.

#호출자에게 필요할 때 매개변수 노출하기

공유 컨트롤 크기는 여러 속성을 조율할 수 있습니다. 별도 프리셋 유틸리티로 인해 호출자가 계산을 반복해야 한다면 매개변수로 이 관계를 표현하세요:

하나의 크기로 높이와 안쪽 여백 제어하기

@utility action-size(--height: 2.5rem) {  min-height: var(--height);  padding-inline: calc(var(--height) / 2);}
생성된 CSS
@layer theme {  :root,  :host {    --color-zinc-90: oklch(24.6% .0022 265);    --color-zinc-100: oklch(15% .0016 265)  }  :root,  :host {    --color-surface-raised: light-dark(var(--color-white), var(--color-zinc-90));    --color-line-divider: light-dark(oklch(0% 0 none / .12), oklch(100% 0 none / .12));    --color-text-strong: light-dark(var(--color-zinc-100), var(--color-white))  }  :root,  :host {    --color-white: oklch(100% 0 none)  }  :root,  :host {    --font-size-sm: .875rem;    --text-sm: var(--font-size-sm);    --text-sm--line-height: 1.5;    --text-sm--letter-spacing: 0;    --radius-md: .375rem;    --spacing-md: 1rem  }  :root,  :host {    --shadow-sm: 0 0 0 1px light-dark(oklch(0% 0 none / .04), oklch(100% 0 none / .05)), 0 1px 1px -.5px light-dark(oklch(0% 0 none / .045), oklch(0% 0 none / .3)), 0 2px 2px -1px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .26)), 0 4px 4px -2px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .24))  }}@layer utilities {  .text-sm {    font-size: var(--text-sm);    line-height: var(--text-sm--line-height, normal);    letter-spacing: var(--text-sm--letter-spacing, normal)  }  .action-size\(\) {    min-height: 2.5rem;    padding-inline: calc(2.5rem / 2)  }  .action-size\(3rem\) {    min-height: 3rem;    padding-inline: calc(3rem / 2)  }  .items-center {    align-items: center  }  .bg-surface-raised {    background-color: var(--color-surface-raised)  }  .b-line-divider {    border-color: var(--color-line-divider)  }  .r-md {    border-radius: var(--radius-md)  }  .b-solid {    border-style: solid  }  .b\(1\) {    border-width: calc(1 * 1px)  }  .shadow-sm {    box-shadow: var(--shadow-sm)  }  .fg-text-strong {    color: var(--color-text-strong)  }  .flex {    display: flex  }  .flex-wrap {    flex-wrap: wrap  }  .gap-md {    gap: var(--spacing-md)  }}
action-size()는 2.5rem을, action-size(3rem)은 3rem을 사용합니다. 최소 높이와 가로 안쪽 여백 모두 인수를 따릅니다. 이 버튼은 크기만 시연합니다.

하나의 정의와 개별 호출 값

루트 크기 16px에서 최소 높이는 40px와 48px이며 padding-inline은 선택한 높이의 절반입니다. 강조된 안쪽 영역은 측정 안내선입니다.

텍스트 설명

같은 action-size 유틸리티를 기본값 2.5rem과 3rem으로 호출합니다. 두 번째 컨트롤은 최소 높이와 가로 안쪽 여백이 더 크며 두 컨트롤은 각각의 인수를 유지합니다.

빈 호출은 선언된 기본값을 사용합니다. 인수는 컴파일 중에 알려져 있어야 하므로 크기를 선택할 때 완전한 클래스 문자열을 사용하세요. JavaScript에서 연속적으로 바뀌는 값은 대신 네이티브 CSS 사용자 지정 속성에 둡니다. 매개변수 계약에 허용 타입과 제한이 설명되어 있습니다.

공유 정의를 바꾸기 전에 로컬 재정의가 있는 인스턴스를 포함해 최소 두 호출 지점을 비교하세요. 호버와 키보드 상태를 확인하고 생성 CSS를 검사합니다. 호출자에게 같은 동작이 더 이상 필요하지 않다면 모든 인스턴스에 예외를 추가하지 말고 정의를 분리하세요. 프로젝트 간 안정적인 어휘 공유는 패키지 작성으로 이어집니다.