Yerel <select> öğesinin stilini belirlemek geçmişte zordu ve yalnızca düz metin seçenekleri içerebiliyordu. appearance: base-select özelliği, <select> öğesi için özelleştirilebilir bir durumu etkinleştirmenin açıklayıcı ve yalnızca CSS içeren bir yolunu sunar. Bu sayede geliştiriciler, yerel klavye erişilebilirliğini ve form entegrasyonunu korurken <option> öğelerine resimler, SVG'ler ve karmaşık düzenler gibi zengin HTML içerikleri ekleyebilir. Ağır, özel olarak oluşturulmuş seçim bileşenlerini standart, yerel öğelerle değiştirmek için bu kalıbı kullanın.
Nasıl uygulanır?
Customizable Select API'yi kullanarak zengin medya seçici uygulamak için:
- Temel stilleri etkinleştirme:
::picker(select)sözde öğesini kullanarakappearance: base-selectstilini hem<select>öğesine hem de dahili seçicisine uygulayın. Bu, tarayıcının<select>içindeki içerikler için HTML ayrıştırıcısını değiştirir. - Düğme içeriğini tanımlama: Seçici kapatıldığında nelerin gösterileceğini tanımlamak için
<select>içinde standart<button>ve<selectedcontent>öğelerini kullanın.<selectedcontent>öğesi, seçilen seçeneğin içeriğini otomatik olarak yansıtır. Şu anda seçili olan zengin içeriği düğmede görüntülemek istiyorsanız bu gereklidir. - Seçeneklerde zengin içerik kullanma: Artık
<option>etiketlerinin içine resim, SVG ve diğer HTML etiketlerini yerleştirebilirsiniz. Bu API'den önce tarayıcı,<option>etiketlerinden etiketleri çıkarır ve yalnızca düz metin oluştururdu. - Popover'ı biçimlendirme:
::picker(select)sözde öğesini hedefleyerek açılır seçenekler listesini biçimlendirin. Üst katmanda oluşturulduğu içinz-indexile uğraşmanız gerekmez. Seçenekler, Anchor Positioning API kullanılarak yerel olarak konumlandırılır.
Örnek Kod: Zengin Rol Seçici
<label for="role-picker">Select your role</label>
<select class="custom-select" name="role" id="role-picker">
<button>
<selectedcontent></selectedcontent> <!-- Mirrors the selected option's content automatically so you do not need JS to update the button -->
</button>
<!-- Define concise aria-label values on options whose mirrored rich content would otherwise read awkwardly as a concatenated string -->
<option value="frontend" aria-label="Frontend Developer">
<svg aria-hidden="true" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect>
</svg>
<div class="option-text">
<span class="option-title">Frontend Developer</span>
<span class="option-desc">React, Vue, CSS</span>
</div>
</option>
<option value="backend" aria-label="Backend Developer">
<svg aria-hidden="true" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<rect x="2" y="12" width="20" height="14" rx="2" ry="2"></rect>
</svg>
<div class="option-text">
<span class="option-title">Backend Developer</span>
<span class="option-desc">Node.js, Python</span>
</div>
</option>
</select>
select.custom-select,
select.custom-select::picker(select) {
appearance: base-select; /* MUST opt-in both the select and its picker to enable the customizable state, otherwise browser standard rendering applies */
}
select.custom-select {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
padding: 12px;
background-color: #1e293b;
border: 1px solid #334155;
border-radius: 8px;
color: #f1f5f9;
cursor: pointer;
}
select.custom-select::picker(select) {
background-color: #0f172a;
border: 1px solid #334155;
border-radius: 8px;
padding: 8px;
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.5);
width: anchor-size(width); /* Uses Anchor Positioning API to keep the dropdown precisely aligned to the button trigger width */
}
select.custom-select option {
display: flex;
align-items: center;
gap: 12px;
padding: 10px;
border-radius: 4px;
cursor: pointer;
}
select.custom-select option:hover {
background-color: #1e293b;
}
/* Remove standard OS checkmark for base-select */
select.custom-select option::before {
display: none;
}
/* MANDATORY: Provide multiple visual indicators (e.g., prominent background color and bold title font) to communicate the checked state cleanly */
select.custom-select option:checked {
background-color: #3b82f6;
color: #ffffff;
}
select.custom-select option:checked .option-title {
font-weight: 700;
}
Stratejik Uygulama ve En İyi Uygulamalar
- Daha önce yalnızca ağır JavaScript kullanıcı arayüzü çerçeveleriyle mümkün olan karmaşık seçenek düzenlerine (simgeler, açıklamalar, resimler) ihtiyacınız olduğunda
appearance: base-selectKULLANIN. - Performans gecikmeleri fark ederseniz geçici öğeler KULLANMAYIN. Tarayıcı, yerel klavye odağını yerel olarak işler.
- DO account for top-layer rendering. Seçici, en üst katmanda oluşturulur. Yani sayfa içeriğinin göreceli
z-indexdeğerini geçersiz kılar. .custom-select selectedcontent .option-desc { display: none; }öğesini biçimlendirerek düğme durumunda çok fazla yer kaplayan ikincil ayrıntıları (açıklamalar gibi) GİZLEYİN.- Düzen davranışını test edin.
appearance: base-selectayarı, seçimi en uzun seçenek genişliğine göre boyutlandırma şeklindeki varsayılan tarayıcı davranışını kaldırır. Düzen kaymalarını önlemek için sabit bir genişlik ayarlamanız veya flex/grid kısıtlamaları kullanmanız gerekebilir. <select>öğenizin birnameözelliğine ve ilişkili bir<label>özelliğine sahip olduğundan emin olun. Bu sayede, özel bir kullanıcı arayüzü olsa bile bileşen ekran okuyucular tarafından erişilebilir durumda kalır ve standart form gönderimleriyle doğru şekilde çalışır.- Form gönderiminin eskisi gibi çalışması için seçeneklerde standart
valueözelliklerini kullanın.
Yedek Stratejiler
Özelleştirilebilir <select> için yedekler ve tarayıcı desteği
Henüz appearance: base-select öğesini desteklemeyen tarayıcılar için <select> öğesi, standart bir işletim sistemi açılır listesine sorunsuz bir şekilde indirgenir.
- Metin Olmayan İçerik Yok Sayılır: Eski tarayıcılar,
<option>etiketlerinin içindeki HTML etiketlerini (<svg>veya<div>gibi) kaldırır ve yalnızca metin düğümlerini oluşturur.<option>öğesinin metin içeriğinin okunabilir ve kendi başına anlamlı olduğundan emin olun. - HTML Yapısı İşleme: Standart ayrıştırıcılar,
<select>içindeki<button>ve<selectedcontent>etiketlerini yoksayabilir veya geçersiz olarak değerlendirebilir. Standart metni okunabilir bir yedek olarak görüyorsanız progresif geliştirme için ağır JavaScript polyfill'leri kesinlikle gerekli değildir.
document.addEventListener("DOMContentLoaded", () => {
// Check if browser supports base-select value
if (!CSS.supports("appearance", "base-select")) {
// Custom select overrides are not supported natively.
}
});