Стилизация select

Стилизация select на чистом CSS без использования сторонних библиотек или JavaScript кода. А также бонус: рассмотрим как стилизовать select option при помощи JavaScript и jQuery.

  1. Стилизация slect при помощи appearance.
  2. Стилизация select option.
  3. Создание выпадающего списка, используя input.
  4. Проверка, открыт ли select.

Стилизация select

Структура будет стандартной:

<select size="1">
    <option>Слон</option>
    <option>Бегемот</option>
    <option>Жираф</option>
</select>

Чтобы в select отображаемая строка была одна используем атрибут size со значением 1.

Стилизация для нашего select.

-webkit-appearance: none;
-moz-appearance: none;
-ms-appearance: none;
appearance: none;
background: url("path/img.png") no-repeat right center;
outline: 0;

Получим ↓

В примере выше мы прописали четыре строчки ccs свойства appearance с вендорными префиксами, чтобы свойство работало одинаково во всех браузерах. Что это за свойство читайте ниже.

Вся сложность заключалась лишь в замене стандартной стрелки в прямоугольнике, вместо которой мы реализовали background. Таким образом можно вставить любую картинку. Необходимо лишь подогнать размер при помощи свойства background-size

Appearance CSS

Реализовать нашу задачу помогло css3 свойство appearance.

Данное свойство позволяет изменить вид элемента на: button, checkbox, radio, field, icon и многое другое. В нашем случае мы вообще скрыли элемент, используя none и добавили картинку с помощью background.

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

Для того чтобы стилизовать select option нам потребуется JavaScript. Начнём с HTML и CSS.

<select class="select" name="language">
    <option disabled>Выбрать</option>
    <option value="HTML">HTML</option>
    <option value="JavaScript">JavaScript</option>
    <option value="PHP">PHP</option>
</select>
.select {
    display: block;
    max-width: 215px;
    width: 100%;
    position: relative;
}
.new-select {
    position: relative;
    border: 1px solid #ced4da;
    padding: 10px 15px;
    cursor: pointer;
    user-select: none;
}
.new-select__list {
    position: absolute;
    top: 45px;
    left: 0;
    border: 1px solid #ced4da;
    cursor: pointer;
    width: 100%;
    z-index: 2;
    background: #fff;
    user-select: none;
}
.new-select__list.on {
    display: block;
}
.new-select__item span {
    display: block;
    padding: 10px 15px;
}
.new-select__item span:hover {
    color: #12b223;
}
.new-select:after {
    content: "";
    display: block;
    width: 25px;
    height: 25px;
    position: absolute;
    right: 9px;
    top: 9px;
    background: url("path-to-image") no-repeat right center / cover;
    opacity: 0.6;
    transition: all .27s ease-in-out;
    transform: rotate(0deg);
}
.new-select.on:after {
    transform: rotate(180deg);
}

Перед JavaScript-кодом должен быть подключен jQuery.

$(".select").each(function () {
    const _this = $(this),
        selectOption = _this.find("option"),
        selectOptionLength = selectOption.length,
        selectedOption = selectOption.filter(":selected"),
        duration = 450; // длительность анимации

    _this.hide();
    _this.wrap("<div class='select'></div>");
    $("<div>", {
        class: "new-select",
        text: _this.children("option:disabled").text()
    }).insertAfter(_this);

    const selectHead = _this.next(".new-select");
    $("<div>", {
        class: "new-select__list"
    }).insertAfter(selectHead);

    const selectList = selectHead.next(".new-select__list");
    for (let i = 1; i < selectOptionLength; i++) {
        $("<div>", {
            class: "new-select__item",
            html: $("<span>", {
                text: selectOption.eq(i).text()
            })
        })
            .attr("data-value", selectOption.eq(i).val())
            .appendTo(selectList);
    }

    const selectItem = selectList.find(".new-select__item");
    selectList.slideUp(0);
    selectHead.on("click", function () {
        if (!$(this).hasClass("on")) {
            $(this).addClass("on");
            selectList.slideDown(duration);

            selectItem.on("click", function () {
                let chooseItem = $(this).data("value");

                $("select").val(chooseItem).attr("selected", "selected");
                selectHead.text($(this).find("span").text());

                selectList.slideUp(duration);
                selectHead.removeClass("on");
            });

        } else {
            $(this).removeClass("on");
            selectList.slideUp(duration);
        }
    });
});

Input select

Более простой вариант при помощи input. Данный вариант мне нравится больше.

<div class="select">
    <input class="select__input" type="hidden" name="">
    <div class="select__head">Выберите</div>
    <ul class="select__list" style="display: none;">
        <li class="select__item">Стилизация select CSS</li>
        <li class="select__item">Стилизация select JavaScript</li>
        <li class="select__item">Стилизация select, используя input</li>
    </ul>
</div>

Стили.

.select {
    position: relative;
    display: block;
    min-width: 220px;
    width: 100%;
    max-width: 400px;
    margin-bottom: 20px;
}
.select__head {
    width: 100%;
    max-width: 100%;
    box-shadow: 0 0 4px rgba(0, 0, 0, 0.2);
    border-radius: 10px;
    padding: 14px 15px;
    font-size: 14px;
    line-height: 18px;
    color: rgba(66, 67, 72, 0.8);
    cursor: pointer;
}
.select__head::after {
    width: 10px;
    height: 6px;
    background: #FFF url('data:image/svg+xml,%3Csvg width="10" height="6" viewBox="0 0 10 6" fill="none" xmlns="http: //www.w3.org/2000/svg"%3E%3Cpath fill-rule="evenodd" clip-rule="evenodd" d="M4.50495 5.78413L0.205241 1.25827C-0.0684138 0.970375 -0.0684138 0.503596 0.205241 0.215836C0.478652 -0.0719461 0.922098 -0.071946 1.19549 0.215837L5.00007 4.22052L8.80452 0.215953C9.07805 -0.0718292 9.52145 -0.0718292 9.79486 0.215953C10.0684 0.503736 10.0684 0.970492 9.79486 1.25839L5.49508 5.78425C5.35831 5.92814 5.17925 6 5.00009 6C4.82085 6 4.64165 5.928 4.50495 5.78413Z" fill="%23ED266A"/%3E%3C/svg%3E%0A') no-repeat center / cover;
    position: absolute;
    right: 20px;
    bottom: 50%;
    transform: translateY(50%);
    content: "";
    display: block;
    transition: .2s ease-in;
}
.select__head.open::after {
    transform: translateY(50%) rotate(180deg);
}
.select__list {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: #fff;
    box-shadow: 0 0 4px rgba(0, 0, 0, 0.2);
    border-radius: 10px;
    margin-top: 5px;
    max-height: 205px;
    overflow-x: hidden;
    overflow-y: auto;
    z-index: 100;
    margin: 0;
    padding: 0;
    font-size: 14px;
    color: #424348;
    scrollbar-color: dark;
    scrollbar-width: thin;
    overscroll-behavior: contain;
}
.select__list::-webkit-scrollbar {
    width: 7px;
    background-color: #F8F9FA;
    padding: 5px;
}
.select__list::-webkit-scrollbar-thumb {
    border-radius: 10px;
    background-color: #D9D9D9;
}
.select__list .select__item {
    position: relative;
    border-top: 1px solid rgba(224, 229, 231, 0.5);
    padding: 10px 15px;
    cursor: pointer;
    list-style-type: none;
}
.select__list .select__item:hover {
    background-color: rgba(224, 229, 231, 0.5);
}

jQuery код.

jQuery(($) => {
    $(".select").on("click", ".select__head", function () {
        if ($(this).hasClass("open")) {
            $(this).removeClass("open");
            $(this).next().fadeOut();
        } else {
            $(".select__head").removeClass("open");
            $(".select__list").fadeOut();
            $(this).addClass("open");
            $(this).next().fadeIn();
        }
    });

    $(".select").on("click", ".select__item", function () {
        $(".select__head").removeClass("open");
        $(this).parent().fadeOut();
        $(this).parent().prev().text($(this).text());
        $(this).parent().prev().prev().val($(this).text());
    });

    $(document).click(function (e) {
        if (!$(e.target).closest(".select").length) {
            $(".select__head").removeClass("open");
            $(".select__list").fadeOut();
        }
    });
});

Проверка открыт ли select

Будем изменять положение стрелки в зависимости от того открыт или закрыт select.

const select = document.querySelector("select");

select.addEventListener("blur", () => selectEvent());
select.addEventListener("click", () => selectEvent());

selectEvent = (event) => {
    if (event.type == "click") {
        if (select.classList.contains("change")) {
            select.classList.remove("change");
        } else {
            select.classList.add("change");
        }
    }
    if (event.type == "blur") {
        select.classList.remove("change");
    }
};

Если вам понравилась статья про стилизацию select, рекомендую прочитать про Стилизацию чекбоксов.