개발자 의견 요청: 맞춤설정 가능한 선택

<select> 요소와 같은 양식 컨트롤의 스타일 지정은 수년 동안 개발자의 주요 고충으로 보고되었으며, Google은 이에 대한 해결책을 마련하기 위해 노력해 왔습니다. 이 작업은 복잡하고 제대로 구현하는 데 오랜 시간이 걸렸지만, 이제 이 기능을 출시할 날이 얼마 남지 않았습니다. 맞춤설정 가능한 버전의 select 요소가 WHATWG에서 공식적으로 2단계에 있으며, 브라우저 간 관심이 높고 Chrome Canary 130에서 테스트할 수 있는 프로토타입이 있습니다.

사용해 보고 의견을 보내주세요

Chrome Canary 설치가 버전 130으로 업데이트되었고 실험용 웹 플랫폼 기능 플래그가 사용 설정되어 있는지 확인합니다. 주소 표시줄에서 chrome://flags로 이동하여 #experimental-web-platform-features를 사용 설정하면 이 플래그를 사용 설정할 수 있습니다. 그러면 이 게시물에서 Codepen 데모를 볼 수 있습니다. 또는 이 Codepen 컬렉션을 확인하여 한곳에서 모두 볼 수 있습니다.

이 양식을 사용하여 기능에 관한 의견을 제공하세요. 완료하는 데 3분밖에 걸리지 않습니다.

기존 HTML select 태그를 기반으로 하는 맞춤설정 가능한 select API의 기능을 살펴보겠습니다.

새 <select> 선택

새 동작을 선택하려면 인페이지 선택 버튼과 선택 선택 도구 모두에서 CSS appearance 속성을 사용하세요. 선택하려면 <select> 요소와 ::picker(select)에서 appearance: base-select를 설정합니다.

::picker(select)는 사용자 에이전트가 제공하는 새로운 가상 요소로, appearance: base-select를 사용하여 새 동작을 선택한 <select> 요소에만 적용됩니다. 이 선택 도구 가상 요소는 기본 선택 버튼에 의해 트리거되는 팝오버입니다. 다음 코드와 같이 두 가지를 모두 선택할 수 있습니다.

select,
::picker(select) {
  appearance: base-select;
}

인페이지 버튼만 선택할 수 있지만 인페이지 버튼을 선택하지 않고 선택 도구 팝오버만 선택할 수는 없습니다. ::picker(select)는 appearance: base-select가 <select>에 적용된 후에만 생성됩니다.

이제 선택 요소를 맞춤설정할 준비가 되었습니다. 새로운 맞춤설정 가능한 선택에는 브라우저와 운영체제에서 동일하게 표시되는 몇 가지 기본 스타일이 포함되어 있습니다. 다음은 macOS의 Chrome에서 기존 선택과 비교한 기본 맞춤 선택의 모습입니다.

오른쪽의 맞춤설정 가능한 선택에 대한 기본 사용자 에이전트 스타일입니다. 이 기능은 변경될 수 있으며, 이에 대한 의견을 듣고 싶습니다.
기본 선택과 맞춤설정 가능한 선택의 데모

부분 분석

선택의 요소를 보여주는 다이어그램

새로운 맞춤설정 가능한 선택 모드에서는 다음과 같은 새로운 요소에 액세스할 수 있습니다. - selectedoption: 현재 선택된 옵션의 내부 HTML을 반영합니다. dish_iconoption::before: 현재 선택된 옵션을 기본 접근성 어포던스로 나타내는 체크표시가 포함되어 있습니다(변경될 수 있음). ::picker(select): 맞춤설정 가능한 선택 항목 내에서 button 외부의 모든 콘텐츠를 포함하는 팝오버입니다.

선택의 모든 부분에 스타일을 지정할 수 있습니다. 예를 들어 <option> 요소 내에 임의의 비대화형 콘텐츠를 추가하고, 선택 드롭다운을 여는 인페이지 버튼의 스타일을 지정하고, 옵션의 드롭다운 목록(::picker(select))의 스타일을 지정할 수 있습니다.

