Добро пожаловать на сайт SEDBY

Воспроизводим HTML Select с помощью Bootstrap

  • 144 просмотра +1
  • 24 января, 2026
  • Обновлено: 25 января, 2026
  • admin
  • Время чтения: 7 минут
Воспроизводим HTML Select с помощью Bootstrap

Необходимость в имитации HTML-элемента возникает редко, и, как правило, если речь заходит об ограничениях. Одним из наиболее проблемных в этом плане является элемент формы select.

Преамбула

В практике веб-разработчика form <select> встречается довольно часто, и стилизуется он с вполне решаемыми трудностями. При использовании CSS-фреймворка Bootstrap все вообще просто: достаточно применить к селекту класс .form-select, и он получит оформление, единообразное с другими элементами формы. И дальнейшая кастомизация не вызовет каких-либо проблем.

Кстати, напомним стандартную разметку:

<select name="codes" id="codes">
  <option value="">--Please choose country code--</option>
  <option value="by">Belarus</option>
  <option value="ru">Russia</option>
</select>

Другой вопрос – присутствие в элементах <option> разметки и, например, графических изображений. Здесь стандарты начинают уходить в отказ: вам доступен только неразмеченный текст. Проблема в том, что клиенту можно попробовать объяснить, почему его задача нерешаема, но понять и принять ваше объяснение он вряд ли сможет. Поэтому приходится думать.

Проблема на примере рабочего кейса

Одним из самых распространенных кейсов, связанных с нашей сегодняшней проблемой, является использование селекта для выбора телефонного кода страны. Это аспект юзабилити, позволяющий с одной стороны облегчить вашему посетителю ввод контактной информации, а с другой – обезопасить администратора проекта от получения некорректных данных.

Очевидно, что для удобства элемент <option> должен включать в себя изображение. В нашем случае – флага страны, код которой выбирает посетитель. Какие же решения приходят на ум в первую очередь?

Самое простое – использовать стандартизированные пиктограммы emoji, о которых мы уже начали понемногу забывать. Пусть это не совсем удобно для веб-разработчика, но, на первый взгляд, работает.

Проблемы начинаются при тестировании, когда мы узнаем о том, что:

  1. Emoji на разных платформах будут отображаться по-разному.
  2. Из OS Windows по причинам политкорректности (политкорректности, Карл!) изображения флагов вообще исключены.
  3. Некоторые браузеры (например, Mozilla Firefox) имеют собственные emoji флагов.

На практике получаем следующую картину:

Как выглядит один emoji на различных платформах
Как выглядит один emoji на различных платформах

В сухом остатке совершенно дикая разносортица, отчитаться за которую перед заказчиком будет сложновато.

Пробные решения

Самое очевидное – использовать SVG-спрайты. Но их создание может затянуться надолго. Еще один вариант – грузить шрифт с флагами. Если вас устроит, существует проект Twemoji или гораздо более интересный Country Flag Emoji Polyfill. Для использования загрузим библиотеку и запустим функцию подмены:

<script type="module" defer>
  import { polyfillCountryFlagEmojis } from "https://cdn.skypack.dev/country-flag-emoji-polyfill";
  polyfillCountryFlagEmojis();
</script>

Теперь просто подключим шрифт первым:

@sans: 'Twemoji Country Flags', 'Open Sans', sans-serif;

При обнаружении флаг-кода emoji, будет скачан только тот фрагмент шрифта, который необходим для заполнения пробелов. В общем и целом, неплохо, но если продолжать базировать подход на использовании emoji, нам придется решать и другие вопросы с их помощью. Чем дальше, тем менее интересным все это будет становиться.

Решаем проблему быстро и красиво

Даже если данные селекта в форме необходимо использовать, самым правильным будет имитация form select с помощью кастомной разметки и скрипта. Это несложная задача, с которой справится даже начинающий верстальщик. Однако если у вас установлен Bootstrap, объем работ можно сократить наполовину.

Мы будем использовать класс .dropdown, который позволит нам уже со старта получить адаптивную имитацию селекта:

