Select стоит на первом месте по сложности стилизации из элементов разметки HTML. Тег <select>
был впервые введён в HTML 3.2 в 1997 году. Он был разработан для обеспечения пользователей возможностью выбора одного или нескольких вариантов из списка. Выполним стилизацию этого элемента несколькими способами: с помощью обычных стилей, используя библиотеку jQuery, и используя только js.
Тег select чаще всего используется на сайтах, где нужно применять фильтры к выводу товара (релятивность, цена, популярность, дата). Так же в формах где требуется собирать информацию от пользователей, <select> может использоваться для выбора из предопределенных вариантов, таких как страны, города, категории и т. д.
Проблемы с изменением стилей для выпадающего списка <option> связаны с тем, что элементы <option> не являются стандартными HTML-элементами, которые отображаются на веб-странице. Вместо этого они являются частью интерфейса пользователя операционной системы или браузера.
Уже несколько лет идет работа над созданием нового тега html с опциями – selectmenu. Этот тег уже доступен в браузере Chrome Canary, его также можно протестировать и в самом Chrome перейдя на страницу about:flags и включив опцию «Experimental Web Platform features».
Chrome
Mozilla
Opera
Edge
Yandex
Даже после выхода CSS3 возможности стилизации <select>
не сильно изменились. Без использования скриптов кастомизировать можно визуально изменить лишь основой тег:
<select class="select-css">
<option disabled>Select option</option>
<option value="Popularity">Popularity</option>
<option value="Lowest price">Lowest price</option>
<option value="Highest price">Highest price</option>
<option value="Brand">Brand</option>
<option value="Name A-Z">Name A-Z</option>
<option value="Name Z-A">Name Z-A</option>
</select>
select css:
.select-css {
display: block;
font-size: 16px;
font-weight: 700;
color: #444;
padding: 5px 25px 5px 15px;
max-width: 250px;
box-sizing: border-box;
margin: 0;
border: 1px solid #aaa;
box-shadow: 0 1px 0 1px rgba(0,0,0,.04);
border-radius: 5px;
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
background-color: #fff;
background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23007CB2%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E'), linear-gradient(to bottom, #ffffff 0%,#e5e5e5 100%);
background-repeat: no-repeat, repeat;
background-position: right 10px top 50%;
background-size: 8px auto, 100%;
margin-bottom: 15px;
}
.select-css::-ms-expand { display: none; }
.select-css:hover { border-color: #888; }
.select-css:focus {
border-color: #aaa;
color: #222;
outline: none;
}
.select-css option{
color:#333;
background: #fff;
font-weight:normal;
}
.select-css option:hover{
background: lightgray;
}
После использования этого кода выйдет следующее:
Чтобы стилизовать согласно капризам дизайна, проще всего скрыть нужный селект, заменив его списком или набором div-ов, которые будут взаимодействовать между собой.
Если вы работаете с CMS и требуется поработать над кодом который выводится через функции самого движка, то довольно трудно будет изменить html вывод этого кода, без хука самих функций.
В таком случае, лучше всего использовать для select jQuery. Возьмем следующий код где в качестве класса используется тоже название select:
<select class="select">
<option value="Popularity">Popularity</option>
<option value="Lowest price">Lowest price</option>
<option value="Highest price">Highest price</option>
<option value="Brand">Brand</option>
<option value="Name A-Z">Name A-Z</option>
<option value="Name Z-A">Name Z-A</option>
</select>
В следующем коде обернем текущий блок кода родительским div-ом, а после оригинального блока выведем html, в котором будет представлен список альтернативных опций.
$('.select').each((index, element) => {
const $this = $(element).hide().wrap('<div class="select"></div>');
const $select = $('<div>', {
class: 'copy_select',
text: $this.children('option:eq(0)').text()
}).insertAfter($this);
const $option_list = $('<div>', {
class: 'option_list'
}).insertAfter($select);
$this.find('option').each((index, option) => {
if (index !== 0) {
$('<div>', {
class: 'option_item',
html: $('<span>').text($(option).text())
})
.attr('data-value', $(option).val())
.appendTo($option_list);
}
});
$option_list.hide();
$select.on('click', () => {
$select.toggleClass('on');
$option_list.slideToggle(100);
});
$option_list.on('click', '.option_item', function() {
const chooseItem = $(this).data('value');
$('select').val(chooseItem).prop('selected', true);
$select.text($(this).find('span').text());
$option_list.slideUp(100);
$select.removeClass('on');
});
});
Теперь можно оформлять вывод через стили.
.select {
display: block;
max-width: 215px;
width: 100%;
position: relative;
}
.copy_select {
position: relative;
border: 1px solid #ced4da;
padding: 10px 15px;
cursor: pointer;
user-select: none;
}
.option_list {
position: absolute;
top: 45px;
left: 0;
border: 1px solid #ced4da;
cursor: pointer;
width: 100%;
z-index: 2;
background: #fff;
user-select: none;
}
.option_list.on {
display: block;
}
.option_item span {
display: block;
padding: 10px 15px;
}
.option_item span:hover {
color: #12b223;
}
.copy_select:after {
content: '23F7';
display: block;
position: absolute;
right: 9px;
top: 9px;
height: 20px;
line-height: 20px;
opacity: 0.6;
transition: all .27s ease-in-out;
transform: rotate(0deg);
font-size: 18px;
}
В результате выйдет следующий блок select, с которым с помощью стилей можно придать любой вид:
Тоже самое можно проделать и без библиотеки jQuery, используем для select js:
document.querySelectorAll('.select').forEach(function(element) {
element.style.display = 'none';
var selectWrapper = document.createElement('div');
selectWrapper.classList.add('select');
element.parentNode.insertBefore(selectWrapper, element);
selectWrapper.appendChild(element);
var select = document.createElement('div');
select.classList.add('copy_select');
select.textContent = element.querySelector('option:disabled').textContent;
selectWrapper.appendChild(select);
var optionList = document.createElement('div');
optionList.classList.add('option_list');
selectWrapper.appendChild(optionList);
element.querySelectorAll('option').forEach(function(option, index) {
if (index !== 0) {
var optionItem = document.createElement('div');
optionItem.classList.add('option_item');
optionItem.innerHTML = '<span>' + option.textContent + '</span>';
optionItem.setAttribute('data-value', option.value);
optionList.appendChild(optionItem);
}
});
optionList.style.display = 'none';
select.addEventListener('click', function() {
var isOpen = select.classList.contains('on');
if (!isOpen) {
select.classList.add('on');
optionList.style.display = 'block';
optionList.querySelectorAll('.option_item').forEach(function(item) {
item.addEventListener('click', function() {
var chooseItem = this.getAttribute('data-value');
element.value = chooseItem;
select.textContent = this.querySelector('span').textContent;
optionList.style.display = 'none';
select.classList.remove('on');
});
});
} else {
select.classList.remove('on');
optionList.style.display = 'none';
}
});
});