कस्टमाइज़ किया जा सकने वाला select API, <select> एलिमेंट और उनके ड्रॉपडाउन पिकर को ऐनिमेट करने के लिए, सीएसएस पर आधारित एक डिक्लेरेटिव तरीका उपलब्ध कराता है. appearance: base-select को सीएसएस ऐनिमेशन की आधुनिक तकनीकों के साथ इस्तेमाल करके, टॉप-लेयर एलिमेंट के लिए फ़्लूइड और प्रीमियम यूज़र इंटरफ़ेस (यूआई) ट्रांज़िशन बनाए जा सकते हैं. इसके लिए, आपको JavaScript की भारी-भरकम लाइब्रेरी पर निर्भर रहने की ज़रूरत नहीं है. इन तकनीकों में, @starting-style और allow-discrete ट्रांज़िशन बिहेवियर शामिल हैं.
पहले, नेटिव सिलेक्ट ड्रॉपडाउन को ऐनिमेट करना नामुमकिन था. इसकी वजह यह थी कि उनका यूज़र इंटरफ़ेस (यूआई), ऐक्सेस किए जा सकने वाले व्यूपोर्ट की सीमाओं से बाहर रेंडर होता था. appearance: base-select की मदद से, पिकर को पेज के किसी अन्य एलिमेंट की तरह स्टाइल किया जा सकता है और ऐनिमेट किया जा सकता है.
इन्हें कैसे लागू करें
ऐनिमेशन वाला सेलेक्ट पिकर लागू करने के लिए:
- पसंद के मुताबिक बनाने की सुविधा के लिए ऑप्ट-इन करना:
<select>एलिमेंट और::picker(select)स्यूडो-एलिमेंट, दोनों परappearance: base-selectलागू करें. - साइज़ अपने-आप बदलने वाले ट्रांज़िशन चालू करना (ज़रूरी नहीं):
interpolate-size: allow-keywordsको तय करें (आम तौर पर:rootपर), ताकि ब्राउज़र कोheight: autoऔरheight: 0जैसी अलग-अलग मेट्रिक वैल्यू के बीच ट्रांज़िशन करने की अनुमति मिल सके. - टॉप-लेयर कंटेनर को ऐनिमेट करना:
::picker(select)पर स्टैंडर्ड एंट्री/एग्ज़िट स्टाइल लागू करें.display: noneऔरdisplay: blockके बीच ट्रांज़िशन के दौरान अपारदर्शिता की सेटिंग काम करे, इसके लिए आपकोtransition-behavior: allow-discreteका इस्तेमाल करना होगा. इसे अक्सर इनलाइन के तौर परtransition: display 0.3s allow-discreteलिखा जाता है. @starting-styleकी मदद से, ओपनिंग स्टेट में हुक करें:@starting-styleका इस्तेमाल करके, उन बेसलाइन स्टाइल को तय करें जिन्हें ब्राउज़र को ट्रांज़िशन शुरू होने से पहले कंप्यूट करना चाहिए. उदाहरण के लिए, अगर आपको इसे फ़ेड इन करना है, तो@starting-styleब्लॉक में ओपैसिटी को0पर सेट करें.- आइकॉन को घुमाना: ऐरो इंडिकेटर पर ट्रांज़िशन (जैसे, घुमाना या ट्रांसलेशन) लागू करने के लिए, सूडो-एलिमेंट फ़ोकस या
:open::picker-iconजैसे ऐक्टिव सिलेक्टर का इस्तेमाल करें.
कोड का उदाहरण: स्मूथ सिलेक्ट स्केल और फ़ेड
यहां दिए गए उदाहरण में, पिकर कंटेनर के लिए स्टैंडर्ड पेज ऐनिमेशन के साथ स्टाइल किया गया कस्टम विकल्प दिखाया गया है.
<!-- Always use a <label> linked via 'for' to the select for accessibility -->
<label for="theme-select">Visual Theme</label>
<select id="theme-select" class="animated-select" name="theme">
<!-- The <button> inside <select> becomes the visible trigger when appearance: base-select is used -->
<button>
<!-- <selectedcontent> automatically displays the content of the chosen <option> -->
<selectedcontent></selectedcontent>
</button>
<option value="system">
<!-- MANDATORY: Decorative inline SVGs MUST set aria-hidden="true" to prevent redundant screen reader announcement -->
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect>
<line x1="8" y1="21" x2="16" y2="21"></line>
<line x1="12" y1="17" x2="12" y2="21"></line>
</svg>
System Default
</option>
<option value="light">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
Light UI
</option>
</select>
/* Opt-in to customizable select */
.animated-select,
.animated-select::picker(select) {
appearance: base-select;
}
/* Enable auto-keyword transitions (usually set globally at :root) */
:root {
interpolate-size: allow-keywords;
}
/* Style the visible trigger and icon rotation */
.animated-select {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
padding: 0.875rem 1rem;
font-size: 1rem;
border-radius: 8px;
cursor: pointer;
transition: border-color 0.2s ease;
}
.animated-select::picker-icon {
transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
.animated-select:open::picker-icon {
transform: rotate(180deg);
}
/*
* The Picker Container
* Uses top-layer animations with `allow-discrete` visibility hooks
*/
.animated-select::picker(select) {
background: white;
border-radius: 12px;
box-shadow: 0 10px 25px -3px rgba(0,0,0,0.1);
padding: 0.5rem;
margin-top: 0.25rem;
width: anchor-size(width);
overflow: hidden;
/* The crucial transition setting for popover animations */
transition:
display 0.4s allow-discrete,
overlay 0.4s allow-discrete,
opacity 0.4s cubic-bezier(0.16, 1, 0.3, 1),
height 0.4s cubic-bezier(0.16, 1, 0.3, 1);
opacity: 0;
height: 0;
}
/* Open State */
.animated-select:open::picker(select) {
opacity: 1;
height: auto;
}
/* @starting-style to hook the transition on initial popover open */
@starting-style {
.animated-select:open::picker(select) {
opacity: 0;
height: 0;
}
}
/* Support for SVG inside Options and Selected Content */
.animated-select option svg,
.animated-select selectedcontent svg {
flex-shrink: 0; /* Prevent icons from shrinking */
width: 1.25rem;
height: 1.25rem;
}
/* MANDATORY: Provide multiple indicators (e.g. bold font and distinct background) for the checked state to avoid color-only state communication */
.animated-select option:checked {
font-weight: 700;
background-color: #f1f5f9;
}
/* Ensure copy-paste safety for users with motion sensitivities */
@media (prefers-reduced-motion: reduce) {
.animated-select::picker(select),
.animated-select::picker-icon {
transition: none !important;
}
}
रणनीति को लागू करने के तरीके और सबसे सही तरीके
- DO use
@starting-stylewhen you need animations to trigger exactly when an element transitions fromdisplay: noneto visible. - ऐड-हॉक स्क्रोल लॉकिंग का इस्तेमाल न करें. 'base-select' से मैनेज किए जाने वाले टॉप-लेयर एलिमेंट में, बैकड्रॉप को सामान्य तरीके से खारिज करने की अनुमति होनी चाहिए.
- ज़रूर देखें कि उपयोगकर्ता ने मोशन कम करने की सेटिंग चालू की है या नहीं. ऐनिमेशन की सीमाओं को हमेशा
prefers-reduced-motionमीडिया क्वेरी में रैप करें. इससे मोशन सिकनेस से पीड़ित लोगों के लिए, सुलभता की सुविधाएं उपलब्ध कराई जा सकेंगी. - लेआउट के काम करने के तरीके की जांच करना.
appearance: base-selectको सेट करने से, डिफ़ॉल्ट ब्राउज़र का वह व्यवहार हट जाता है जिसके तहत, ब्राउज़र सबसे लंबे विकल्प की चौड़ाई के आधार पर, चुने गए विकल्प का साइज़ तय करता है. लेआउट शिफ़्ट रोकने के लिए, आपको तय चौड़ाई सेट करनी पड़ सकती है या फ़्लेक्स/ग्रिड कंस्ट्रेंट का इस्तेमाल करना पड़ सकता है. - पक्का करें कि आपके
<select>मेंnameएट्रिब्यूट और उससे जुड़ा<label>मौजूद हो. इससे यह पक्का होता है कि कस्टम यूज़र इंटरफ़ेस (यूआई) होने पर भी, कॉम्पोनेंट को स्क्रीन रीडर ऐक्सेस कर सकते हैं. साथ ही, यह स्टैंडर्ड फ़ॉर्म सबमिशन के साथ सही तरीके से काम करता है. - विकल्पों पर स्टैंडर्ड
valueएट्रिब्यूट का इस्तेमाल करें, ताकि यह पक्का किया जा सके कि फ़ॉर्म सबमिशन पहले की तरह ही काम करे.
फ़ॉलबैक रणनीतियां
कस्टमाइज़ किए जा सकने वाले <select> के लिए फ़ॉलबैक और ब्राउज़र की सुविधा
जिन ब्राउज़र पर अब तक appearance: base-select काम नहीं करता है उनके लिए, <select> एलिमेंट को स्टैंडर्ड ऑपरेटिंग सिस्टम के ड्रॉपडाउन में बदल दिया जाता है.
- बिना टेक्स्ट वाले कॉन्टेंट को अनदेखा किया जाता है: पुराने ब्राउज़र,
<option>टैग में मौजूद एचटीएमएल टैग (जैसे,<svg>या<div>) को हटा देते हैं और सिर्फ़ टेक्स्ट नोड को रेंडर करते हैं. पक्का करें कि<option>का टेक्स्ट कॉन्टेंट पढ़ने लायक हो और उसका कोई मतलब निकलता हो. - एचटीएमएल स्ट्रक्चर को मैनेज करना: स्टैंडर्ड पार्सर,
<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.
}
});