Изображения в опциях

Поддержка HTML-контента внутри <option>

Базовый механизм отображения изображений в списке Slim Select опирается на то, что библиотека заменяет стандартный <select> кастомной разметкой. В результате содержимое <option> перестаёт ограничиваться текстом и может включать HTML, если это допускается конфигурацией и режимом рендера.

Наиболее прямой способ — внедрение изображения прямо в содержимое опции:

<select id="country-select">
  <option value="kz">
    <img src="/flags/kz.png" alt=""> Казахстан
  </option>
  <option value="ru">
    <img src="/flags/ru.png" alt=""> Россия
  </option>
  <option value="us">
    <img src="/flags/us.png" alt=""> США
  </option>
</select>

В таком виде Slim Select при инициализации преобразует содержимое опций в кастомный список, где HTML внутри option становится частью отображаемого элемента.

Ключевая особенность подхода заключается в том, что:

  • изображение становится частью текста опции;
  • управление стилями полностью ложится на CSS;
  • структура данных остаётся минимальной.

Использование data-* атрибутов для изображений

Более управляемый и масштабируемый способ — хранение ссылки на изображение в атрибутах data-*. Это позволяет отделить данные от представления.

<select id="users-select">
  <option value="1" data-avatar="/avatars/user1.jpg">Иван Петров</option>
  <option value="2" data-avatar="/avatars/user2.jpg">Анна Смирнова</option>
  <option value="3" data-avatar="/avatars/user3.jpg">Дмитрий Соколов</option>
</select>

Далее изображение выводится через кастомный рендеринг опции.


Кастомный рендер опций с изображениями

Slim Select предоставляет возможность переопределять отображение элементов списка через настройки рендера (в зависимости от версии API используется подход с шаблонизацией option и selected).

Типовой паттерн:

new SlimSelect({
  select: '#users-select',
  settings: {
    showSearch: true
  },
  // концептуально: кастомизация вывода
  option: (data) => {
    const img = data.element?.dataset?.avatar;

    return `
      <div class="ss-option">
        <img class="ss-avatar" src="${img}" alt="">
        <span>${data.text}</span>
      </div>
    `;
  },
  selected: (data) => {
    const img = data.element?.dataset?.avatar;

    return `
      <div class="ss-selected">
        <img class="ss-avatar" src="${img}" alt="">
        <span>${data.text}</span>
      </div>
    `;
  }
});

Такой подход позволяет:

  • полностью контролировать структуру опции;
  • добавлять аватары, иконки, бейджи;
  • менять отображение выбранного значения независимо от списка.

Иконки через CSS-классы

Альтернативная модель — привязка изображений через CSS-классы вместо <img>.

<option value="kz" class="flag flag-kz">Казахстан</option>
<option value="ru" class="flag flag-ru">Россия</option>
<option value="us" class="flag flag-us">США</option>
.flag {
  padding-left: 28px;
  background-repeat: no-repeat;
  background-position: left center;
  background-size: 20px 14px;
}

.flag-kz { background-image: url("/flags/kz.png"); }
.flag-ru { background-image: url("/flags/ru.png"); }
.flag-us { background-image: url("/flags/us.png"); }

Преимущества:

  • отсутствие <img> тегов;
  • более высокая производительность при больших списках;
  • удобное кеширование через CSS.

Опции с динамической загрузкой изображений

При работе с удалёнными данными изображения часто приходят вместе с JSON-ответом API. В этом случае Slim Select инициализируется уже после подготовки <option>:

const select = document.querySelector('#users-select');

fetch('/api/users')
  .then(res => res.json())
  .then(users => {
    users.forEach(user => {
      const option = document.createElement('option');
      option.value = user.id;
      option.textContent = user.name;
      option.dataset.avatar = user.avatar;
      select.appendChild(option);
    });

    new SlimSelect({
      select: '#users-select',
      settings: {
        showSearch: true
      }
    });
  });

Такой подход сохраняет:

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

Отображение изображений в выбранном значении

В Slim Select важно разделять два уровня отображения:

  • список опций;
  • выбранное значение.

Часто требуется отображать изображение не только в списке, но и в поле выбора.

.ss-selected img {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  margin-right: 8px;
}
selected: (data) => {
  const avatar = data.element?.dataset?.avatar;

  return `
    <div class="ss-selected-content">
      <img src="${avatar}" />
      <span>${data.text}</span>
    </div>
  `;
}

Такой паттерн особенно характерен для:

  • списков пользователей;
  • CRM-интерфейсов;
  • выбора контактов и участников.

Оптимизация загрузки изображений

При большом количестве опций изображения становятся критическим фактором производительности.

Используются следующие техники:

1. Lazy loading через loading="lazy"

<img src="/avatars/user.jpg" loading="lazy">

2. Превью-версии изображений Использование миниатюр вместо оригиналов:

/avatars/user.jpg → /avatars/thumbs/user.jpg

3. Предзагрузка видимых элементов

const preload = (url) => {
  const img = new Image();
  img.src = url;
};

Обработка ошибок загрузки изображений

При динамических данных неизбежны битые ссылки. В кастомных шаблонах добавляется fallback:

option: (data) => {
  const avatar = data.element?.dataset?.avatar;

  return `
    <div class="ss-option">
      <img src="${avatar}"
           oner ror="this.src='/avatars/default.png'">
      <span>${data.text}</span>
    </div>
  `;
}

Такой механизм предотвращает визуальные разрывы интерфейса.


Группировка изображений в опциях

При использовании <optgroup> изображения могут комбинироваться с логической группировкой:

<optgroup label="Команды">
  <option data-avatar="/team/a.png">Команда A</option>
  <option data-avatar="/team/b.png">Команда B</option>
</optgroup>

В кастомном рендере учитывается уровень вложенности:

option: (data) => {
  const avatar = data.element?.dataset?.avatar;

  return `
    <div class="ss-option ${data.group ? 'ss-grouped' : ''}">
      ${avatar ? `<img src="${avatar}">` : ''}
      <span>${data.text}</span>
    </div>
  `;
}

Унификация структуры изображений

При проектировании интерфейса с Slim Select изображения часто стандартизируются по типу:

  • квадратные аватары (пользователи);
  • прямоугольные флаги (страны);
  • иконки брендов;
  • пиктограммы категорий.

Единый CSS-подход:

.ss-option img {
  width: 22px;
  height: 22px;
  object-fit: cover;
  border-radius: 4px;
}

Безопасность при использовании HTML в опциях

Использование изображений через HTML-строки в опциях требует контроля входных данных. При генерации через API важно исключать внедрение произвольного HTML:

  • экранирование текстовых значений;
  • проверка URL изображений;
  • ограничение допустимых доменов;
  • запрет inline-скриптов в разметке.

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