button의 스타일을 지정하고, 자체 화살표 표시기를 가져오고, 요소 내부 및 주변에 임의의 콘텐츠를 추가할 수도 있습니다. 콘텐츠를 추가하는 것 외에도 이러한 새 요소와 기본 스타일을 숨길 수 있습니다. 예를 들어 옵션의 ::before 의사 요소에 표시 체크표시를 원하지 않는 경우 다음 CSS를 사용합니다.

/* Remove the default checkmark from the selected option */
option::before {
 display: none;
}

선택 요소 내에 요소가 무제한으로 있을 수 있지만 브라우저는 <button> 요소 외부의 모든 요소를 ::picker(select) 가상 요소로 버킷화합니다. 이 요소는 버튼에 고정된 팝오버처럼 작동합니다. 이 <button>는 ::picker(select)를 전환합니다. 선택 항목 바로 안에 있는 옵션 및 기타 요소는 ::picker(select)로 호이스팅되거나 스타일 지정 목적으로 자체 래퍼를 가져올 수 있습니다. 이 래퍼도 ::picker(select) 가상 요소 내에 배치됩니다.

<select>
  <button>
    <selectedoption></selectedoption>
  </button>
  // Everything else that will go into the ::picker(select) popover
</select>

맞춤설정 가능한 새로운 <select>는 팝오버 및 앵커 위치 지정의 기능을 사용합니다. 이 두 가지 기본 기술을 기반으로 빌드됩니다. 즉, 선택 내의 드롭다운 옵션 목록은 선택을 여는 트리거 버튼에 고정된 팝오버 역할을 합니다.

앵커 위치 지정을 사용하여 이 ::picker(select) 팝오버의 스타일을 지정할 수 있습니다(다른 요소에 고정하는 것 포함). 이 콘텐츠 모델은 최상위 레이어 애니메이션 스타일이 옵션 목록과 함께 작동하여 진입 및 종료 효과에 애니메이션을 적용한다는 의미이기도 합니다.

기존 <select> 요소 개선

이전에는 Chrome팀에서 <selectlist> 요소에 대한 아이디어를 연구하고 있었습니다. 이 게시물에서는 기존 <select> 요소를 재사용하도록 재설계된 기능을 설명합니다.

기존 <select> 요소를 재사용할 때의 주요 이점 중 하나는 기본 HTML 요소를 점진적으로 개선할 수 있다는 것입니다. 새 요소와 비교할 때 <select>를 재사용하면 페이지에 의미 있는 콘텐츠가 계속 렌더링됩니다. 다음 예는 맞춤설정된 선택과 지원되지 않는 브라우저를 사용하는 사용자에게 표시되는 내용을 보여줍니다.

option 내의 모든 텍스트 콘텐츠는 select 요소의 대체 버전에 렌더링됩니다.

기본 스타일 지정

변경사항은 select 요소의 시각적 스타일 지정만큼 간단할 수 있습니다. 예를 들어 버튼 스타일, 마우스 오버 및 포커스 스타일, 선택 옵션의 배경을 업데이트할 수 있습니다. appearance: base-select를 사용하여 선택한 후 선택한 부분에 원하는 CSS를 적용합니다.

기본 버튼을 사용하여 선택의 다양한 부분의 스타일 변경

화살표 표시기를 맞춤설정하려면 선택 내부에 자체 버튼과 화살표를 추가합니다.

<select>
  <button>
    <selectedoption></selectedoption>
    <span>
      // Arrow here
    </span>
  </button>
  // Everything else that will go into the ::picker(select) popover
</select>

그런 다음 화살표의 스타일을 지정합니다.

/* style the arrow */
button span {
  /* arrow styles */
  transition: rotate 0.2s;
}

/* adjust arrow styles when the picker is open */
select:open button span {
  rotate: -180deg;
}

옵션 내 복잡한 콘텐츠

<select> 내부의 <option> 요소 내에서 문자열 외의 콘텐츠를 추가하고 스타일을 지정하는 기능을 통해 더 많은 작업을 할 수 있습니다. 기본적인 예로는 드롭다운 메뉴에서 국가 이름 옆에 국기 이미지를 추가하는 것이 있습니다. 이렇게 하려면 옵션 텍스트 옆에 이미지 요소를 추가합니다.

