কাস্টম বেছে নেওয়া পিকার লেআউট

CSS প্রপার্টি appearance: base-select, <select> এলিমেন্ট ও তার পিকারকে (::picker(select)-এর মাধ্যমে) সাধারণ HTML এলিমেন্টের মতো স্টাইল করার ক্ষমতা আনলক করে। Grid বা Flexbox-এর মতো আধুনিক CSS লেআউট টেকনিকের সাথে একত্রিত করে, আপনি প্রথাগত স্ট্যাক করা উল্লম্ব তালিকা থেকে বেরিয়ে আসতে পারেন এবং কাস্টম JS ছাড়াই একটি সমৃদ্ধ ভিজ্যুয়াল অভিজ্ঞতা তৈরি করতে পারেন। যেমন, আপনি display: grid ব্যবহার করে কার্ডের 2D গ্রিড হিসেবে বিকল্পগুলি স্টাইল করতে পারেন।

এটি রঙ চয়নকারী, ইমোজি নির্বাচক বা প্রোডাক্টের ধরনের জন্য আদর্শ যেখানে একটি সমৃদ্ধ ভিজ্যুয়াল মেনু তালিকার চেয়ে বেশি কার্যকর।

কীভাবে প্রয়োগ করতে হয়

১. বেস স্টাইলিং অ্যাক্টিভেট করুন

<select> এলিমেন্ট এবং তার ইন্টার্নাল পিকার সিউডো-এলিমেন্ট select::picker(select), দুটিতেই appearance: base-select প্রয়োগ করুন:

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

২. পিকার কন্টেনার স্টাইল করুন

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) স্টাইল করলে, এটি বাছাইকারীকে দৃশ্যমান করবে, এমনকি যখন নির্বাচন বন্ধ থাকে!

৩. বিকল্প স্টাইল করুন

<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. */
}

৪. বেছে নেওয়া বিকল্প স্টাইল করুন

বেছে নেওয়া বিকল্প স্টাইল করতে, 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 কন্ট্রোলের মতো, শুধুমাত্র রঙের মাধ্যমে স্ট্যাটাস দেখাবেন না এবং কোন বিকল্পটি বেছে নেওয়া হয়েছে তা দেখানোর জন্য একাধিক ভিজ্যুয়াল ইন্ডিকেটর (যেমন, রঙ, বর্ডারের ঘনত্ব, টিকচিহ্ন) ব্যবহার করুন।

৫. (ঐচ্ছিক) বেছে নেওয়া বিকল্পের টিকচিহ্নের স্টাইল পরিবর্তন করুন

ডিফল্ট হিসেবে, ব্রাউজার প্রতিটি <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 ব্যবহার করবেন না, কারণ লেখার মোডের উপর নির্ভর করে এগুলি পরিবর্তিত হবে, যেখানে টিক চিহ্নের আকার পরিবর্তিত হয় না।

৬. (ঐচ্ছিক) বেছে নেওয়া বিকল্পের ডিসপ্লে কাস্টমাইজ করুন

ডিফল্ট হিসেবে, <select> বেছে নেওয়া বিকল্পের শুধু টেক্সট ভার্সন দেখাবে। বেছে নেওয়া ভ্যালুর জন্য রিচ কন্টেন্ট দেখাতে, <button>-এর মধ্যে <selectedcontent> ব্যবহার করুন এবং/অথবা বেছে নেওয়া বিকল্পটি আলাদাভাবে দেখান (যেমন, নির্দিষ্ট বিবরণ লুকান)।

<selectedcontent>-এর চারপাশে <button> না থাকলে <selectedcontent> ব্যবহার করবেন না, কারণ <selectedcontent> অন্য যেকোনও কন্টেন্ট এলিমেন্টের মতো পিকারের অংশ হয়ে যাবে।

পেশাদার পদ্ধতি

  • লেআউট আচরণ পরীক্ষা করুন। appearance: base-select সেট করলে, ডিফল্ট ব্রাউজার আচরণ সরিয়ে দেয়, যা সবচেয়ে দীর্ঘ বিকল্পের প্রস্থের উপর ভিত্তি করে বেছে নেওয়ার সাইজ নির্ধারণ করে। লেআউট শিফ্ট প্রতিরোধ করতে আপনাকে নির্দিষ্ট প্রস্থ সেট করতে বা ফ্লেক্স/গ্রিড কনস্ট্রেন্ট ব্যবহার করতে হতে পারে।
  • আপনার <select>-এ name অ্যাট্রিবিউট এবং সংশ্লিষ্ট <label> আছে কিনা তা নিশ্চিত করুন। এটি নিশ্চিত করে যে কাস্টম UI থাকলেও, কম্পোনেন্টটি স্ক্রিন রিডারের জন্য অ্যাক্সেসযোগ্য থাকে এবং স্ট্যান্ডার্ড ফর্ম জমা দেওয়ার সাথে সঠিকভাবে কাজ করে।
  • ফর্ম জমা দেওয়ার প্রক্রিয়া যাতে আগের মতোই কাজ করে তা নিশ্চিত করতে বিকল্পে স্ট্যান্ডার্ড value অ্যাট্রিবিউট ব্যবহার করুন।

অ্যাক্সেসিবিলিটি

নেটিভ <select> শুধুমাত্র লিনিয়ার উপরে/নিচে তীরচিহ্ন নেভিগেশন ম্যানেজ করে, তাই খোলা পিকারে বাঁদিকে/ডানদিকে কিছু করে না এবং উপরে/নিচে এখনও সারি এবং কলাম নির্বিশেষে আইটেমগুলি ক্রমানুসারে নেভিগেট করে।

গ্রিড অনুসরণ করে এমন স্পেশিয়াল নেভিগেশন প্রয়োগ করতে, আপনি keydown ইন্টারসেপ্ট করতে পারেন এবং তীরচিহ্ন কী ব্যবহার করা হলে, যেদিকে প্রেস করা হয়েছে সেই দিকে সবচেয়ে কাছের বিকল্পে ফোকাস রুট করতে পারেন (যেমন, getBoundingClientRect() ব্যবহার করে)। উপযুক্ত পরবর্তী/পূর্ববর্তী আইটেম নির্ধারণ করতে, DOM পদ্ধতি ব্যবহার করুন যা প্রকৃত জ্যামিতিতে কাজ করে (যেমন getBoundingClientRect()) grid-template-columns বা grid-column-এর মতো CSS স্ট্রিং পার্স করার পরিবর্তে, যা জটিল গ্রিড, সাবগ্রিড, 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> ট্যাগ উপেক্ষা করতে পারে বা সেগুলিকে ভুল হিসেবে বিবেচনা করতে পারে। আপনি যদি স্ট্যান্ডার্ড টেক্সটকে রিডেবল ফলব্যাক হিসেবে দেখেন, তাহলে প্রোগ্রেসিভ এনহ্যান্সমেন্টের জন্য কোনও ভারী জাভাস্ক্রিপ্ট পলিফিলের প্রয়োজন নেই।
document.addEventListener("DOMContentLoaded", () => {
  // Check if browser supports base-select value
  if (!CSS.supports("appearance", "base-select")) {
    // Custom select overrides are not supported natively.
  }
});