Создание кастомных выпадающих списков

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

Тренажер CSS

В этой серии заданий вы попрактикуетесь в стилизации стандартных элементов `<select>` и создании полностью кастомных выпадающих списков с использованием HTML и CSS. Задания охватывают скрытие стандартных элементов управления браузера, добавление собственных индикаторов (стрелок) с помощью псевдоэлементов и фоновых изображений, а также создание и стилизацию выпадающих списков с нуля для полного контроля над их внешним видом и поведением. Упражнения построены от простого к сложному, позволяя постепенно освоить различные техники кастомизации.

Список тем

Скрытие стандартной стрелки select

Начнем с основ. Часто при стилизации выпадающих списков первым шагом является скрытие стандартной стрелки, которую добавляет браузер. Ваша задача — изменить стиль элемента `<select>`, чтобы убрать его стандартное оформление.

CSS
.custom-select {
  /* Убираем стандартное оформление браузера */
  input1: none;
  -webkit-appearance: none;
  -moz-appearance: none;

  /* Добавляем базовые стили для наглядности */
  display: block;
  width: 100%;
  padding: 8px 12px;
  border: 1px solid #ccc;
  background-color: #fff;
  font-size: 16px;
  line-height: 1.5;
  color: #333;
  cursor: pointer;
}
HTML
<div class="container">
  <label for="lang-select">Выберите язык:</label>
  <select class="custom-select" id="lang-select">
    <option value="ru">Русский</option>
    <option value="en">English</option>
    <option value="de">Deutsch</option>
  </select>
</div>
Для скрытия стандартного оформления элементов форм, включая стрелку у `<select>`, используется свойство `appearance` (или его аналоги с префиксами `-webkit-` и `-moz-` для лучшей кроссбраузерности). Установите для него значение `none`.
Заполнить ответами все поля
Результат
Сообщения
Выполнить
Отметить решенным
Показать подсказку

Добавление кастомной стрелки (псевдоэлемент)

Теперь, когда стандартная стрелка скрыта, нужно добавить свою. Мы обернем `<select>` в контейнер `div` и добавим стрелку с помощью псевдоэлемента `::after` для этого контейнера. Расположите стрелку справа внутри контейнера.

CSS
.select-wrapper {
  input1: relative; /* Контейнер для позиционирования стрелки */
  width: 200px;
}

.custom-select-arrowed {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  display: block;
  width: 100%;
  padding: 8px 30px 8px 12px; /* Оставляем место справа для стрелки */
  border: 1px solid #ccc;
  background-color: #fff;
  font-size: 16px;
  line-height: 1.5;
  color: #333;
  cursor: pointer;
}

.select-wrapperinput2 {
  content: '▼';
  input3: absolute;
  top: 50%;
  right: 10px;
  transform: translateY(-50%);
  color: #555;
  pointer-events: none; /* Чтобы клики проходили на select */
}
HTML
<div class="select-wrapper">
  <select class="custom-select-arrowed" id="os-select">
    <option value="win">Windows</option>
    <option value="mac">MacOS</option>
    <option value="lin">Linux</option>
  </select>
</div>
Задайте контейнеру `position: relative`. Для псевдоэлемента `::after` используйте `content` для символа стрелки (например, '▼') или создайте ее с помощью границ. Задайте `position: absolute`, расположите справа (`right`) и по центру вертикали (`top`, `transform: translateY`). Не забудьте `pointer-events: none`, чтобы клики проходили на сам select.
Заполнить ответами все поля
Результат
Сообщения
Выполнить
Отметить решенным
Показать подсказку

Структура для полностью кастомного списка

Стилизация `<option>` крайне ограничена. Создадим полностью кастомный выпадающий список с помощью HTML-элементов. У нас будет кнопка (или `div`, имитирующий поле выбора) и скрытый блок с опциями. Ваша задача — скрыть блок с опциями по умолчанию.

CSS
.custom-dropdown {
  position: relative;
  width: 220px;
  font-family: sans-serif;
}

.dropdown-selected {
  padding: 10px 15px;
  border: 1px solid #ccc;
  background-color: #fff;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.dropdown-arrow {
  /* Можно добавить стилизованную стрелку позже */
  border: solid black;
  border-width: 0 2px 2px 0;
  display: inline-block;
  padding: 3px;
  transform: rotate(45deg);
  -webkit-transform: rotate(45deg);
}

.dropdown-options {
  input1: none; /* Скрываем опции по умолчанию */
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  background-color: #fff;
  border: 1px solid #ccc;
  border-top: none;
  max-height: 150px;
  overflow-y: auto;
  z-index: 10;
  list-style: none;
  margin: 0;
  padding: 0;
}

.dropdown-options li {
  padding: 10px 15px;
  cursor: pointer;
}

.dropdown-options li:hover {
  background-color: #f0f0f0;
}
HTML
<div class="custom-dropdown">
  <div class="dropdown-selected" tabindex="0"> 
    <span>Выберите фрукт</span>
    <span class="dropdown-arrow"></span>
  </div>
  <ul class="dropdown-options">
    <li>Яблоко</li>
    <li>Банан</li>
    <li>Апельсин</li>
    <li>Манго</li>
  </ul>
