탐색

Directives

유틸리티와 믹스인

필요할 때 생성하는 유틸리티, 재사용 가능한 믹스인, 레이어에 속하는 네이티브 스타일을 정의합니다.

이 페이지의 내용

@utility는 필요할 때 생성할 클래스를 등록합니다. @mixin은 재사용할 CSS 본문에 이름을 붙이고 @apply는 호출 위치에서 이를 확장합니다. 네이티브 선택자는 일반 CSS로 유지됩니다. 형식을 선택하는 방법은 스타일 재사용에 있으며 이 페이지는 문법과 교체 규칙을 정의합니다.

@utility

최상위에서 클래스 형식을 명시적으로 선언합니다.

@utility card-layout {  display: grid;  gap: var(--spacing-md);  &:hover {    outline: 1px solid currentColor;  }}@utility col-gap-(--spacing) {  column-gap: var(--spacing);}@utility grid-cols(--cols <integer>) {  display: grid;  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));}

마크업에서 card-layout, col-gap-sm, grid-cols(3)@sm을 사용합니다. 헤더는 고정 클래스, 토큰 패턴, 함수 중 무엇을 등록할지 결정합니다. 각 형식은 그 형식만 등록하며 토큰 패턴이 함수 호출도 만들지는 않습니다. 선언이나 지원하는 중첩 규칙을 추가해도 등록은 바뀌지 않습니다.

유틸리티 이름이나 토큰 접두사에는 _를 넣을 수 없습니다. 클래스에서 _가 하위 선택자를 시작하므로 이런 정의는 소스 위치에서 오류를 보고합니다. 토큰 키에는 _를 넣을 수 있으며 var()에서 쓸 수 있는 유효한 변수로 남지만 단독 토큰 클래스나 자동 완성을 만들지는 않습니다. 믹스인 이름, 사용자 지정 속성, 네이티브 스타일시트 클래스에는 _를 계속 쓸 수 있습니다.

등록과 프리셋

테마는 토큰을 제공하고 유틸리티 정의는 그 토큰으로 생성할 클래스를 결정합니다. 전체 프리셋은 "@master/css"를 가져오세요. 스타일시트를 명시적으로 구성할 때는 자신의 토큰과 함께 "@master/css/utilities.css"를 불러올 수 있습니다.

전체 토큰과 속성 매핑은 계열 색인에, 해당 등록은 고정 유틸리티와 직접 숫자 값에 있습니다. 모두 여기서 설명하는 같은 정의 형식을 사용합니다.

토큰 패턴

패턴에는 끝의 자리표시자 하나가 있습니다. 매개변수는 토큰 네임스페이스를, 고정 부분은 클래스 접두사를 지정합니다. 타입 없는 자리표시자는 토큰 값을 바인딩합니다.

@utility p-(--spacing) {  padding: var(--spacing);}@utility m-(--spacing) {  margin: var(--spacing);}@utility fg-(--color) {  color: var(--color);}@utility size-(--spacing) {  width: var(--spacing);  height: var(--spacing);}

p-md는 var(--spacing-md)를 바인딩하고 size-md는 두 선언에 그 참조를 사용합니다. 일반 토큰은 브라우저가 평가하는 참조를 유지하고 inline 토큰은 선언 값을 한 번 치환합니다. 알 수 없는 토큰은 클래스를 만들지 않습니다. 값 패턴은 --를 포함하는 키를 비롯해 숫자와 유니코드 키를 허용합니다.

<string> 자리표시자는 토큰 키를 바인딩하여 보조 값을 명시적으로 참조할 수 있게 합니다.

@theme {  --text-hero: var(--font-size-5xl);  --text-hero--line-height: 1.15;  --text-hero--letter-spacing: -.03em;}@utility text-(--text <string>) {  font-size: var(ident("--text-" var(--text)));  line-height: var(ident("--text-" var(--text) "--line-height"), normal);  letter-spacing: var(ident("--text-" var(--text) "--letter-spacing"), normal);}

text-hero는 문자열 "hero"를 바인딩하며 일치하는 주 토큰이 필요합니다. --를 포함한 보조 키는 클래스를 만들지 않고 보조 값이 없으면 작성한 대체 값을 사용합니다. ident()는 정적으로 일반 CSS 식별자로 접힙니다. 네임스페이스는 매개변수에서 오므로 @utility type-(--text <string>)는 같은 토큰을 다른 클래스 접두사로 사용합니다. 토큰 자리표시자는 기본값이나 다른 타입을 허용하지 않습니다.

