CSS 폼 컨트롤 스타일링 레벨 1

W3C 최초 공개 작업 초안,

이 문서에 대한 자세한 정보
이 버전:
https://www.w3.org/TR/2025/WD-css-forms-1-20250325/
최신 발행 버전:
https://www.w3.org/TR/css-forms-1/
편집자 초안:
https://drafts.csswg.org/css-forms-1/
이력:
https://www.w3.org/standards/history/css-forms-1/
피드백:
CSSWG 이슈 저장소
명세 내 인라인
편집자:
(Apple Inc.)
이 명세에 대한 수정 제안:
GitHub 편집기

초록

이 CSS 모듈은 폼 컨트롤과 그 여러 부분을 스타일링하는 다양한 방법을 정의한다.

CSS는 구조화된 문서 (예: HTML 및 XML) 를 화면, 종이 등에 렌더링하는 방식을 설명하기 위한 언어이다.

이 문서의 상태

이 절은 이 문서가 발행된 시점의 상태를 설명한다. 현재 W3C 발행물의 목록과 이 기술 보고서의 최신 개정판은 https://www.w3.org/TR/의 W3C 표준 및 초안 색인에서 찾을 수 있다.

이 문서는 CSS 작업 그룹에 의해 권고안 트랙을 사용하여 최초 공개 작업 초안으로 발행되었다. 최초 공개 작업 초안으로 발행되었다고 해서 W3C와 그 회원들의 승인을 의미하는 것은 아니다.

이 문서는 초안 문서이며 언제든지 다른 문서에 의해 갱신, 대체 또는 폐기될 수 있다. 이 문서를 진행 중인 작업 이외의 것으로 인용하는 것은 부적절하다.

피드백은 GitHub에 이슈를 제출하여 보내는 것이 좋으며(권장), 제목에 다음과 같이 명세 코드 “css-forms”를 포함해야 한다: “[css-forms] …의견 요약…”. 모든 이슈와 의견은 보관된다. 또는, 피드백은 (보관된) 공개 메일링 리스트 www-style@w3.org로 보낼 수 있다.

이 문서는 2023년 11월 03일 W3C 프로세스 문서의 적용을 받는다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에 의해 작성되었다. W3C는 그룹의 산출물과 관련하여 이루어진 모든 특허 공개의 공개 목록을 유지하며, 해당 페이지에는 특허 공개 방법에 대한 지침도 포함되어 있다. 개인이 그 개인이 믿기에 필수 청구항을 포함하는 특허에 대해 실제로 알고 있는 경우, 그 개인은 W3C 특허 정책의 6절에 따라 해당 정보를 공개해야 한다.

1. 소개

이 절은 비규범적이다.

사용자 에이전트는 오래전부터 폼 컨트롤을 스타일링하는 비표준적인 방법을 제공해 왔다. 그러나 이러한 모든 컨트롤은 사용자 에이전트마다 일관되지 않게 구현되어, 작성자에게 불필요한 마찰을 만들어낸다.

이 모듈은 상호운용 가능하게 사용할 수 있을 만큼 충분히 자세하게 일련의 폼 컨트롤 부분을 정의하는 것을 목표로 한다.

또한 폼 컨트롤을 사용자 지정하는 새로운 방법도 정의하며, 이전에는 사용자 지정 컨트롤을 처음부터 구현해야만 가능했던 일반적인 사용 사례를 다룬다. 이는 많은 작업이 필요하고, 올바르게 구현하기 어려우며, 접근성이나 플랫폼 규약을 깨뜨리는 경우가 많았다.

2. 기본 모양으로 선택적으로 전환하기: appearance: base

appearance의 정의를 여기로 옮긴다.

이름: appearance
새 값: base

폼 컨트롤에 적용되면, base는 해당 컨트롤을 기본 모양 상태로 둔다.

기본 모양을 가진 컨트롤은 표준 CSS와 아래에 정의된 의사 요소를 사용하여 일관되게 스타일링할 수 있으며, UA 전반에서 일관된, 재정의 가능한 기본 스타일을 적용한다. 컨트롤이 그 상태에 있을 때, 사용자 에이전트는 부록 A: 기본 모양 사용자 에이전트 스타일시트의 스타일을 해당 컨트롤에 적용한다.

사용자 에이전트는 또한 § 4 의사 요소에서 정의한 의사 요소를 활성화해야 한다. 이러한 의사 요소(::picker() 제외)는 항상 그 원천 요소에서 appearance를 상속한다. 사용자 에이전트는 이를 appearance: inherit !important 선언으로 구현할 수 있다.

NOTE: 이 상속은 작성자가 같은 컨트롤에 대해 네이티브 부분과 비네이티브 부분을 섞는 것을 방지한다.

2.1. 기본 모양을 위한 설계 원칙

