Так как select не стилизуется напрямую, работаем над его клоном ".select-wrapper"
Будем называть его псевдосписок.
В примере помощью JavaScript синхронизируется взаимный выбор option
Рядом с обычным select указываем его будущую обертку:
<select class="custom-select">
<option selected>Выберите тип</option>
<option>Landing Page</option>
<option>Корпоративный сайт</option>
<option>Онлайн магазин</option>
</select>
<div class="select-wrapper"></div>
Код JavaScript:
"use strict";
var option = document.querySelectorAll('.custom-select option'),
selectWrapper = document.querySelector('.select-wrapper'); // Создание контейнера для псевдосписка
var selectResult = document.createElement('div');
selectResult.classList.add('select-result');
selectWrapper.appendChild(selectResult); // Создание первого элемента псевдосписка. Здесь будет показан выбранный элемент
var firstDiv = document.createElement('div');
firstDiv.style.display = 'none';
selectResult.appendChild(firstDiv); // Создание интуитивной иконки для псевдосписка
var iconSelect = document.createElement('span');
iconSelect.innerHTML = ">";
selectResult.appendChild(iconSelect);
document.querySelectorAll('.select-result div').forEach(function (item) {
item.addEventListener('onmouseover', function (e) {
console.log(e.target);
e.target.style.backgroundColor = 'red';
});
}); // Перебор <option> и копирование их в <div> и вставка в контейнер для псевдосписка
option.forEach(function (item) {
var div = document.createElement('div');
div.innerHTML = item.innerHTML;
selectResult.appendChild(div);
}); // Открытие\Закрытие псевдосписка
document.querySelector('.select-wrapper').addEventListener('click', function (e) {
selectResult.classList.toggle('select-active');
}); // Клик на каждом элементе псевдосписка
document.querySelectorAll('.select-result div').forEach(function (item) {
item.addEventListener('click', function (e) {
// Если псевдосписок раскрыт, то вставляем выбранный элемент на первую позицию и закрываем псевдосписок
if (selectResult.classList.contains('select-active')) {
document.querySelector('.select-result div').innerHTML = e.target.innerHTML;
firstDiv.style.display = 'block'; // <option selected> если совпадает содержимое с выбранным элементом псевдосписка
option.forEach(function (item) {
item.innerHTML === e.target.innerHTML ? item.selected = true : false;
});
}
});
}); // Fix Убирает дублирование выбранного элемента в списке псевдосписка
document.querySelectorAll('.select-result div').forEach(function (item) {
item.addEventListener('click', function (e) {
if (selectResult.classList.contains('select-active')) {
document.querySelectorAll('.select-result div').forEach(function (el) {
el.classList.remove('display-none');
});
e.target.classList.add('display-none');
}
});
}); // Fix Убирает дублирование только первого элемента псевдосписка, который является заглушкой по умолчанию
/* document.querySelectorAll('.select-result div').forEach((item) => {
item.addEventListener('click', (e) => {
if (selectResult.classList.contains('select-active') && e.target.innerHTML === document.querySelector('.custom-select option').innerHTML) {
e.target.classList.add('display-none');
} else if (selectResult.classList.contains('select-active') && e.target.innerHTML !== document.querySelector('.custom-select option').innerHTML) {
document.querySelectorAll('.select-result div')[1].classList.remove('display-none')
}
})
});*/
// Fix Закрывает псевдосписок при клике вне его области
document.addEventListener('click', function (e) {
// ВАЖНО!
// "ИЛИ" срабатывает после первого совпадения и дальше не проверяет
// Поэтому, если убрать сравнение с document, то проверяется второе условие и при клике за пределы <html> появится ошибка typeError, так как у document нет метода .contains
if (e.target.parentNode === document || !e.target.parentNode.classList.contains('select-active')) {
selectResult.classList.remove('select-active');
}
}); // BONUS
// При клике на <option> выбирается соответствующий элемент в псевдосписке
document.querySelector('.custom-select').addEventListener('change', function (e) {
document.querySelectorAll('.select-result div').forEach(function (item) {
item.classList.remove('display-none');
});
document.querySelectorAll('.select-result div').forEach(function (item) {
if (item.innerHTML === e.target.options[e.target.selectedIndex].innerHTML) {
item.classList.add('display-none');
document.querySelector('.select-result div').innerHTML = item.innerHTML;
firstDiv.style.display = 'block';
}
});
});