공유 접두사는 여러 네임스페이스를 명시적으로 제공할 수 있습니다.

@utility font-(--font-family) {  font-family: var(--font-family);}@utility font-(--font-size) {  font-size: var(--font-size);}@utility font-(--font-weight) {  font-weight: var(--font-weight);}

font-sans, font-sm, font-bold는 각각 해당 키가 있는 유일한 네임스페이스를 선택합니다. 여러 분기에 같은 키가 있으면 사용 시 AMBIGUOUS_TOKEN을 보고하며 CSS를 생성하지 않습니다. 키를 구분하거나 (font-size:var(--font-size-brand)) 같은 네이티브 선언을 사용하세요. 이 규칙은 문자열 키 레시피와 다중 선언 본문에도 적용됩니다. 음수와 불투명도는 유일한 분기를 선택한 뒤에만 검사합니다.

고정 클래스는 패턴보다 우선합니다. 예약되는 것은 토큰 키가 아닌 전체 클래스 표기입니다. 따라서 --text-center가 있어도 text-center는 text-align을 설정하지만 fg-solid, b-solid/.5, -mx-auto는 여전히 solid나 auto 토큰에 접근합니다. 패턴은 가장 긴 접두사를 사용하며 선택한 계열에 토큰이 없으면 짧은 접두사를 다시 시도하지 않고 오류를 보고합니다. 매개변수 네임스페이스가 다른 토큰 패턴은 접두사를 공유할 수 있습니다. 뒤의 패턴은 디코딩한 접두사와 네임스페이스가 같은 정의를 매개변수 모드, 본문, 소스, 의존성과 함께 완전히 교체합니다. 정적 등록과 함수 등록은 같은 형식과 이름의 정의를 독립적으로 교체합니다.

음수와 불투명도는 직접 값 부분집합에 적용됩니다. 타입 없는 자리표시자 하나와 전체 값이 var(--parameter)인 네이티브 선언 하나가 필요합니다. -m-md는 숫자 간격 토큰을 음수로 만들고 -p-md는 padding이 음수를 지원하지 않아 유효하지 않습니다. fg-red/.5는 색상 토큰에 0부터 1까지의 불투명도를 적용합니다. 일반 다중 선언이나 문자열 키 레시피에는 이 기능을 적용하지 않습니다.

네임스페이스 두 개가 일치해도 선언 두 개를 만들지 않음

이 사용자 정의 테마에는 두 토큰 키가 모두 있습니다. Master CSS는 클래스를 생성하기 전에 유일한 네임스페이스를 선택해야 합니다.

텍스트 설명
  1. --font-family-brand: monospace와 --font-size-brand: 2rem이 있으면 font-brand는 두 프리셋 font- 계열에 일치합니다.
  2. 결과는 AMBIGUOUS_TOKEN이며 해당 클래스의 CSS는 생성되지 않습니다. 분기는 결합되지 않습니다.
  3. 키를 구분하거나 (font-size:var(--font-size-brand)) 같은 명시적인 네이티브 선언을 사용하세요.

정적 인수

함수 유틸리티와 믹스인은 타입 없음, <integer>, <number>, <string>, <custom-ident> 위치 매개변수를 받습니다. 정적 기본값은 --cols <integer>: 2처럼 콜론을 사용합니다. 숫자는 숫자 리터럴이어야 하며 그리드 수와 스팬은 양의 정수여야 합니다. 문자열 인수는 따옴표가 필요합니다.

@utility pair(--size) {  width: var(--size);  height: var(--size);}

pair(2rem)처럼 사용합니다. 일반 함수 인수는 정적으로 알려져 있어야 합니다. 함수나 믹스인에 타입과 기본값이 없는 매개변수 하나와 전체 값이 var(--parameter)인 네이티브 선언 하나만 있으면 기호적 var() 식도 허용합니다. 호출자의 참조는 브라우저 평가를 위해 그대로 유지됩니다. 다른 함수는 외부 var(), attr(), 브라우저 의존 인수를 거부합니다. 알려진 외부 매개변수는 var(--parameter)로 전달할 수 있습니다.

A parameter utility

@utility pair(--size) { width: var(--size); height: var(--size); } @safelist 'pair(2rem)';
생성된 CSS
@layer utilities {  .pair\(2rem\) {    width: 2rem;    height: 2rem  }}

정적 레시피 인수와 실시간 CSS 값은 다름