다음 설계 원칙은 폼 컨트롤의 기본 모양 스타일시트의 설계에 적용되며, 중요도가 높은 순서대로 나열한다:

  1. 스타일은 모든 사용자 에이전트에서 동일하다.

  2. 컨트롤은 추가 스타일 없이도 그 자체로 인식 가능하고 사용할 수 있다.

  3. 컨트롤은 WCAG 2.2 AA 표준을 100% 통과한다.

  4. 스타일은 컨트롤 전반에서 일관된다…

    1. …외형과 느낌에서.

    2. …코드에서 정의되는 방식에서.

    3. …크기 조정과 상호작용에서.

  5. 복잡한 리셋 스타일시트 없이도 웹사이트의 브랜딩에 쉽게 맞출 수 있다:

    1. 최소한의 코드를 사용하며 쉽게 재정의할 수 있다.

    2. 자체적으로 강한 voice & tone을 갖지 않으며, 시각적으로 가능한 한 단순하다.

    3. 가능할 때마다 새 스타일을 정의하기보다 페이지 스타일을 상속한다.

    4. 조정에 강건하다…

      1. …자체가 변경될 때(예: 글꼴, 테두리, 레이아웃 변경).

      2. …문맥 안에 놓일 때(예: flex 또는 grid 자식이 될 준비가 되어 있음).

  6. 포괄적이다:

    1. 각 컨트롤의 모든 상태를 포함한다.

    2. 모든 쓰기 모드와 색 구성표를 지원한다.

특히 HTML 폼 컨트롤의 경우, 이러한 원칙은 부록 A: 기본 모양 사용자 에이전트 스타일시트에 정의된 필수 사용자 에이전트 스타일시트를 통해 적용된다.

2.2. 예제

구현, 실험, bikeshedding 및 사용자 에이전트 스타일시트 개선을 통해 이 예제들을 다듬는다.

이 예제들의 주된 목적은 기본 모양을 위한 설계 원칙이 실제로 어떻게 적용되는지 보여주는 것이다.

개별 컨트롤에 기본 모양을 적용하려면 다음 코드를 사용한다:

input, textarea, meter, progress, button, select {
  appearance: base;
}

NOTE: 다음 예제에서 사용되는 폼 레이아웃은 자세히 설명하지 않는다.

2.2.1. 기본 사용자 에이전트 색상

다음은 루트 요소에서 기본 라이트 및 다크 모드 색상을 각각 상속받는 기본 모양 색상이다:

라이트 색 구성표의 기본 모양 스크린샷 다크 색 구성표의 기본 모양 스크린샷

2.2.2. 색상/글꼴 사용자 지정

다음은 기본 모양 위에서 수행되는 사용자 지정의 몇 가지 예이다:

form {
  font-family: "American Typewriter";
  background-color: rgb(254, 252, 221);
  color: rgb(131, 17, 0);
}

input, textarea, meter, progress, button, select {
  appearance: base;
}

갈색 텍스트와 옅은 노란색 배경을 가진 사용자 지정 기본 모양의 스크린샷

form {
  font-family: "Courier New";
  font-size: 14px;
  background-color: rgb(0, 0, 0);
  color: rgb(0, 249, 0);
}

input, textarea, meter, progress, button, select {
  appearance: base;
}

녹색 텍스트와 검은색 배경을 가진 사용자 지정 기본 모양의 스크린샷

3. 피커 스타일링

3.1. ::picker() 의사 요소

::picker() 의사 요소는 페이지 밖으로 튀어나오는 폼 컨트롤의 부분을 나타낸다.

::picker() = ::picker( <form-control-identifier>+ )
<form-control-identifier> = select

::picker() 의사 요소는 원천 요소기본 모양을 지원하고 팝업 피커를 가질 때에만 일치한다. 지정된 <form-control-identifier>는 또한 원천 요소고유 피커 이름과 일치해야 한다. 예를 들어, select 요소의 고유 피커 이름select이다.

::picker() 의사 요소가 렌더링되려면, 그것과 그 원천 요소가 모두 계산된 appearance 값으로 base를 가져야 한다.

다음 스타일은 select 피커와 select에 기본 모양을 적용하고, 피커에 몇 가지 추가 스타일을 더한다:
select, select::picker(select) {
  appearance: base;
}
select::picker(select) {
  border: 5px solid red;
  background-color: blue;
}

NOTE: ::picker()의 비함수형 형태는, 새 피커가 지원되기 시작할 때 피커가 의도치 않게 스타일링되는 것을 방지하는 용도로는 현재 작동하지 않는다. 모든 폼 컨트롤 피커의 스타일링이 확정되면, 이 비함수형 형태는 모든 피커에 대해 작동할 것이다.

4. 의사 요소

폼 컨트롤은 작성자가 개별적으로 스타일링하고 싶어 할 수 있는 많은 부분으로 구성되므로, 사용자 에이전트가 개별 폼 컨트롤에 대한 의사 요소를 제공할 필요가 있다.

아래 절은 사용자 에이전트 전반에서 일관된 방식으로 다룰 수 있도록, 가장 일반적인 사용 사례를 포괄하려는 일련의 의사 요소를 소개한다.

HTML에 적용되는 폼 컨트롤 의사 요소에 대한 정보성 개요
컨트롤 의사 요소
<progress>
├─ ''::track''
│  └─ ''::fill''
└─ ''::thumb''
<meter>
<input type=checkbox switch>
<input type=range>
<input type=checkbox> ::checkmark
<input type=radio>
<input type=file> ::file-selector-button
<input type=date>

§ 4.8 날짜/시간 입력 필드의 부분 스타일링: ::field-component 및 ::field-separator 의사 요소 참조

<input type=datetime-local>
<input type=time>
<input type=month>
<input type=week>
<input> (type 없음) § 4.5 텍스트 필드의 부분 스타일링: ::field-text 및 ::clear-icon 의사 요소 참조
<input type=text>
<input type=search>
<input type=email>
<input type=password>
<input type=tel>
<input type=url>
<input type=number> § 4.7 숫자 필드의 부분 스타일링: ::step-control, ::step-up 및 ::step-down 의사 요소 참조
<input type=color> ::color-swatch
<textarea> § 4.6 textarea의 부분 스타일링: ::placeholder 및 ::field-text 의사 요소 참조
<select> ::picker-icon
<option> ::checkmark
버튼

