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

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

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».

jquery select

Как выглядит select в разных браузерах

Chrome

select chrome

Mozilla

select option mozilla

Opera

Edge

Yandex

Стилизация select css

Даже после выхода 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;
}

После использования этого кода выйдет следующее:

Используем для оформления select jQuery

Чтобы стилизовать согласно капризам дизайна, проще всего скрыть нужный селект, заменив его списком или набором 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, с которым с помощью стилей можно придать любой вид:

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

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