그림의 pair 유틸리티는 두 선언을 가집니다. 별도의 단일 매개변수·단일 선언 기호 참조 예외는 적용되지 않습니다.

텍스트 설명
  1. @utility pair(--size) { width: var(--size); height: var(--size); }는 pair(2rem)의 알려진 인수를 받아 두 선언에 바인딩합니다.
  2. 이 레시피는 인수가 브라우저에 의존하는 pair(var(--size))를 거부합니다. 동적으로 유지할 값에는 명시적인 네이티브 선언 클래스를 사용하세요.
  3. (width:var(--size))는 브라우저를 위해 변수 참조를 유지하고 너비만 바꿉니다. 높이도 필요하면 별도 높이 선언을 추가하세요.

@mixin과 @apply

Master는 실험적인 CSS Mixins 명세의 정적 부분집합을 컴파일합니다. 정의는 이중 하이픈 이름을 사용하며 무조건적인 스타일시트 수준 규칙이어야 합니다. 믹스인은 CSS 재사용을 제공하며 Master 클래스를 등록하지 않습니다.

@mixin --caption {  font-size: var(--font-size-sm);  line-height: 1.5;}.caption {  color: currentColor;  @apply --caption;  font-weight: 600;}@utility caption {  @apply --caption;}

@apply는 네이티브 규칙, 유틸리티, 다른 믹스인 안에서 믹스인 호출 하나를 받습니다. 유틸리티 이름이나 클래스 목록은 받지 않습니다. 작성한 선언 위치에서 확장하며 중복, 중요도, 선택자, 조건, URL 소유권을 유지합니다.

매개변수는 &:hover와 조건 래퍼를 포함해 적용 요소에서 사용할 수 있습니다. 다른 요소에서의 매개변수 사용, 재할당, 선택자나 조건 보간, 재귀 정의, 오버로드, @private, 지원하지 않는 타입은 컴파일 오류입니다. 이 정적 부분집합은 브라우저 의존 매개변수 평가, 비공개 속성, 범용 함수를 구현하지 않습니다.

믹스인은 호출 위치에서 확장

삽입 앞뒤의 같은 줄은 정렬된 상태입니다. 선택자, 선언 순서, 바깥 레이어는 호출자의 것으로 유지됩니다.

텍스트 설명
  1. --caption 믹스인은 font-size: 14px와 line-height: 1.5를 제공합니다.
  2. .caption 안의 @apply --caption은 color: currentColor와 font-weight: 600 사이에서 확장됩니다.
  3. 확장은 클래스를 등록하거나 네이티브 규칙을 생성 레이어로 옮기지 않습니다. 중복 선언과 작성 순서를 유지합니다.

콘텐츠와 클래스 래퍼

@contents로 호출자의 선언이나 중첩 규칙이 재사용 래퍼에 들어갈 위치를 표시합니다.

@mixin --card-wide() {  @container card (width >= 40rem) {    @contents {      display: grid;    }  }}.card {  @apply --card-wide {    gap: 1rem;  }}

@contents;는 제공한 콘텐츠를 삽입합니다. @contents { … }는 호출이 블록을 생략했을 때만 대체 콘텐츠를 제공합니다. 명시적으로 빈 @apply --card-wide {}는 대체 콘텐츠를 억제합니다. 각 contents 위치는 블록을 한 번 삽입하고 선언, 중복, 중첩 규칙을 유지합니다. @contents가 없는 믹스인은 제공한 블록을 무시합니다.

contents 블록 생략과 빈 블록은 다름

믹스인에는 @contents { display: grid; }가 있습니다. 호출 위치의 중괄호가 의도적인 빈 블록과 생략을 구분합니다.

텍스트 설명
  1. @apply --panel;은 contents 블록을 생략하고 display: grid 대체 콘텐츠를 사용합니다.
  2. @apply --panel {}는 빈 블록을 제공해 대체 콘텐츠를 억제하며 이 예제에서는 선언을 추가하지 않습니다.
  3. @apply --panel { display: flex; }는 자신의 콘텐츠로 대체 콘텐츠를 바꾸며 두 display 선언을 병합하지 않습니다.

제공한 콘텐츠는 중첩 적용을 통해 전달해도 호출자의 매개변수 바인딩을 유지합니다. 대체 콘텐츠는 정의한 믹스인의 바인딩을 사용합니다. 일반 사용자 지정 속성은 네이티브 CSS 캐스케이드 동작을 유지합니다. 유한한 중첩 호출은 허용하지만 재귀 정의나 확장 깊이 및 노드 한도 초과는 오류입니다.

@mixin --hocus {  &:is(:hover, :focus-visible) {    @contents;  }}@utility emphasis {  color: red;  display: block;}
<button class="(color:red)@apply(--hocus)">Save</button><div class="grid-cols(3)@apply(--card-wide)"></div><div class="emphasis@apply(--hocus)!"></div>

@apply(--name(...))는 정적 인수를 받습니다. 여러 @ 래퍼는 왼쪽에서 오른쪽으로 중첩되므로 (color:red)@apply(--a)@apply(--b)는 --a를 --b 밖에 둡니다. 유틸리티는 선언을 하나의 블록으로 제공하므로 래퍼 자체 선언은 클래스당 한 번 출력됩니다. 선택자 접미사는 기존 위치를 유지하며 마지막 !는 확장한 모든 선언을 중요하게 표시합니다. 클래스 선두 부분과 @apply 이외의 조건 접미사가 클래스 순서를 정합니다. 각 외부 조건 분기는 독립적으로 정렬되는 규칙 하나입니다. 믹스인 내부 선택자와 조건은 출력 텍스트에 남고 클래스를 뒤쪽 단계로 옮기지 않으며 확장은 작성 순서를 유지합니다. 선언, 선택자, 조건을 추가하지 않는 확장은 단일 선언 유틸리티와 정렬되고 선두 부분이 (property:value)이면 네이티브 선언과 정렬됩니다. 나머지는 레시피로 정렬됩니다. 검사와 충돌 분석은 확장된 규칙을 사용합니다.

사용하지 않는 정의, 버려진 contents, 사용하지 않는 대체 블록은 토큰이나 키프레임을 유지하지 않습니다. 전달된 네이티브 @apply는 emitted-globals 계약을 통해 리소스 루트로 남습니다. 선언 위치와 상대 URL은 정의하거나 호출한 파일을 유지합니다.

래퍼가 호출자 선언을 배치

강조한 슬롯과 삽입 선언은 선택자 경계 안의 같은 위치에 있습니다. 래퍼는 선언의 적용 위치를 제어합니다.

텍스트 설명
  1. @mixin --hocus { &:is(:hover, :focus-visible) { @contents; } }는 명시적 contents 슬롯이 있는 선택자 래퍼를 정의합니다.
  2. underline@apply(--hocus)는 슬롯에 text-decoration-line: underline을 제공합니다. 출력 규칙은 어느 상태에서든 클래스 소유 요소에 일치합니다.
  3. 배치를 읽기 쉽도록 그림은 이스케이프 클래스 소유 요소를 &로 줄여 표시합니다. 생성 CSS는 전체 소유 요소를 유지합니다.

전체 정의 교체

뒤의 정의는 같은 등록의 본문 전체를 교체하며 선언을 병합하지 않습니다. 같은 이름의 정적 유틸리티와 함수 유틸리티는 별도 등록입니다. 토큰 패턴은 디코딩한 접두사와 네임스페이스가 같은 분기만 교체합니다.

@utility badge {  color: red;  padding: 1rem;}@utility badge {  color: blue;}

이제 badge는 color: blue만 출력합니다. 이전 padding과 그 의존성은 사라집니다.

뒤의 정의가 전체 등록을 교체

두 정의는 같은 정적 유틸리티를 등록합니다. 두 번째 정의가 첫 번째 정의 전체를 교체하므로 기존 padding도 남지 않습니다. 이는 생성 전 정의 교체이며 두 CSS 규칙의 캐스케이드 경쟁이 아닙니다.

텍스트 설명
  1. 첫 정적 badge 정의는 color: red와 padding: 1rem을 포함합니다.
  2. 뒤의 정적 badge 정의는 color: blue만 포함하며 첫 정의 전체를 교체합니다.
  3. badge를 사용하면 color: blue를 포함한 규칙 하나를 생성합니다. 이전 padding과 그 의존성은 남지 않습니다.
  4. 정적 등록과 함수 등록은 독립적입니다. 토큰 패턴은 접두사와 네임스페이스가 같은 분기만 교체하고 믹스인은 전체 명명 정의를 교체합니다.

믹스인 이름에는 매개변수 목록, 본문, 의존성을 포함한 최종 정의 하나만 있습니다. 빈 정의도 등록된 상태를 유지합니다. 전방 중첩 호출은 최종 레지스트리로 해석하며 매개변수 오버로드는 없습니다.

정적 이름과 함수는 별도 등록