<option value="france">
  <img src="img/flag_of_france.svg" alt="" />
  <span>France</span>
</option>
국기가 표시된 국가 선택 도구

더 복잡한 예로는 프로필 사진, 이름, 대체 정보가 포함되어 드롭다운에서 선택할 항목을 결정하는 데 도움이 될 수 있습니다.

<option value="eur">
    <img src="euro-flag.png" alt="" />
    <div class="currency">
      <div class="currency-short">EUR</div>
      <div class="currency-long">Euro</div>
    </div>
    <div class="symbol" aria-hidden="true">€</div>
</option>
통화 선택 도구 스크린샷

선택한 옵션의 스타일 지정

선택한 옵션이 드롭다운에서와는 다르게 선택된 상태로 표시되도록 할 수 있습니다. 예를 들어 Gmail UI에서는 공간을 절약하기 위해 옵션을 선택하면 라벨이 삭제됩니다. 스타일 지정을 위해 <selectedoption> 요소에 후크하여 이 작업을 실행합니다. <option>에는 다음 마크업이 모두 포함됩니다.

 <option value="reply-all">
    <img class="material-symbol"  src="material-symbol-reply.png">
    <span class="text">Reply all</span>
  </option>

이제 <selectedoption> 내의 .text에 display: none을 적용하여 텍스트 콘텐츠를 숨기고 아이콘만 표시합니다.

selectedoption .text {
  display: none;
}
선택한 옵션을 나타내는 아이콘이 있는 Gmail 스타일 선택입니다.

상호작용 옵션

::picker(select)의 스타일을 완전히 제어할 수 있으므로 이전 데모를 기반으로 마우스 오버 및 포커스 시 상호작용하도록 만듭니다. 이 데모에서는 새로운 calc-size() 함수를 사용하여 마우스 오버 시 또는 선택 항목에 focus-visible이 있는 옵션이 있는 경우 아이콘 표시에서 옵션의 전체 너비 표시로 선택 도구의 너비에 애니메이션을 적용합니다.

/* base styles when picker is open but not interacted with */
::picker(select) {
  width: var(--icon-width);
  transition: width 0.5s;
}

/* animate the text in on hover & focus */
::picker(select):hover,
select:has(option:focus-visible)::picker(select) {
  /*  auto width!  */
  width: calc-size(auto, size + 0.5rem);
}
마우스 오버 또는 포커스 시 콘텐츠가 점진적으로 표시되는 대화형 Gmail 스타일 선택입니다.

제한사항 및 접근성 참고사항

강한 힘에는 큰 책임이 따릅니다. 접근성을 유지하기 위해 이 기능에는 몇 가지 제한사항이 있습니다.

  • <option> 요소 외에는 버튼이나 기타 요소와 같은 상호작용형(포커스 가능) 요소가 아직 <select> 내에서 허용되지 않습니다. 현재 제안된 콘텐츠 모델은 <div>, <span>, <option>, <optgroup>, <img>, <svg>, <hr> 요소만 허용합니다.
  • 분할 버튼은 현재 접근성 솔루션을 개발하는 실험 단계에 있습니다.

향후 이러한 환경의 접근성 스토리가 구체화됨에 따라 콘텐츠 모델이 더 유연하게 확장될 것으로 예상됩니다.

결론

Google은 이 기능이 실무 그룹과 표준 기관을 통해 발전하는 모습을 기대하고 있으며, 프로토타입을 적극적으로 빌드하고 이 기능의 형태를 평가하는 과정에서 진행 상황을 공유하고 있습니다. 예상대로 작동하지 않는 부분이 있으면 알려주세요.

이 기능은 아직 개발 중이지만 간단한 의견 양식을 통해 의견을 보내주시면 감사하겠습니다.

웹에서 접근성이 우수하고 맞춤설정 가능한 양식 컨트롤을 더 쉽게 빌드할 수 있도록 도와주셔서 감사합니다.