CSS 속성 appearance: base-select를 사용하면 일반 HTML 요소와 마찬가지로 <select> 요소와 선택 도구(::picker(select)를 통해)의 스타일을 지정할 수 있습니다.
Grid 또는 Flexbox와 같은 최신 CSS 레이아웃 기법과 결합하면 기존의 세로로 쌓인 목록에서 벗어나 커스텀 JS 없이도 풍부한 시각적 환경을 만들 수 있습니다.
예를 들어 display: grid를 사용하여 옵션을 카드의 2D 그리드로 스타일 지정할 수 있습니다.
이는 색상 선택 도구, 그림 이모티콘 선택기 또는 목록보다 풍부한 시각적 메뉴가 더 효과적인 제품 옵션에 적합합니다.
구현 방법
1. 기본 스타일 지정 활성화
<select> 요소와 내부 선택 도구 가상 요소 select::picker(select) 모두에 appearance: base-select를 적용합니다.
select.grid-picker {
&, &::picker(select) {
appearance: base-select;
}
}
2. 선택 도구 컨테이너 스타일 지정
select:open::picker(select)를 타겟팅하고 display: grid (또는 display: flex)를 적용합니다.
다른 컨테이너와 마찬가지로 열과 간격을 정의합니다.
select.grid-picker:open::picker(select) {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
}
중요: :open는 필수 항목입니다. select::picker(select)의 스타일을 지정하면 선택기가 닫혀 있어도 선택기가 표시됩니다.
3. 옵션 스타일 지정
<option> 요소를 타겟팅하여 그리드 항목 또는 카드로 스타일을 지정합니다.
내부에 이미지, SVG 또는 복잡한 레이아웃을 추가할 수 있습니다.
/* Style options as grid cards */
.grid-picker option {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
/* padding, border-radius, background, etc. */
}
4. 선택한 옵션의 스타일 지정
선택한 옵션의 스타일을 지정하려면 option:checked를 사용합니다. 예를 들면 다음과 같습니다.
.grid-picker option:checked {
position: relative;
border: 2px solid var(--primary-color);
background-color: oklab(from var(--primary-color) l a b / 8%);
}
다른 UI 컨트롤과 마찬가지로 색상만으로 상태를 전달하지 말고 여러 시각적 표시기 (예: 색상, 테두리 두께, 체크표시)를 사용하여 선택된 옵션을 전달합니다.
5. (선택사항) 선택한 옵션 체크표시 스타일 지정
기본적으로 브라우저는 체크표시를 모든 <option>의 첫 번째 하위 요소로 렌더링합니다.
content: "✓" / ""가 있는 ::before처럼 동작하며, 작성자가 제공한 ::before가 있는 경우 그 앞에 렌더링됩니다.
옵션이 선택되지 않으면 visibility: hidden를 통해 체크표시가 숨겨집니다.
::checkmark 가상 요소를 사용하여 스타일을 지정하거나, 스타일 지정만으로 선택을 전달하거나 맞춤 표시기를 사용하려는 경우 완전히 숨길 수 있습니다.
예를 들어 옵션의 오른쪽 상단에 배치하려면 다음과 같이 하면 됩니다.
select.grid-picker {
> option::checkmark {
/* Hide the checkmark for unselected options */
display: none;
}
> option:checked {
position: relative;
&::checkmark {
position: absolute;
inset-block-start: -.4em;
inset-inline-end: -.5em;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
min-inline-size: 1.6em;
aspect-ratio: 1;
padding-right: 0.12em;
padding-left: 0.05em;
border-radius: 50%;
background: var(--primary-color);
color: white;
font-size: 70%;
font-weight: bold;
}
}
}
도움말: 체크표시 주위에 컨테이너 (예: 원)를 그릴 때는 모양을 고려한 시각적 중앙 정렬을 위해 위쪽으로 약간 이동합니다 (여기서는 padding-bottom 및 padding-left 사용).
이 경우 padding-inline-start 또는 padding-block-end를 사용하지 마세요. 체크표시의 모양은 쓰기 모드에 따라 변경되지 않지만 padding-inline-start 또는 padding-block-end는 변경되기 때문입니다.
6. (선택사항) 선택한 옵션 표시 맞춤설정
기본적으로 <select>는 선택한 옵션의 텍스트 전용 버전을 표시합니다.
선택한 값의 리치 콘텐츠를 표시하려면 <button> 내에서 <selectedcontent>를 사용하거나 선택한 옵션을 다르게 표시합니다 (예: 특정 세부정보 숨기기).
<selectedcontent>는 다른 콘텐츠 요소와 마찬가지로 선택 도구의 일부가 되므로 주변에 <button> 없이 <selectedcontent>를 사용하지 않습니다.
권장사항
- 레이아웃 동작을 테스트합니다.
appearance: base-select를 설정하면 가장 긴 옵션 너비를 기준으로 선택 항목의 크기를 조정하는 기본 브라우저 동작이 삭제됩니다. 레이아웃 변경을 방지하려면 고정 너비를 설정하거나 flex/grid 제약 조건을 사용해야 할 수 있습니다. <select>에name속성과 연결된<label>가 있는지 확인합니다. 이렇게 하면 맞춤 UI를 사용하더라도 스크린 리더가 구성요소에 액세스할 수 있고 표준 양식 제출이 올바르게 작동합니다.- 옵션에 표준
value속성을 사용하여 양식 제출이 이전과 동일하게 작동하도록 합니다.
접근성
네이티브 <select>는 선형 위/아래 화살표 탐색만 처리하므로 왼쪽/오른쪽은 열린 선택 도구에서 아무 작업도 하지 않으며 위/아래는 행과 열에 관계없이 항목을 순차적으로 탐색합니다.
그리드를 따르는 공간 탐색을 구현하려면 화살표 키를 사용할 때 keydown를 가로채고 눌린 방향에서 가장 가까운 옵션으로 포커스를 라우팅하면 됩니다 (예: getBoundingClientRect() 사용).
적절한 다음/이전 항목을 결정하려면 grid-template-columns 또는 grid-column와 같은 CSS 문자열을 파싱하는 대신 실제 도형 (예: getBoundingClientRect())에서 작동하는 DOM 메서드를 사용하세요. 이러한 문자열은 복잡한 그리드, 하위 그리드, RTL, 기타 레이아웃 시나리오에서 취약하고 오류가 발생하기 쉽습니다.
그렇다고 해서 불필요하게 과도하게 설계하지 마세요. 레이아웃에 대해 알고 있는 불변량을 사용하여 이 로직을 단순화하세요.
참고: 이 내용은 키보드 탐색에만 적용됩니다. <select> 및 ::picker()에는 여전히 기본 역할 (menu 또는 listbox)이 있으며, 이 역할은 재정의할 수 없고 role="grid"가 있는 요소를 포함할 수 없습니다.
선택 도구 내에 role="grid"가 있는 래퍼를 중첩하는 것은 실제로 작동하지만 유효하지 않으며 AT 사용자에게 혼란을 줄 수 있습니다.
경우에 따라 <optgroup>를 사용하여 옵션을 그룹화하면 role="grid" 없이도 우수한 스크린 리더 UX를 생성할 수 있습니다.
그렇지 않으면 스크린 리더 사용자를 위해 원하는 UX를 달성하기 위해 팝오버 API, 앵커 위치 지정, role="grid"를 사용하는 맞춤 솔루션으로 전환해야 할 수 있습니다.
대체 전략
맞춤설정 가능한 <select>의 대체 및 브라우저 지원
아직 appearance: base-select를 지원하지 않는 브라우저의 경우 <select> 요소가 표준 운영체제 드롭다운으로 원활하게 다운그레이드됩니다.
- 텍스트가 아닌 콘텐츠 무시: 이전 브라우저는
<option>태그 내의 HTML 태그 (예:<svg>또는<div>)를 제거하고 텍스트 노드만 렌더링합니다.<option>의 텍스트 콘텐츠가 그 자체로 읽기 쉽고 의미가 있는지 확인합니다. - HTML 구조 처리: 표준 파서는
<select>내의<button>및<selectedcontent>태그를 무시하거나 잘못된 것으로 처리할 수 있습니다. 표준 텍스트를 읽을 수 있는 대체로 간주하는 경우 점진적 개선을 위해 무거운 JavaScript 폴리필이 반드시 필요한 것은 아닙니다.
document.addEventListener("DOMContentLoaded", () => {
// Check if browser supports base-select value
if (!CSS.supports("appearance", "base-select")) {
// Custom select overrides are not supported natively.
}
});