경로는 등록의 정체성을 나타냅니다. 이름이 같아도 두 정의가 오버로드나 병합 본문이 되지 않습니다.

텍스트 설명
  1. @utility badge { display: inline-block; }는 정적 badge 클래스를 등록합니다. @utility badge(--inset) { padding: var(--inset); }는 별도 함수를 등록합니다.
  2. 정적 정의를 display: block으로 교체하면 badge가 바뀌지만 badge(8px)는 여전히 padding: 8px를 작성합니다.
  3. 교체는 같은 형식과 이름의 전체 본문에 영향을 줍니다. 함수는 정적 클래스의 대체 경로가 아닙니다.

정의 범위와 가져오기

@theme, @utility, @mixin, @custom-media, @custom-container는 최상위 정의입니다. 레이어나 조건 래퍼 안의 등록은 오류입니다. 믹스인 본문은 선언, 중첩 선택자, 지원하는 네이티브 조건, 중첩 @apply, @contents를 포함할 수 있습니다. 레이어 배치는 호출 위치에서 정합니다.

소스 스캔, 세이프리스트, 엔진 API, 런타임 DOM 변경의 클래스는 사용 루트입니다. 전달된 네이티브 CSS의 @apply도 루트지만 사용하지 않는 유틸리티나 믹스인 또는 전달하지 않은 @reference 스타일시트 안의 것은 아닙니다. 의존성 수집은 매개변수 바인딩과 ident() 접기 뒤에 수행됩니다. 사용하는 토큰은 선언 순서와 전이적 의존성을 유지합니다. 정적 토큰은 사용처가 없어도 루트로 남습니다. 마지막 루트를 제거하면 리소스를 해제하며 네이티브 CSS 리소스는 emittedGlobals로 고정됩니다.

런타임 manifest는 이후 DOM 클래스에 대비해 사용하지 않는 정의를 유지합니다. 온디맨드 생성은 CSS와 리소스 출력에 관한 것입니다. 네이티브 CSS 가지치기는 명시적으로 활성화해야 하며 키프레임은 선언 파일의 네이티브 보존 및 가지치기 정책을 공유합니다. 한정자 있는 가져오기는 네이티브 CSS만 포함해야 합니다. 정의는 한정자 없는 가져오기나 참조로 불러오세요.

네이티브 속성 우선순위

네이티브 (property:value) 클래스는 유틸리티 등록과 독립적으로 CSS 속성 의미를 유지합니다. 같은 조건에서 단일 선언 유틸리티와 네이티브 선언 클래스는 레시피의 일부를 재정의할 수 있습니다. 전체 정렬과 재정의 규칙은 선언과 값을 참고하세요.

네이티브 기본 스타일

네이티브 기본 스타일은 @layer defaults에 작성합니다.

네이티브 컴포넌트

네이티브 컴포넌트 선택자는 @layer components에 작성합니다.

@layer components {  .button {    display: inline-flex;    padding: var(--spacing-md);    &:focus-visible {      outline: 2px solid currentColor;    }  }}

네이티브 규칙은 스타일시트 가져오기 그래프에 따라 전달됩니다. 유틸리티 정의는 클래스 이름을 등록하고 믹스인 정의는 @apply를 통해 CSS 재사용을 제공합니다. 둘 다 컴파일 중 처리되며 사용할 때만 CSS를 출력합니다.

Sass 상호 운용

Sass를 사용할 때는 CSS 믹스인 정의를 .css 파일에 두세요. 현재 Dart Sass는 향후 CSS 지원을 위해 @mixin --name을 예약하고 Sass 믹스인으로는 거부합니다. Sass 호환성 공지를 참고하세요. SCSS 파일은 Master CSS가 컴파일하기 전에 보간으로 네이티브 at-rule을 출력할 수 있습니다.

@#{'mixin'} --card {  padding: 1rem;}.card { @apply --card; }

이는 Sass 보간이며 추가 Master CSS 구문이 아닙니다. Sass @include와 CSS @apply는 별개 구문으로 유지됩니다.

테마 선택자 래퍼

네이티브 선택자와 쿼리가 테마 재정의를 활성화합니다. 믹스인은 일치하는 클래스 조건을 제공할 수 있습니다.

@mixin --ocean {  &:where([data-theme="ocean"], [data-theme="ocean"] *) {    @contents;  }}

(color:white)@apply(--ocean)을 사용합니다. 섀도 호스트를 대상으로 할 때는 :host(...) 선택자를 명시적으로 추가하세요.