Кастомный select с анимацией выпадающего списка
Стандартные элементы select имеют ограниченные возможности стилизации, особенно в разных браузерах. Мы создадим кастомный select, который можно полностью стилизовать под дизайн сайта, с плавной анимацией раскрытия списка и возможностью выбора вариантов.
HTML структура
Создадим обёртку для нашего кастомного select и добавим элементы для отображения выбранного значения и списка вариантов:
<div class="custom-select">
<div class="select-header">
<span class="selected-value">Выберите вариант</span>
<span class="arrow">▼</span>
</div>
<ul class="select-options">
<li data-value="1">Вариант 1</li>
<li data-value="2">Вариант 2</li>
<li data-value="3">Вариант 3</li>
<li data-value="4">Вариант 4</li>
</ul>
</div>
Базовые стили
Зададим основные стили для нашего select и скроем выпадающий список:
.custom-select {
position: relative;
width: 200px;
font-family: Arial, sans-serif;
}
.select-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 15px;
border: 1px solid #ddd;
border-radius: 4px;
cursor: pointer;
background-color: #fff;
transition: border-color 0.3s;
}
.select-header:hover {
border-color: #aaa;
}
.arrow {
transition: transform 0.3s;
}
.select-options {
position: absolute;
top: 100%;
left: 0;
right: 0;
max-height: 0;
overflow: hidden;
margin: 0;
padding: 0;
list-style: none;
background-color: #fff;
border: 1px solid transparent;
border-radius: 0 0 4px 4px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
transition: all 0.3s ease;
z-index: 100;
}
.select-options li {
padding: 10px 15px;
cursor: pointer;
transition: background-color 0.2s;
}
.select-options li:hover {
background-color: #f5f5f5;
}
Стили для открытого состояния
Добавим стили для открытого состояния select и анимацию стрелки:
.custom-select.active .select-options {
max-height: 300px;
border-color: #ddd;
border-top: none;
}
.custom-select.active .arrow {
transform: rotate(180deg);
}
.custom-select.active .select-header {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
JavaScript для функциональности
Добавим обработчики событий для открытия/закрытия select и выбора вариантов:
const customSelect = document.querySelector('.custom-select');
const selectHeader = customSelect.querySelector('.select-header');
const selectedValue = customSelect.querySelector('.selected-value');
const options = customSelect.querySelectorAll('.select-options li');
// Открытие/закрытие select
selectHeader.addEventListener('click', () => {
customSelect.classList.toggle('active');
});
// Выбор варианта
options.forEach(option => {
option.addEventListener('click', () => {
selectedValue.textContent = option.textContent;
customSelect.classList.remove('active');
// Здесь можно добавить обработку выбранного значения
console.log('Выбрано:', option.dataset.value);
});
});
// Закрытие при клике вне select
document.addEventListener('click', (e) => {
if (!customSelect.contains(e.target)) {
customSelect.classList.remove('active');
}
});
Итоговый код
Полный код кастомного select с анимацией:
<div class="custom-select">
<div class="select-header">
<span class="selected-value">Выберите вариант</span>
<span class="arrow">▼</span>
</div>
<ul class="select-options">
<li data-value="1">Вариант 1</li>
<li data-value="2">Вариант 2</li>
<li data-value="3">Вариант 3</li>
<li data-value="4">Вариант 4</li>
</ul>
</div>
.custom-select {
position: relative;
width: 200px;
font-family: Arial, sans-serif;
}
.select-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 15px;
border: 1px solid #ddd;
border-radius: 4px;
cursor: pointer;
background-color: #fff;
transition: border-color 0.3s;
}
.select-header:hover {
border-color: #aaa;
}
.arrow {
transition: transform 0.3s;
}
.select-options {
position: absolute;
top: 100%;
left: 0;
right: 0;
max-height: 0;
overflow: hidden;
margin: 0;
padding: 0;
list-style: none;
background-color: #fff;
border: 1px solid transparent;
border-radius: 0 0 4px 4px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
transition: all 0.3s ease;
z-index: 100;
}
.select-options li {
padding: 10px 15px;
cursor: pointer;
transition: background-color 0.2s;
}
.select-options li:hover {
background-color: #f5f5f5;
}
.custom-select.active .select-options {
max-height: 300px;
border-color: #ddd;
border-top: none;
}
.custom-select.active .arrow {
transform: rotate(180deg);
}
.custom-select.active .select-header {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
const customSelect = document.querySelector('.custom-select');
const selectHeader = customSelect.querySelector('.select-header');
const selectedValue = customSelect.querySelector('.selected-value');
const options = customSelect.querySelectorAll('.select-options li');
selectHeader.addEventListener('click', () => {
customSelect.classList.toggle('active');
});
options.forEach(option => {
option.addEventListener('click', () => {
selectedValue.textContent = option.textContent;
customSelect.classList.remove('active');
console.log('Выбрано:', option.dataset.value);
});
});
document.addEventListener('click', (e) => {
if (!customSelect.contains(e.target)) {
customSelect.classList.remove('active');
}
});
: