ساخت custom select با استفاده از ویژگی appearance: base-select در CSS

همون‌طور که در پست قبلی اشاره کردم چالش‌های این ماه CodePen درباره ویژگی‌های جدید CSS که امسال معرفی شدن هست. چالش هفته دوم ساخت custom select با استفاده از appearance: base-select بوده؛ روش جدیدی که در ادامه درباره‌ش توضیح می‌دم.

احتمالا می‌دونید که تغییر ظاهر عنصر <select> کار دشواریه، چون این عنصر یکسری بخش‌های داخلی داره که در سطح سیستم عامل استایل‌دهی میشن و نمیشه با استفاده از انتخابگرهای CSS به اونها دسترسی داشت و تغییری در ظاهر این بخش‌ها ایجاد کرد.

customizable select راه‌حلی برای حل این مشکل ارائه می‌کنه و به شما این امکان رو میده که در مرورگرهایی که از این ویژگی پشتیبانی می‌کنند – در حال حاضر فقط از نسخه ۱۳۵ به بعد در Chrome پشتیبانی میشه – بطور کامل ساختار عنصر <select> رو تغییر بدید.

در دمو زیر می‌تونید نمونه‌ای که برای چالش CodePen با استفاده از این ویژگی ساختم رو مشاهده کنید.

ساختار HTML یه custom select

عنصرهای قدیمی <select>، <option>، و <optgroup> مثل قبل کار می‌کنند ولی با استفاده از customizable select می‌تونید از عنصرهای دیگه‌ای مثل <button> یا <div> در صورت لزوم داخل این عنصرها استفاده کنید. کدهای زیر نمونه ساده‌ای از ساختار HTML یه custom select رو نشون میده.

<select>
  <button>
    <selectedcontent></selectedcontent>
  </button>

  <option value="hamburger">
    <div class="custom-option">
      <span class="indicator">🍔</span>
      <span class="option-text">Hamburger</span>
    </div>
  </option>
  <option value="pizza">
    <div class="custom-option">
      <span class="indicator">🍕</span>
      <span class="option-text">Pizza</span>
    </div>
  </option>
  <option value="hot-dog">
    <div class="custom-option">
      <span class="indicator">🌭</span>
      <span class="option-text">Hot Dog</span>
    </div>
  </option>
</select>

همون‌طور که می‌بینید تگ‌های HTML یه customizable select تفاوت‌هایی با عنصر <select> معمولی یا کلاسیک داره که در ادامه توضیح میدم:

  • اول از همه یه عنصر <button> داریم که به‌عنوان اولین فرزند داخل <select> قرار گرفته. اگر این دکمه وجود داشته باشه به عنوان select button جایگزین دکمه‌ی پیش‌فرض می‌شه و با کلیک روی این دکمه لیست گزینه‌ها یا انتخابگر کشویی (drop-down picker) باز خواهد شد.
  • داخل عنصر <button> یک عنصر جدید بنام <selectedcontent> داریم. وظیفه‌اش اینه که یه نسخه‌ی کپی (clone) از گزینه‌ی انتخاب‌شده رو — همراه با محتوای کاملش، حتی اگر شامل تگ‌های HTML باشه — نشون بده.
  • خود <option>‌ها هم مثل <select> کلاسیک وجود دارن، با این تفاوت که این‌بار می‌تونید داخلشون از انواع تگ‌های HTML هم استفاده کنید.

نکته‌ی جالب درباره‌ی ساختار HTML این نوع custom select اینه که اگر همین کد رو توی مرورگری که این قابلیت رو پشتیبانی نمی‌کنه inspect کنید، فقط تگ‌های <select> و <option> رو می‌بینید و باقی تگ‌های اضافه توسط مرورگر حذف می‌شن.

فعال کردن قابلیت customizable select در CSS

برای فعال کردن قابلیت customizable select عنصر <select> و لیست گزینه‌ها یا انتخابگر کشویی که با شبه عنصر ::picker(select) نمایش داده میشه باید مقدار appearance: base-select رو داشته باشند:

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

می‌تونید فقط خود <select> رو انتخاب کنید و اجازه بدید انتخابگر کشویی همون ظاهر پیش‌فرض سیستم‌عامل رو داشته باشه؛ اما معمولاً بهتره هر دو رو با هم انتخاب کنید. نکته اینجاست که نمی‌تونید فقط picker رو بدون select انتخاب کنید.

وقتی این کار رو انجام بدید، خروجی‌تون یه <select> با استایل خیلی ساده و قابل‌کنترل خواهد بود که می‌شه راحت با CSS تغییرش داد. می‌تونید استایل‌های پیش‌فرض <select> رو با چند خط CSS حذف کنید و به‌جاش روی استایل‌دهی به <button> تمرکز کنید.

select {
  background: none;
  border: 0;
  padding: 0;
  outline: none;
}

استایل‌دهی به آیکون انتخابگر (picker-icon)

برای استایل‌دهی به آیکون داخل <button> – فلشی که هنگام بسته بودن <select> به سمت پایین اشاره می‌کنه – می‌تونید از شبه عنصر ::picker-icon استفاده کنید.

select::picker-icon {
  transition: 0.4s rotate;
}

همونطور که در کد بالا می‌بینید می‌تونید transition را برای این عنصر فعال کنید و با استفاده از transform و شبه کلاس :open زمانی که انتخابگر باز شد جهت آیکون را تغییر بدید:

select:open::picker-icon {
  rotate: 180deg;
}

یا اینکه آیکون پیش فرض رو با استفاده از display: none مخفی کنید و یه آیکون متفاوت از نوع SVG به <select> اضافه کنید. برای این کار آیکون را داخل تگ <button> و بعد از تگ <selectedcontent> قرار بدید:

<button>
  <selectedcontent></selectedcontent>

  <svg width="24" height="24" viewBox="0 0 24 24">
    <path fill="currentColor" d="m7 10l5 5l5-5z"/>
  </svg>
</button>

استایل‌دهی به انتخابگر کشویی (drop-down picker)

لیست گزینه‌ها یا انتخابگر کشویی هر چیزی‌ که درون عنصر <select> قرار داره را شامل میشه، به جز <button> و <selectedcontent>. در مثال ما، این به معنای تمام عناصر <option> و محتویات آنهاست.

می‌تونید با استفاده از شبه عنصر ::picker(select) در CSS انتخاب کنید و استایلش رو تغییر بدید، در مثال زیر border پیش‌فرض picker حذف شده.

::picker(select) {
  border: none;
}

استایل‌دهی به گزینه‌ (option) های select

برای استایل‌دهی به تگ‌های <option> هم خیلی راحت می‌تونید از کلاس custom-option یا خود option استفاده کنید:

option {
  /* your code */
}

برای دسترسی به گزینه‌ای که انتخاب شده هم می‌تونید از شبه کلاس :checked استفاده کنید:

option:checked {
  /* your code */
}

همچنین با استفاده از شبه عنصر ::checkmark می‌تونید به علامت تیک داخل گزینه انتخاب شده دسترسی داشته باشید و استایلش رو تغییر بدید، در مثال زیر علامت تیک تغییر می‌کنه و به سمت راست منتقل میشه.

option::checkmark {
  order: 1;
  margin-left: auto;
  content: "☑️";
}

جمع بندی

فکر می‌کنم همه‌ی نکات لازم رو توضیح دادم و امیدوارم براتون مفید بوده باشه. اگر دوست دارید بیشتر وارد جزئیات بشید، پیشنهاد می‌کنم مقاله‌ی Customizable select elements رو بخونید.