কাস্টমাইজ করা যায় এমন সিলেক্ট API, <select> এলিমেন্ট ও তার ড্রপডাউন পিকার অ্যানিমেট করার জন্য একটি ডিক্লারেটিভ, CSS-চালিত উপায় অফার করে। আধুনিক CSS অ্যানিমেশন টেকনিকের সাথে appearance: base-select একত্রিত করে—যেমন @starting-style এবং allow-discrete ট্রানজিশন আচরণ—আপনি ভারী JavaScript লাইব্রেরির উপর নির্ভর না করেই টপ-লেয়ার এলিমেন্টের জন্য ফ্লুইড, প্রিমিয়াম UI ট্রানজিশন তৈরি করতে পারেন।
আগে, নেটিভ সিলেক্ট ড্রপডাউন অ্যানিমেট করা অসম্ভব ছিল কারণ তাদের UI অ্যাক্সেসযোগ্য ভিউপোর্ট সীমাবদ্ধতার বাইরে রেন্ডার করা হয়েছিল। appearance: base-select-এর মাধ্যমে, পিকারটি অন্য যেকোনও পৃষ্ঠা এলিমেন্টের মতো স্টাইলযোগ্য এবং অ্যানিমেটেবল হয়ে ওঠে।
কীভাবে প্রয়োগ করতে হয়
অ্যানিমেটেড সিলেক্ট পিকার প্রয়োগ করতে:
- কাস্টমাইজেশন চালু করা:
<select>এলিমেন্ট এবং::picker(select)ছদ্ম-এলিমেন্ট, দুটিতেইappearance: base-selectপ্রয়োগ করুন। - অটো-সাইজিং ট্রানজিশন চালু করুন (ঐচ্ছিক):
height: autoএবংheight: 0-এর মতো ডিসক্রিট মেট্রিক ভ্যালুর মধ্যে ব্রাউজারকে ট্রানজিশন করার অনুমতি দিতেinterpolate-size: allow-keywords(সাধারণত:root-এ) নির্ধারণ করুন। - টপ-লেয়ার কন্টেনার অ্যানিমেট করুন:
::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;
}
}
স্ট্র্যাটেজিক প্রয়োগ ও পেশাদার পদ্ধতি
- কোনও এলিমেন্ট
display: noneথেকে দৃশ্যমান হওয়ার সময় অ্যানিমেশন ট্রিগার করতে চাইলে@starting-styleব্যবহার করুন। - অ্যাড-হক স্ক্রল লকিং ব্যবহার করবেন না। ‘base-select’ দ্বারা ম্যানেজ করা টপ-লেয়ার এলিমেন্টকে স্বাভাবিক ব্যাকড্রপ ডিসমিস আচরণ করার অনুমতি দিতে হবে।
- অবশ্যই রিডিউসড মোশন সংক্রান্ত পছন্দ যাচাই করুন। মোশন সিকনেসে আক্রান্ত ব্যক্তিদের জন্য অ্যাক্সেসযোগ্য পরিবেশ নিশ্চিত করতে, সবসময়
prefers-reduced-motionমিডিয়া কোয়েরিতে অ্যানিমেশন কনস্ট্রেন্ট র্যাপ করুন। - লেআউট আচরণ পরীক্ষা করুন।
appearance: base-selectসেট করলে, ডিফল্ট ব্রাউজার আচরণ সরিয়ে দেয়, যা সবচেয়ে দীর্ঘ বিকল্পের প্রস্থের উপর ভিত্তি করে বেছে নেওয়ার সাইজ নির্ধারণ করে। লেআউট শিফ্ট প্রতিরোধ করতে আপনাকে নির্দিষ্ট প্রস্থ সেট করতে বা ফ্লেক্স/গ্রিড কনস্ট্রেন্ট ব্যবহার করতে হতে পারে। - আপনার
<select>-এnameঅ্যাট্রিবিউট এবং সংশ্লিষ্ট<label>আছে কিনা তা নিশ্চিত করুন। এটি নিশ্চিত করে যে কাস্টম UI থাকলেও, কম্পোনেন্টটি স্ক্রিন রিডারের জন্য অ্যাক্সেসযোগ্য থাকে এবং স্ট্যান্ডার্ড ফর্ম জমা দেওয়ার সাথে সঠিকভাবে কাজ করে। - ফর্ম জমা দেওয়ার প্রক্রিয়া যাতে আগের মতোই কাজ করে তা নিশ্চিত করতে বিকল্পে স্ট্যান্ডার্ড
valueঅ্যাট্রিবিউট ব্যবহার করুন।
ফলব্যাক স্ট্র্যাটেজি
কাস্টমাইজ করা যায় এমন <select>-এর জন্য ফলব্যাক ও ব্রাউজার সাপোর্ট
যেসব ব্রাউজারে এখনও appearance: base-select কাজ করে না, সেখানে <select> এলিমেন্ট স্ট্যান্ডার্ড অপারেটিং সিস্টেম ড্রপডাউনে অবনমিত হয়।
- টেক্সট নয় এমন কন্টেন্ট উপেক্ষা করা হয়েছে: পুরনো ব্রাউজার
<option>ট্যাগের মধ্যে HTML ট্যাগ (যেমন<svg>বা<div>) বাদ দিয়ে শুধু টেক্সট নোড দেখায়।<option>-এর টেক্সট কন্টেন্ট যেন পাঠযোগ্য এবং অর্থপূর্ণ হয় তা নিশ্চিত করুন। - HTML স্ট্রাকচার ম্যানেজ করা: স্ট্যান্ডার্ড পার্সার
<select>-এর মধ্যে<button>এবং<selectedcontent>ট্যাগ উপেক্ষা করতে পারে বা সেগুলিকে ভুল হিসেবে বিবেচনা করতে পারে। আপনি যদি স্ট্যান্ডার্ড টেক্সটকে রিডেবল ফলব্যাক হিসেবে দেখেন, তাহলে প্রোগ্রেসিভ এনহ্যান্সমেন্টের জন্য কোনও ভারী জাভাস্ক্রিপ্ট পলিফিলের প্রয়োজন নেই।
document.addEventListener("DOMContentLoaded", () => {
// Check if browser supports base-select value
if (!CSS.supports("appearance", "base-select")) {
// Custom select overrides are not supported natively.
}
});