<div class="dropdown">
  <button class="btn dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
    Dropdown button
  </button>
  <ul class="dropdown-menu">
    <li><a class="dropdown-item" href="#">Action</a></li>
    <li><a class="dropdown-item" href="#">Another action</a></li>
    <li><a class="dropdown-item" href="#">Something else here</a></li>
  </ul>
</div>

Теперь заменим текстуальную часть на изображения флагов и подписи к ним:

<div class="dropdown">
  <button id="currentcode" class="btn dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
    <img src="images/flags/by.svg" alt="{PHP.cot_countries.by}" />
  </button>
  <ul id="codeselector" class="dropdown-menu">
    <li>
      <a class="dropdown-item" href="#">
        <img src="images/flags/by.svg" alt="{PHP.cot_countries.by}" />
        <span>{PHP.cot_countries.by}</span>
      </a>
    </li>
    <li>
      <a class="dropdown-item" href="#">
        <img src="images/flags/ru.svg" alt="{PHP.cot_countries.ru}" />
        <span>{PHP.cot_countries.ru}</span>
      </a>
    </li>
  </ul>
</div>

Результат показывает, что нам понадобится лишь изменить цвет обводки элемента <button>:

button#currentcode { border-color: rgb(222, 226, 230); }

jQuery-скрипт для обработки

Поскольку физически селекта больше не существует, вместо события change() мы будем обрабатывать событие click(). Код страны будем брать из атрибута data-code:

const selectElement = $('#codeselector');
selectElement.find('a').click(function(e) {
  e.preventDefault();
  code = $(this).attr('data-code');
  pict = $(this).find('img').clone();
  $('#currentcode').html(pict);
  switch (code) {
    case 'by':
      // Something here
      break;
    case 'ru':
      // Something here
      break;
    default:
      // Something here
      break;
  }
});

Обратите внимание на использование метода .clone() – мы дублируем картинку, но не переносим ее в новый контейнер.

Еще один важный момент: в Bootstrap-стиле элемента button используется псевдоэлемент ::after. Чтобы он не удалялся при дублировании картинки, используем вложенный элемент <span>.

Готовая разметка с добавлением встроенных бутстраповских классов будет выглядеть так:

<div class="dropdown">
  <button id="currentcode" class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
    <span><img src="images/flags/by.svg" alt="BY" /></span>
  </button>
  <ul id="codeselector" class="dropdown-menu">
    <li>
      <a class="dropdown-item d-flex gap-2" href="#" data-code="by">
        <img src="images/flags/by.svg" alt="{PHP.cot_countries.by}" />
        <span>{PHP.cot_countries.by}</span>
      </a>
    </li>
    <li>
      <a class="dropdown-item d-flex gap-2" href="#" data-code="ru">
        <img src="images/flags/ru.svg" alt="{PHP.cot_countries.ru}" />
        <span>{PHP.cot_countries.ru}</span>
      </a>
    </li>
  </ul>
</div>

, а готовый код – следующим образом:

const selectElement = $('#codeselector');
selectElement.find('a').click(function(e) {
  e.preventDefault();
  code = $(this).attr('data-code');
  pict = $(this).find('img').clone();
  $('#currentcode > span').html(pict);
  switch (code) {
    case 'by':
      // Something here
      break;
    case 'ru':
      // Something here
      break;
    default:
      // Something here
      break;
  }
});

Заключение

Если вам требуется кастомизация элемента формы <select> (например, добавление в нее графики), самым простым и наименее ресурсоемким способом будет его радикальная трансформация в другую разметку. Чем дольше вы будете тащить в код emoji и шрифты для замены символов, тем более неповоротливым и негибким он будет становиться.

Радикальный способ на наш взгляд гораздо привлекательнее. Переверстывание селекта несложно выполнить вручную, а если вы используете "бортовой" Bootstrap, делать вообще практически ничего не придется.

Ранее мы определяли все "за" и "против" использования элементов label в формах.


Комментарии:
Комментарии отсутствуют

Новый комментарий

Ваш комментарий будет доступен для редактирования 10 минут
Блок пользователя
Регистрация на нашем сайте позволит вам общаться на форумах и получить доступ к другому полезному функционалу
Вы вошли как Гость