Мобильная версия

Поведение Slim Select на мобильных устройствах отличается от десктопного режима прежде всего ограничениями экрана, особенностями touch-интерфейса и поведением мобильных браузеров при работе с позиционированными элементами и виртуальной клавиатурой. Основная задача адаптации — сохранить функциональность кастомного select-компонента и одновременно избежать конфликтов с нативными механизмами iOS и Android.

Slim Select строится вокруг кастомного выпадающего списка, который заменяет стандартный <select> элемент. На мобильных устройствах подобный подход сталкивается с проблемами:

  • ограниченная область экрана;
  • нестабильное позиционирование position: fixed;
  • автоматическое масштабирование при фокусе на input;
  • конфликт виртуальной клавиатуры с поисковой строкой.

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

Кастомный режим (Slim Select UI):

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

Гибридный режим (fallback на нативный select):

  • на мобильных устройствах отключается кастомный UI;
  • используется стандартный <select>;
  • повышается стабильность поведения на слабых устройствах.

Реализация гибридного подхода обычно базируется на проверке ширины экрана или user-agent:

const isMobile = window.matchMedia("(max-width: 768px)").matches;

if (isMobile) {
  // оставить нативный select
} else {
  new SlimSelect({
    select: '#select'
  });
}

Touch-интерфейс и обработка событий

Мобильный UX требует учёта особенностей touch-событий. В Slim Select взаимодействие с элементами списка опирается на click, однако на мобильных устройствах важно учитывать:

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

Оптимизация заключается в:

  • увеличении padding элементов списка;
  • минимальной высоте интерактивных элементов (не менее 44px);
  • отказе от сложных hover-эффектов.
.ss-option {
  min-height: 44px;
  padding: 12px 16px;
}

Особенности viewport и iOS Safari

Одной из ключевых проблем мобильной версии является поведение 100vh на iOS. Виртуальная строка браузера изменяет высоту viewport при прокрутке, что приводит к скачкам выпадающего списка.

Типовые проблемы:

  • dropdown выходит за пределы экрана;
  • фиксированные блоки “прыгают”;
  • неправильно рассчитывается высота контейнера.

Решение заключается в использовании динамических единиц:

.ss-content {
  max-height: calc(100dvh - 100px);
}

или через Jav * aScript:

function setVh() {
  document.documentElement.style.setProperty('--vh', `${window.innerHeight * 0.01}px`);
}

window.addEventListener('resize', setVh);
setVh();

Позиционирование выпадающего списка

На мобильных устройствах dropdown часто требует перехода в режим “overlay”, когда список перекрывает весь экран или большую его часть.

Основные подходы:

  • абсолютное позиционирование внутри контейнера;
  • фиксированное позиционирование относительно viewport;
  • перенос dropdown в body (portal-подход).

Проблема position: fixed на iOS заключается в его нестабильности при прокрутке. Поэтому часто используется стратегия динамического пересчёта координат:

function updatePosition(trigger, dropdown) {
  const rect = trigger.getBoundingClientRect();

  dropdown.style.top = `${rect.bottom}px`;
  dropdown.style.left = `${rect.left}px`;
  dropdown.style.width = `${rect.width}px`;
}

Блокировка прокрутки страницы

При открытии Slim Select dropdown важно предотвращать прокрутку основного документа, чтобы избежать “разъезда” интерфейса.

Стандартный подход:

document.body.style.overflow = 'hidden';

Однако на iOS этого недостаточно. Дополнительно требуется фиксация scroll позиции:

let scrollY = 0;

function lockScroll() {
  scrollY = window.scrollY;
  document.body.style.position = 'fixed';
  document.body.style.top = `-${scrollY}px`;
  document.body.style.width = '100%';
}

function unlockScroll() {
  document.body.style.position = '';
  document.body.style.top = '';
  window.scrollTo(0, scrollY);
}

Производительность на мобильных устройствах

Мобильные браузеры чувствительны к:

  • частым reflow при изменении DOM;
  • анимациям с layout-пересчётом;
  • сложным теням и blur-эффектам.

Оптимизация Slim Select-структуры включает:

  • минимизацию DOM-узлов внутри dropdown;
  • использование transform вместо top/left для анимаций;
  • отключение тяжёлых CSS эффектов на слабых устройствах;
  • кэширование результатов поиска.
.ss-content {
  will-change: transform;
  transform: translateZ(0);
}

Работа с виртуальной клавиатурой

При использовании встроенного поиска внутри Slim Select возникает конфликт с виртуальной клавиатурой:

  • клавиатура перекрывает dropdown;
  • изменяется высота viewport;
  • input теряет фокус при прокрутке.

Решения:

  1. Фиксация dropdown выше клавиатуры через пересчёт viewport.
  2. Перенос поиска в верхнюю часть экрана.
  3. Отключение поиска на мобильных устройствах.
const config = {
  search: window.innerWidth > 768
};

Адаптивные медиа-правила

CSS-адаптация играет ключевую роль в мобильной версии Slim Select. Основные точки контроля:

@media (max-width: 768px) {
  .ss-content {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border-radius: 0;
  }

  .ss-list {
    max-height: calc(100dvh - 60px);
  }
}

Такой подход превращает dropdown в полноэкранный слой, что улучшает UX на маленьких дисплеях.

Паттерн инициализации и переинициализации

Адаптивные интерфейсы часто требуют пересоздания компонента при изменении размера экрана.

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

let instance;

function initSelect() {
  if (instance) instance.destroy();

  const isMobile = window.innerWidth <= 768;

  if (!isMobile) {
    instance = new SlimSelect({
      select: '#select'
    });
  }
}

window.addEventListener('resize', initSelect);
initSelect();

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

Accessibility на мобильных устройствах

Мобильная версия требует строгого соблюдения accessibility-поведения:

  • корректная работа focus trap внутри dropdown;
  • управление через экранные дикторы;
  • поддержка клавиатурной навигации (Bluetooth keyboards);
  • использование ARIA-атрибутов для состояния раскрытия.

Ключевые состояния:

  • aria-expanded;
  • aria-selected;
  • role="listbox" и role="option".

Фокус должен оставаться внутри активного компонента при открытом списке, иначе происходит потеря контекста управления.

Поведение при смене ориентации экрана

При переходе между portrait и landscape режимами происходит изменение viewport, что влияет на:

  • высоту dropdown;
  • позиционирование fixed-элементов;
  • видимость поискового input.

Рекомендуемый механизм — пересчёт layout при событии orientationchange:

window.addEventListener('orientationchange', () => {
  setTimeout(() => {
    // пересчёт позиции dropdown
  }, 200);
});

Ограничения мобильных браузеров

Мобильные браузеры накладывают ряд ограничений на кастомные select-компоненты:

  • ограничение z-index stacking contexts;
  • нестабильное поведение overflow: hidden;
  • различия между Safari и Chrome на Android;
  • ограниченная поддержка сложных анимаций.

Из-за этого Slim Select в мобильной версии часто требует упрощённого визуального слоя и отказа от избыточной интерактивности в пользу стабильности взаимодействия.