Стилізація select тільки на css, і з використанням js

Опублікував(а): Александр
Оновлено: 10.03.2024

Select – один із найскладніших для стилізації елементів HTML-розмітки. Найпоширеніший спосіб стилізації поля вибору – використовувати для select jQuery. За допомогою цієї бібліотеки легко маніпулювати елементами DOM.

З 1997 року, коли він був вперше представлений у HTML 3.2, тег дає користувачам можливість вибрати один або декілька варіантів зі списку.

У цій статті ми розглянемо декілька способів стилізації SELECT:

SELECT часто використовується:

Для фільтрації товарів: за ціною, популярністю, датою тощо.
У формах: для вибору країни, міста, категорії тощо. Стилізація складна, тому що ці елементи не є стандартними HTML-елементами.

Вони відображаються як частина інтерфейсу користувача браузера або операційної системи.

Проблеми зі зміною стилів для списку пов’язані з тим, що елементи не є стандартними HTML-елементами, які відображаються на веб-сторінці. Натомість вони є частиною інтерфейсу користувача операційної системи або браузера.

Вже кілька років йде робота над створенням нового тега html з опціями – selectmenu. Цей тег вже доступний у браузері Chrome Canary, його також можна протестувати і в самому Chrome перейшовши на сторінку about:flags і увімкнувши опцію “Experimental Web Platform features”.

jquery select

Як виглядає SELECT у різних браузерах

Chrome

select chrome

Mozilla

select option mozilla

Opera

css select

Edge

js select edge

Yandex

css select yandex

Стилизация SELECT за допомогою CSS

Навіть після виходу 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 за допомогою jQuery

Щоб стилізувати 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, з яким за допомогою стилів можна надати будь-якого вигляду:

Оформлення select через JS

Те ж саме можна зробити і без бібліотеки 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';
        }
    });
});