</div>
Используйте свойство `display` со значением `none`, чтобы полностью скрыть блок с опциями из потока документа и сделать его невидимым.
Заполнить ответами все поля
Результат
Сообщения
Выполнить
Отметить решенным
Показать подсказку

Отображение кастомного списка при фокусе

Теперь нужно сделать так, чтобы список опций появлялся, когда пользователь кликает или переходит табом на элемент выбора. Мы будем использовать псевдокласс `:focus-within` на родительском контейнере `.custom-dropdown`.

CSS
.custom-dropdown {
  position: relative;
  width: 220px;
  font-family: sans-serif;
}

.dropdown-selected {
  padding: 10px 15px;
  border: 1px solid #ccc;
  background-color: #fff;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  outline: none; /* Убираем стандартный контур фокуса, если нужно */
}

.dropdown-selected:focus {
  border-color: #888;
}

.dropdown-arrow {
  border: solid black;
  border-width: 0 2px 2px 0;
  display: inline-block;
  padding: 3px;
  transform: rotate(45deg);
}

.dropdown-options {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  background-color: #fff;
  border: 1px solid #ccc;
  border-top: none;
  max-height: 150px;
  overflow-y: auto;
  z-index: 10;
  list-style: none;
  margin: 0;
  padding: 0;
}

.dropdown-options li {
  padding: 10px 15px;
  cursor: pointer;
}

.dropdown-options li:hover {
  background-color: #f0f0f0;
}

/* Показываем опции при фокусе внутри контейнера */
input1 input2 {
  input3: block;
}
HTML
<div class="custom-dropdown">
  <div class="dropdown-selected" tabindex="0"> 
    <span>Выберите фрукт</span>
    <span class="dropdown-arrow"></span>
  </div>
  <ul class="dropdown-options">
    <li>Яблоко</li>
    <li>Банан</li>
    <li>Апельсин</li>
    <li>Манго</li>
  </ul>
</div>
Добавьте CSS-правило, которое выбирает `.custom-dropdown:focus-within`. Внутри этого правила выберите дочерний элемент `.dropdown-options` и измените его свойство `display` на `block` (или другое подходящее значение, например `flex`, если используется flexbox), чтобы показать список.
Заполнить ответами все поля
Результат
Сообщения
Выполнить
Отметить решенным
Показать подсказку

Плавное появление и поворот стрелки

Сделаем появление списка более плавным и добавим поворот стрелки при открытии. Используйте CSS-переходы (`transition`) для свойств `opacity` и `transform` у списка опций, а также для `transform` у стрелки.

CSS
.custom-dropdown {
  position: relative;
  width: 220px;
  font-family: sans-serif;
}

.dropdown-selected {
  padding: 10px 15px;
  border: 1px solid #ccc;
  background-color: #fff;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  outline: none;
}

.dropdown-selected:focus {
  border-color: #888;
}

.dropdown-arrow {
  border: solid black;
  border-width: 0 2px 2px 0;
  display: inline-block;
  padding: 3px;
  transform: rotate(45deg);
  input1: transform 0.3s ease; /* Плавный поворот стрелки */
}

.dropdown-options {
  /* display: none; */ /* Заменяем display на opacity/visibility */
  input2: 0; /* Начальная прозрачность */
  input3: hidden; /* Скрываем из доступности */
  transform: translateY(-10px); /* Небольшой сдвиг вверх */
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  background-color: #fff;
  border: 1px solid #ccc;
  border-top: none;
  max-height: 150px;
  overflow-y: auto;
  z-index: 10;
  list-style: none;
  margin: 0;
  padding: 0;
  transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s; /* Плавное появление */
}

.dropdown-options li {
  padding: 10px 15px;
  cursor: pointer;
}

.dropdown-options li:hover {
  background-color: #f0f0f0;
}

.custom-dropdown:focus-within .dropdown-options {
  /* display: block; */ /* Заменяем display на opacity/visibility */
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

/* Поворачиваем стрелку при открытии */
.custom-dropdown:focus-within .dropdown-arrow {
  input4: rotate(-135deg);
}
HTML
<div class="custom-dropdown">
  <div class="dropdown-selected" tabindex="0"> 
    <span>Выберите фрукт</span>
    <span class="dropdown-arrow"></span>
  </div>
  <ul class="dropdown-options">
    <li>Яблоко</li>
    <li>Банан</li>
    <li>Апельсин</li>
    <li>Манго</li>
  </ul>
</div>
Для списка `.dropdown-options` задайте начальное состояние `opacity: 0;` и `visibility: hidden;` (вместо `display: none;`). При `:focus-within` меняйте `opacity` на `1` и `visibility` на `visible`. Добавьте свойство `transition` для `opacity` и `transform` (можно добавить небольшой сдвиг через `translateY`). Для стрелки `.dropdown-arrow` добавьте `transition` для `transform`. В состоянии `:focus-within` измените `transform` стрелки, чтобы она повернулась (например, `rotate(-135deg)`).
Заполнить ответами все поля
Результат
Сообщения
Выполнить
Отметить решенным
Показать подсказку
НайтиКурс.Ру