Select – один із найскладніших для стилізації елементів HTML-розмітки. Найпоширеніший спосіб стилізації поля вибору – використовувати для select jQuery. За допомогою цієї бібліотеки легко маніпулювати елементами DOM.
З 1997 року, коли він був вперше представлений у HTML 3.2, тег дає користувачам можливість вибрати один або декілька варіантів зі списку.
У цій статті ми розглянемо декілька способів стилізації SELECT:
SELECT часто використовується:
Для фільтрації товарів: за ціною, популярністю, датою тощо.
У формах: для вибору країни, міста, категорії тощо. Стилізація складна, тому що ці елементи не є стандартними HTML-елементами.
Вони відображаються як частина інтерфейсу користувача браузера або операційної системи.
Проблеми зі зміною стилів для списку пов’язані з тим, що елементи не є стандартними HTML-елементами, які відображаються на веб-сторінці. Натомість вони є частиною інтерфейсу користувача операційної системи або браузера.
Вже кілька років йде робота над створенням нового тега html з опціями – selectmenu. Цей тег вже доступний у браузері Chrome Canary, його також можна протестувати і в самому Chrome перейшовши на сторінку about:flags і увімкнувши опцію “Experimental Web Platform features”.
Chrome
Mozilla
Opera
Edge
Yandex
Навіть після виходу CSS3 можливості стилізації не сильно змінилися. Без використання скриптів кастомізувати можна візуально змінити лише основою.
<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;
}
Результат:
Щоб стилізувати SELECT відповідно до капризів дизайну, найпростіше його приховати, замінивши списком або набором div-ів, які будуть взаємодіяти між собою.
Якщо ви працюєте з CMS і вам потрібно попрацювати з кодом, який виводиться через функції самого движка, то буде досить складно змінити HTML-вивід цього коду без хука самих функцій.
У такому випадку найкраще використовувати jQuery для select.
Розглянемо наступний код, де в якості класу використовується та ж сама назва 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 чистий JavaScript.
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';
}
});
});