그림을 추가한다.

4.1. 피커 열기 아이콘: ::picker-icon 의사 요소

::picker-icon 의사 요소는 피커의 존재를 나타내는 아이콘을 표현하는 컨트롤의 부분을 나타낸다. 이는 원천 요소기본 모양을 가지고 피커를 열 경우에만 생성된다. 이는 완전히 스타일링 가능한 의사 요소이며, 그 원천 요소에서 상속한다.

::picker-icon원천 요소의 자식인 것처럼, ::after 의사 요소가 생성하는 모든 박스 뒤에 박스를 생성하며, 내용은 content로 지정된다.

4.2. 파일 선택기 버튼: ::file-selector-button 의사 요소

::file-selector-button 의사 요소는 UA가 그러한 버튼을 렌더링하는 경우, 파일 피커를 여는 데 사용되는 버튼을 나타낸다.

이는 일반적으로 button 요소를 대상으로 하며, 해당 버튼은 input 요소 내부에 있고 type=file을 가진다. 이는 요소 기반 의사 요소이다.

예를 들어, 다음 예제는 파일 선택기 버튼 주위에 녹색 테두리를 보여야 한다:
::file-selector-button { border: 3px solid green }

4.3. 체크 표시 스타일링: ::checkmark 의사 요소

::checkmark 의사 요소는 항목이 체크되었는지 여부를 나타내는 표시자를 나타내며, 체크박스, 라디오, option 요소에 존재한다.

이는 원천 요소:checked 의사 클래스를 지원하고, 기본 모양을 가지거나 기본 모양을 가진 조상이 있을 때에만 생성된다. 이는 완전히 스타일링 가능한 의사 요소이며, 그 원천 요소에서 상속한다.

체크박스 및 라디오 요소의 경우, 이는 원천 요소의 자식인 것처럼, ::before::after 의사 요소가 생성하는 박스 사이에 박스를 생성하며, 내용은 content로 지정된다.

option 요소의 경우, 이는 원천 요소의 자식인 것처럼, ::before 의사 요소가 생성하는 모든 박스 앞에 박스를 생성하며, 내용은 content로 지정된다.

다음 예제는 체크 표시의 배경 이미지를 변경한다:
::checkmark { background-image: url(...) }

또한 :indeterminate와 함께 사용하여 불확정 체크 표시를 스타일링할 수 있다:

:indeterminate::checkmark { background-image: url(...) }

4.4. 슬라이더류 컨트롤의 부분 스타일링: ::thumb, ::track::fill 의사 요소

명명은 아직 논의 중이다. [Issue #9830]

슬라이더류 컨트롤은 진행 상태를 나타내는 폼 컨트롤이다. 그 진행 상태는 사용자가 조정할 수 있을 수도 있다.

다음 의사 요소는 그 서로 다른 부분을 스타일링하기 위해 제공된다:

::thumb
::thumb 의사 요소는 사용자가 컨트롤의 진행 상태를 조정할 수 있게 하는 부분을 나타낸다.

NOTE: 대부분의 사용자 에이전트에서는 일반적으로 네이티브하게 원형으로 렌더링된다.

::track
::track 의사 요소는 컨트롤의 진행된 부분과 진행되지 않은 부분을 모두 포함하는 부분을 나타낸다.
::fill
::fill 의사 요소는 컨트롤의 진행된 부분을 포함하는 부분을 나타낸다.

컨트롤의 진행 상태가 결정되지 않은 경우(<progress indeterminate>처럼), 사용자 에이전트는 이 부분에 inline-size 0을 부여해야 한다.

이러한 의사 요소는 완전히 스타일링 가능한 의사 요소이며, 그 구조는 다음과 같다:

<input type="range">
├─ ::track
│  └─ ::fill
└─ ::thumb

슬라이더류 컨트롤의 목록은 호스트 언어에 따라 달라진다. HTML에서는 이에 해당하는 것이 다음과 같다:

4.5. 텍스트 필드의 부분 스타일링: ::field-text::clear-icon 의사 요소

::placeholder
::placeholder 의사 요소는 자리 표시자 텍스트를 포함하는 input의 부분을 나타낸다.
::field-text
::field-text 의사 요소는 편집 가능한 텍스트를 포함하는 input의 부분을 나타낸다.
::clear-icon
::clear-icon 의사 요소는 사용자 에이전트가 제공하는 경우, 클릭했을 때 사용자가 input을 지울 수 있게 하는 input의 부분을 나타낸다.

appearance: textfield에서는, 사용자 에이전트가 이 부분을 생성해서는 안 된다.

::field-text::clear-icon은 형제여야 한다.

autofill에서 사용하는 부분을 수집한다.

이를 구현하는 사용자 에이전트의 password visibility toggle을 위해 무언가를 정의할 것인가? [Issue #11845]

::placeholder::field-text와 어떻게 상호작용하는지 정의한다. [Issue #11844]

4.6. textarea의 부분 스타일링: ::placeholder::field-text 의사 요소

::placeholder
::placeholder 의사 요소는 자리 표시자 텍스트를 포함하는 textarea의 부분을 나타낸다.
::field-text
::field-text 의사 요소는 편집 가능한 텍스트를 포함하는 textarea의 부분을 나타낸다.

resizer를 위해 무언가를 정의한다. [Issue #11850]

::placeholder::field-text와 어떻게 상호작용하는지 정의한다. [Issue #11844]

4.7. 숫자 필드의 부분 스타일링: ::step-control, ::step-up::step-down 의사 요소

이러한 의사 요소는 숫자 input을 위해 제공된다. 이들은 완전히 스타일링 가능한 의사 요소이다.

::step-control
::step-control 의사 요소는 위쪽 및 아래쪽 버튼을 포함하는 숫자 input의 부분을 나타낸다.
::step-up
::step-up 의사 요소는 활성화되었을 때 숫자 input 안의 값을 증가시키는 버튼을 나타낸다.
::step-down
::step-down 의사 요소는 활성화되었을 때 숫자 input 안의 값을 감소시키는 버튼을 나타낸다.

그 구조는 다음과 같이 정의된다:

<input type="number">
├─ ::field-text
└─ ::step-control
   ├─ ::step-up
   └─ ::step-down
다음 컨트롤은:
<input type="number">

다음과 같이 다시 스타일링할 수 있다:

[ + 2 - ]

실제 이미지를 삽입한다.

다음 스타일을 사용한다:

input[type=number] {
  appearance: base;
  &::step-control {
    display: contents;
  }
  &::step-up {
    order: 1;
    content: "+";
  }
  &::field-text {
    order: 2;
  }
  &::step-down {
    order: 3;
    content: "-";
  }
}

appearance: textfield에서는, 사용자 에이전트가 이 부분을 생성해서는 안 된다.

4.8. 날짜/시간 입력 필드의 부분 스타일링: ::field-component::field-separator 의사 요소

::field-component
::field-component 의사 요소는 날짜/시간 구성 요소 값을 포함하는 컨트롤의 부분을 나타낸다.
::field-separator
::field-separator 의사 요소는 사용자 에이전트가 그러한 부분을 제공하는 경우, 날짜/시간 구성 요소 값을 분리하는 컨트롤의 부분을 나타낸다.

이 의사 요소들은 형제이다. 컨트롤의 정확한 구조는 국제화와 호스트 언어에 의해 결정되지만, 사용자 에이전트 전반에서 일관되어야 한다.

다음 컨트롤은:
<input type="date">

미국 로케일에서는 다음과 같이 렌더링될 수 있다:

[ 08 / 22 / 2024 [v]]

실제 이미지를 삽입한다.

그 결과 트리는 다음과 같다:

<input type="date">
├─ ::field-component (08)
├─ ::field-separator (/)
├─ ::field-component (22)
├─ ::field-separator (/)
├─ ::field-component (2024)
└─ ::picker-icon

4.9. 색상 견본: ::color-swatch 의사 요소

이름은 ::swatch여야 하는가, 아니면 ::color-swatch여야 하는가? [Issue #11837]

::color-swatch 의사 요소는 선택된 색상 값을 표시하는 컨트롤의 부분을 나타낸다.

예를 들어, 다음 예제는 input과 그 색상 견본을 둥글게 만들어야 한다:
input[type=color], ::color-swatch { border-radius: 100%; }

4.10. 벤더 의사 요소 확장과의 호환성

가능한 경우, 사용자 에이전트는 비표준 의사 요소를 구현하기 위해 별칭 처리를 사용해야 한다.

가능하지 않은 경우, 사용자 에이전트는 표준 의사 요소를 appearance: base용으로 예약하고, 비표준 의사 요소는 appearance: none용으로 사용해야 한다.

5. 의사 클래스

5.1. 서로 다른 meter 상태 지정하기: :low-value / :high-value / :optimal-value 의사 클래스

이것이 UA 로직을 복제할 수 있는지 확인한다. [Issue #11336]

이를 HTML 정의에 연결한다.

:low-value 의사 클래스는 값이 low HTML 속성이 지정한 값보다 낮을 때 meter 요소에 일치한다.

:high-value 의사 클래스는 값이 high HTML 속성이 지정한 값보다 높을 때 meter 요소에 일치한다.

:optimal-value 의사 클래스는 값이 optimum / low / high HTML 속성으로 결정되는 범위 안에 있을 때 meter 요소에 일치한다.

5.2. 리스트박스인 select 지정하기

무언가를 정의한다. [Issue #7422]

6. control-value() 함수

이것은 구현할 준비가 되어 있지 않으므로, 이에 관한 이슈를 제출한다.

데이터 유출과 관련한 개인정보 영향를 고려한다. [Issue #11860]

더 많은 타입 추가를 고려한다. [Issue #11842]

control-value() 함수는 그것이 있는 폼 컨트롤의 현재 값으로 계산된다. 폼 컨트롤이 아닌 요소에 사용되면, 빈 문자열을 반환한다.

<control-value()> = control-value( <type>? )

<type> = '<' [ number | string ] '>'

의사 요소에 사용되면, 그 원천 요소를 기준으로 평가된다.

예를 들어, range input의 값을 그 옆에 표시하려면:
input[type=range]::after {
  content: control-value();
}

7. 위젯 스타일링

field-sizing/accent-color/input-security를 이 명세로 옮길 것인가?

7.1. 슬라이더류 컨트롤의 방향 변경하기: slider-orientation

이 속성을 다시 작업한다.

이름: slider-orientation
값: auto | left-to-right | right-to-left | top-to-bottom | bottom-to-top
초기값: auto
적용 대상: 모든 요소
상속: no
백분율: n/a
계산값: 지정된 대로
표준 순서: 문법에 따름
애니메이션 유형: discrete
auto
슬라이더류 컨트롤의 방향은 쓰기 모드와 방향에 의해 정의된다.
left-to-right
슬라이더류 컨트롤은 가로로 렌더링되며 ::fill은 컨트롤 안에서 왼쪽에 정렬된다.
right-to-left
슬라이더류 컨트롤은 가로로 렌더링되며 ::fill은 컨트롤 안에서 오른쪽에 정렬된다.
top-to-bottom
슬라이더류 컨트롤은 세로로 렌더링되며 ::fill은 컨트롤 안에서 위쪽에 정렬된다.
bottom-to-top
슬라이더류 컨트롤은 세로로 렌더링되며 ::fill은 컨트롤 안에서 아래쪽에 정렬된다.

부록 A: 기본 모양 사용자 에이전트 스타일시트

HTML로 옮긴다.

이 절은 구현을 통해 다듬어야 한다.

color input 스타일은 다듬어야 한다. [Issue #11837]

기본 사항

input,
textarea,
button,
::file-selector-button,
select,
meter,
progress {
    color: inherit;
    font: inherit;
    box-sizing: border-box;
    background-color: transparent;
}

레이아웃

input:not([type=file], [type=range]),
textarea,
button,
::file-selector-button,
::track,
select,
meter,
progress {
  border: 1px solid currentColor;
  background-color: transparent;
}

슬라이더

meter, progress, switch 및 range input 스타일링을 다듬는다.

::track {
  height: 1em;
}

::fill {
  height: 100%;
  background-color: currentColor;
}

::thumb {
  border-radius: 0;
  border: none;
  background-color: currentColor;
  appearance: none;
  width: 1em;
  height: 100%;
}

체크박스 및 라디오

input:is([type=checkbox]:not([switch]), [type=radio]) {
    width: 1em;
    height: 1em;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    content: '';
}

input[type=radio] {
    border-radius: 100%;
}

input[type=checkbox]:not([switch]):checked::checkmark {
    content: '\2713' / '';
}

input[type=radio]:checked::checkmark {
    background-color: currentColor;
    display: inline-block;
    border-radius: inherit;
    height: 100%;
    width: 100%;
}

Select 및 버튼

select {
  /* Base appearance select always sizes based on its contents. */
  field-sizing: content !important;
}

button,
::file-selector-button,
select,
input:is([type="color"], [type="button"], [type="reset"], [type="submit"]) {
  border: 1px solid currentColor;
  background-color: transparent;
  color: inherit;
  /* Padding prevents the text from sticking to the borders.
   * optically centered to account for half leading */
  padding-block: 0.25em;
  padding-inline: 0.5em;

  /* <select>s and <button>s should have border-radius to be
   * distinct from <input>s: https://github.com/w3c/csswg-drafts/issues/10857#issuecomment-2520875011*/
  border-radius: 0.5em;

  /* These min-size rules ensure accessibility by following WCAG rules:
   * https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html
   * The 1.2em is there to make sure that options without text don't change
   * the block size of the button. */
  min-block-size: max(24px, 1lh);
  min-inline-size: 24px;

  /* box-sizing comes from existing UA styles which happen to
   * already be interoperable. */
  box-sizing: border-box;

  /* Push picker icon to the right of the box and have some space
   * in between it and the text. */
  display: inline-flex;
  gap: 1em;

  user-select: none;
}
:is(button, select, input:is([type="color"], [type="button"], [type="reset"], [type="submit"])):enabled:hover,
:enabled::file-selector-button:hover {
  background-color: color-mix(in lab, currentColor 10%, transparent);
}
:is(button, select, input:is([type="color"], [type="button"], [type="reset"], [type="submit"])):enabled:active,
:enabled::file-selector-button:active {
  background-color: color-mix(in lab, currentColor 20%, transparent);
}
:is(button, select, input:is([type="color"], [type="button"], [type="reset"], [type="submit"])):disabled,
:disabled::file-selector-button {
  color: color-mix(in srgb, currentColor 50%, transparent);
}

select > button:first-child {
  /* Prevents button from setting font, color, or background-color */
  all: unset;

  /* Prevents duplicate box decorations */
  display: contents;

  /* Prevents button activation behavior so select can handle events */
  interactivity: inert;
}
select option {
  /* These min-size rules ensure accessibility by following WCAG rules:
   * https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html
   * Unset if the author provides a child button element.
   * The 1lh is there to make sure that options without text don't change
   * the block size of the option. */
  min-inline-size: 24px;
  min-block-size: max(24px, 1lh);

  /* Centers text within the block (vertically). From OpenUI discussion:
   * https://github.com/openui/open-ui/issues/1026#issuecomment-2103187647. */
  align-content: center;

  /* centering + gap between checkmark and option content */
  /* also easily reversed, when checkmark should be inline-end */
  display: flex;
  align-items: center;
  gap: 0.5em;

  /* Makes options with long text widen picker instead
   * of making options tall. */
  white-space: nowrap;
}
select option:enabled:hover {
  background-color: color-mix(in lab, currentColor 10%, transparent);
}
select option:enabled:active {
  background-color: color-mix(in lab, currentColor 20%, transparent);
}
select option:disabled {
  color: color-mix(in lab, currentColor 50%, transparent);
}
select option::checkmark {
  content: '\2713' / '';
}
select option:not(:checked)::checkmark {
  visibility: hidden;
}

select optgroup {
  /* font-weight makes optgroups visually distinct from options. */
  font-weight: bolder;
}

select optgroup option {
  /* Undo font-weight:bolder rule from optgroups. */
  font-weight: normal;
}

select legend,
select option {
  /* spacing ownership moves to children */
  /* space inline from border edges */
  /* this creates a full bleed hover highlight */
  padding-inline: 0.5em;
}

select::picker-icon {
  /* margin-inline-start pushes the icon to the right of the box */
  margin-inline-start: auto;
  display: block;
  content: counter(-ua-disclosure-open, disclosure-open);
}

::picker(select) {
  /* Same properties as popover and dialog */
  color: CanvasText;
  background-color: Canvas;
  border: 1px solid;

  /* box-sizing is set to match the button. */
  box-sizing: border-box;

  /* Remove [popover] padding which
   * prevents options from extending to edges */
  padding: 0;

  /* Anchor positioning and scrollbars */
  inset: auto;
  margin: 0;
  min-inline-size: anchor-size(self-inline);
  min-block-size: 1lh;
  /* Go to the edge of the viewport, and add scrollbars if needed. */
  max-block-size: stretch;
  overflow: auto;
  /* Below and span-right, by default. */
  position-area: block-end span-inline-end;
  position-try-order: most-block-size;
  position-try-fallbacks:
    /* First try above and span-right. */
    block-start span-inline-end,
    /* Then below but span-left. */
    block-end span-inline-start,
    /* Then above and span-left. */
    block-start span-inline-start;
}

부록 B: 탐구

기본 스타일링 제안

이 절은 폼 스타일링 문제를 해결하기 위한 몇 가지 제안을 개략적으로 설명한다.

프로토타입

fantasai가 원래 제안한 이 아이디어는, 소수의 "prototype" 요소를 스타일링할 수 있도록 하자는 것이다. 그러면 브라우저 UI 디자이너가 해당 요소들의 스타일링을 가져와 자신의 UI로 그 디자인을 외삽할 수 있다. 최소한 텍스트, 배경, 테두리 같은 것들을 사용할 수 있다. 한계까지 가면 내부 패딩, border-radius 등도 사용될 수 있다.

@control button {
  <declaration-list>
}

@control input {
  <declaration-list>
}

input::selection {
  <declaration-list>
}

...
다음에 대한 스타일을 사용할 수 있게 된다:

대부분의 폼 컨트롤은, 달력 위젯이나 시계조차도 어떤 방식으로든 이 세 가지 원시 요소의 조합이다. UA가 이 세 가지 원시 요소, 그리고 어쩌면 한두 가지를 더 위한 스타일링을 받으면 나머지를 어떻게 스타일링할지 알아낼 수 있다.

예를 들어, 달력 위젯은 월, 연도, 이를 이동하는 몇 개의 버튼, 그것들을 클릭해 직접 편집할 수 있는 기능, 그리고 해당 월의 날짜 표현을 가질 수 있다. 선택된 날짜는 선택되어 있다. 어쩌면 버튼은 :hover 또는 :focus에서만 표시될 수도 있다 -- UA가 결정한다. 하지만 버튼이 이 특정한 파란색 음영, 해당 border-radius 및 drop-shadow를 가져야 한다는 것은 알고 있다. 달력은 input 필드의 색상으로 표시될 수 있고, 선택된 날짜는 selection 색상으로 표시될 수 있으며, 모든 면에서 페이지의 나머지 input 필드가 보이는 방식과 어울릴 것이다.

이제 작성자는 예를 들어 연도와 월 이름 사이의 간격이나, 연도를 변경하는 버튼에 단단한 화살표가 있는지, 속이 빈 화살표가 있는지, 장식적인 화살표가 있는지를 결정할 수 없고, 월과 그 아래 날짜 필드 사이에 5px 간격을 둔 검은색 단색 반쪽 테두리가 있어야 한다고 결정할 수도 없다. 하지만 달력은 페이지에 속한 것처럼 보일 것이며, UA는 넓지만 짧은 스마트 워치에서 월과 연도를 옆에 배치하는 것이 더 나을 때 다른 달력 레이아웃을 만들어내더라도 아무것도 깨뜨리지 않을 수 있다.

iOS 시간 피커
검은색 영역은 버튼 색상이다. 그것의 매우 옅은 투명 색상이 glass 색상이 될 수 있다. 롤러는 input 색상이다.
Android 시간 피커
더 많은 맥락 없이는 말하기 어렵지만, 오른쪽의 경우 시계판과 디지털 표시부는 @input 색상이고, 강조된 부분은 highlight 색상이며, Done 버튼은 버튼 스타일링이고, 시계판 주변의 음영 영역은 버튼 배경과 같은 색상이다.

반전 시스템 색상

Florian과 Tab이 원래 스케치한 이 아이디어는, UI 디자이너가 자신의 UI에 색을 입힐 때 선택할 수 있는 추상적인 색상 집합을 정의하자는 것이다.

Android 색상 추출 API 제안에서 나온 Tab의 제안 색상 집합:

(여기서 light는 약 75% 밝기, normal은 약 50%, dark는 약 25%이고, vibrant는 최소 30% 채도, 이상적으로는 100%이며, muted는 최대 40% 채도, 이상적으로는 30%이다)

이는 11가지 색상이며, 그중 많은 색상은 웹페이지 자체의 색 구성표에서 도출될 수 있다. 적어도 일부를 지정하면 그중 여러 색상을 자동 생성할 수 있다. 예를 들어 "normal-vibrant" 색상에서 light/dark 변형을 생성하거나, 적절하게 텍스트 색상을 흰색/검은색으로 자동 설정하는 식이다.

하지만 input UI가 페이지의 나머지 부분과 같은 방식으로 색상을 사용한다는 보장은 없다.

기타 컨트롤별 제안

<progress> 및 <meter> 스타일링

<select> 및 <datalist> 스타일링 제안 및/또는 화이트보드 사진을 삽입한다.

Select/Datalist 드롭다운

  1. colorbackground가 모두 설정된 경우에만 스타일링을 허용한다.

  2. Option 컨테이너:

    • 배경

    • 테두리

    • 패딩

  3. option

    • 패딩

    • 테두리

    • border-collapse?

    • 배경

    • display-inside는 허용되고, 자동으로 blockified된다

    • margin, position, float, width, height는 아님

모든 option은 contain:paint이며 BFC이다.

Input UI 예제

이 절은 가능한 한 많은 input UI 예제를 스크린샷으로 수집한다. 특히 모바일 기기에서는 그것들이 다소 "이상하기" 때문이다.

시간 피커

iOS 시간 피커
Android 시간 피커 1
Android 시간 피커 2

날짜 피커

Android 날짜 피커

개인정보 보호 고려 사항

이 명세에 대해 보고된 새로운 개인정보 보호 고려 사항은 없다.

보안 고려 사항

이 명세에 대해 보고된 새로운 보안 고려 사항은 없다.

감사의 말

이 제안에 의견을 제공해 준 Aditya Keerthi, Anne van Kesteren, Elika Etemad, Jen Simmons, Joey Arhar, Jon Davis, Simon Fraser 및 Theresa O’Connor에게 감사한다.

input[type=range] 스타일링에 대한 상세한 분석을 제공해 준 Ana Tudor에게 감사한다.

적합성

문서 규약

적합성 요구사항은 서술적 단언과 RFC 2119 용어를 조합하여 표현된다. 이 문서의 규범적 부분에서 쓰이는 핵심 단어 “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, “OPTIONAL”은 RFC 2119에 설명된 대로 해석해야 한다. 다만 가독성을 위해, 이 명세에서는 이러한 단어가 모두 대문자로 나타나지는 않는다.

명시적으로 비규범적이라고 표시된 절, 예제 및 참고를 제외하고 이 명세의 모든 텍스트는 규범적이다. [RFC2119]

이 명세의 예제는 “for example”이라는 단어로 소개되거나, 다음과 같이 class="example"을 사용하여 규범적 텍스트와 구분된다:

이는 정보성 예제의 예이다.

정보성 참고는 “Note”라는 단어로 시작하며, 다음과 같이 class="note"를 사용하여 규범적 텍스트와 구분된다:

Note, 이는 정보성 참고이다.

권고문은 특별한 주의를 환기하도록 스타일링된 규범적 절이며, 다음과 같이 <strong class="advisement">를 사용하여 다른 규범적 텍스트와 구분된다: UA는 접근 가능한 대안을 제공해야 한다.

적합성 클래스

이 명세에 대한 적합성은 세 가지 적합성 클래스에 대해 정의된다:

스타일시트
CSS 스타일시트.
렌더러
스타일시트의 의미를 해석하고 이를 사용하는 문서를 렌더링하는 UA.
작성 도구
스타일시트를 작성하는 UA.

스타일시트는 이 모듈에 정의된 구문을 사용하는 모든 문장이 일반 CSS 문법과 이 모듈에 정의된 각 기능의 개별 문법에 따라 유효한 경우 이 명세에 적합하다.

렌더러는 적절한 명세에서 정의한 대로 스타일시트를 해석하는 것에 더해, 이 명세가 정의한 모든 기능을 올바르게 파싱하고 그에 따라 문서를 렌더링하여 지원하는 경우 이 명세에 적합하다. 그러나 장치의 한계로 인해 UA가 문서를 올바르게 렌더링하지 못한다고 해서 그 UA가 부적합해지는 것은 아니다. (예를 들어, UA가 단색 모니터에서 색상을 렌더링해야 하는 것은 아니다.)

작성 도구는 이 모듈의 각 기능에 대한 개별 문법과 일반 CSS 문법에 따라 문법적으로 올바른 스타일시트를 작성하고, 이 모듈에 설명된 스타일시트의 다른 모든 적합성 요구사항을 충족하는 경우 이 명세에 적합하다.

부분 구현

작성자가 전방 호환 파싱 규칙을 활용하여 대체 값을 지정할 수 있도록, CSS 렌더러는 사용 가능한 수준의 지원이 없는 모든 at-rule, 속성, 속성 값, 키워드 및 기타 구문 구조를 유효하지 않은 것으로 취급해야 하며(must), 적절히 무시해야 한다. 특히 사용자 에이전트는 하나의 다중 값 속성 선언 안에서 지원되지 않는 구성 값은 선택적으로 무시하고 지원되는 값은 존중해서는 안 된다(must not). 어떤 값이든 유효하지 않은 것으로 간주되면 (지원되지 않는 값은 그렇게 간주되어야 하므로), CSS는 전체 선언을 무시하도록 요구한다.

불안정 및 독점 기능의 구현

미래의 안정적인 CSS 기능과의 충돌을 피하기 위해, CSSWG는 CSS의 불안정 기능 및 독점 확장을 구현할 때 모범 사례를 따를 것을 권장한다.

비실험적 구현

명세가 후보 권고안 단계에 도달하면 비실험적 구현이 가능해지며, 구현자는 명세에 따라 올바르게 구현되었음을 입증할 수 있는 모든 CR 수준 기능에 대해 접두사가 없는 구현을 배포해야 한다.

CSS의 구현 간 상호운용성을 확립하고 유지하기 위해, CSS 작업 그룹은 비실험적 CSS 렌더러가 CSS 기능의 접두사가 없는 구현을 배포하기 전에 구현 보고서(필요한 경우 해당 구현 보고서에 사용된 테스트케이스 포함)를 W3C에 제출할 것을 요청한다. W3C에 제출된 테스트케이스는 CSS 작업 그룹의 검토와 수정을 받을 수 있다.

테스트케이스와 구현 보고서 제출에 관한 추가 정보는 CSS 작업 그룹 웹사이트 https://www.w3.org/Style/CSS/Test/에서 찾을 수 있다. 질문은 public-css-testsuite@w3.org 메일링 리스트로 보내야 한다.

색인

이 명세에서 정의하는 용어

참조로 정의되는 용어

참고문헌

규범적 참고문헌

[CSS-BACKGROUNDS-3]
Elika Etemad; Brad Kemper. CSS 배경 및 테두리 모듈 Level 3. 2024년 3월 11일. CRD. URL: https://www.w3.org/TR/css-backgrounds-3/
[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS 캐스케이딩 및 상속 Level 5. 2022년 1월 13일. CR. URL: https://www.w3.org/TR/css-cascade-5/
[CSS-COLOR-4]
Chris Lilley; Tab Atkins Jr.; Lea Verou. CSS 색상 모듈 Level 4. 2024년 2월 13일. CRD. URL: https://www.w3.org/TR/css-color-4/
[CSS-CONTENT-3]
Elika Etemad; Dave Cramer. CSS 생성 콘텐츠 모듈 Level 3. 2019년 8월 2일. WD. URL: https://www.w3.org/TR/css-content-3/
[CSS-PSEUDO-4]
Daniel Glazman; Elika Etemad; Alan Stearns. CSS 의사 요소 모듈 Level 4. 2022년 12월 30일. WD. URL: https://www.w3.org/TR/css-pseudo-4/
[CSS-UI-4]
Florian Rivoal. CSS 기본 사용자 인터페이스 모듈 Level 4. 2021년 3월 16일. WD. URL: https://www.w3.org/TR/css-ui-4/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS 값 및 단위 모듈 Level 4. 2024년 3월 12일. WD. URL: https://www.w3.org/TR/css-values-4/
[HTML]
Anne van Kesteren; et al. HTML 표준. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[RFC2119]
S. Bradner. RFC에서 요구 수준을 나타내는 데 사용하는 핵심 단어. 1997년 3월. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[SELECTORS-4]
Elika Etemad; Tab Atkins Jr.. 선택자 Level 4. 2022년 11월 11일. WD. URL: https://www.w3.org/TR/selectors-4/

속성 색인

이름 초기값 적용 대상 상속 백분율 애니메이션 유형 표준 순서 계산값
slider-orientation auto | left-to-right | right-to-left | top-to-bottom | bottom-to-top auto 모든 요소 no n/a discrete 문법에 따름 지정된 대로

이슈 색인

appearance의 정의를 여기로 옮긴다.
구현, 실험, bikeshedding 및 사용자 에이전트 스타일시트 개선을 통해 이 예제들을 다듬는다.
그림을 추가한다.
명명은 아직 논의 중이다. [Issue #9830]
autofill에서 사용하는 부분을 수집한다.
이를 구현하는 사용자 에이전트의 password visibility toggle을 위해 무언가를 정의할 것인가? [Issue #11845]
::placeholder::field-text와 어떻게 상호작용하는지 정의한다. [Issue #11844]
resizer를 위해 무언가를 정의한다. [Issue #11850]
::placeholder::field-text와 어떻게 상호작용하는지 정의한다. [Issue #11844]
실제 이미지를 삽입한다.
실제 이미지를 삽입한다.
이름은 ::swatch여야 하는가, 아니면 ::color-swatch여야 하는가? [Issue #11837]
이것이 UA 로직을 복제할 수 있는지 확인한다. [Issue #11336]
이를 HTML 정의에 연결한다.
무언가를 정의한다. [Issue #7422]
이것은 구현할 준비가 되어 있지 않으므로, 이에 관한 이슈를 제출한다.
데이터 유출과 관련한 개인정보 영향을 고려한다. [Issue #11860]
더 많은 타입 추가를 고려한다. [Issue #11842]
field-sizing/accent-color/input-security를 이 명세로 옮길 것인가?
이 속성을 다시 작업한다.
HTML로 옮긴다.
이 절은 구현을 통해 다듬어야 한다.
color input 스타일은 다듬어야 한다. [Issue #11837]
meter, progress, switch 및 range input 스타일링을 다듬는다.
<progress> 및 <meter> 스타일링
<select> 및 <datalist> 스타일링 제안 및/또는 화이트보드 사진을 삽입한다.