Здравствуйте, хабраюзеры и просто читающие. Сравнительно недавно задался вопросом, как применить стили к тегу select. Всем же хочется, чтобы стилизация формы соответствовала дизайну сайта, а пока что еще не все можно описать чистым CSS. В данной статье мы рассмотрим простенький пример написания своего select-списка, используя CSS и библиотеку языка JavaScript - jQuery. Думаю, особенно новичкам будет любопытен данный материал. Конечно, лучше было бы лучше написать на нативном JS, но всем известно, что строк кода было бы больше, и вряд ли он был бы понятнее.
Честно говоря, прежде чем взяться за создание очередного велосипеда, я пробовал найти подобное решение, но кроме эффектных div-оберток для тега select ничего не нашёл. И я подумал, что будет неплохо написать что-то простенькое и нужное. Ну, что ж, начнём!
В нашем кружке лепки из пластилина участвуют три файла:
- selectbox.html
- selectbox.css
- selectbox.js
selectbox.html
Месяц
- Январь
- Февраль
- Март
- Апрель
- Май
- Июнь
- Июль
- Август
- Сентябрь
- Октябрь
- Ноябрь
- Декабрь
Как видно из исходного html-кода, наш список будет предлагать нам выбрать месяц. Теперь рассмотрим файл selectbox.css :
selectbox.css
div#selectBox {
width: 250px;
position: relative;
height: 50px;
border-radius: 3px;
border: solid 1px lightgrey;
background-color: #fff;
color: #333;
cursor: pointer;
overflow: hidden;
transition: .3s;
}
div#selectBox p.valueTag {
padding: 15px;
cursor: pointer;
transition: .2s;
height: 40px;
}
div#selectBox > img.arrow {
position: absolute;
right: 0;
width: 50px;
padding: 15px;
}
/*
для пользователей Safari, Chrome и Opera приятный бонус - стилизованный скролл-бар.
*/
::-webkit-scrollbar {
background: transparent;
width: 0.5em;
position: absolute;
}
::-webkit-scrollbar-track {
background: transparent;
position: absolute;
z-index: -2;
}
::-webkit-scrollbar-thumb {
border-radius: 100px;
background: #888;
}
ul#selectMenuBox {
background: #fff;
transition: .3s;
width: 100%;
height: 200px;
overflow-y: auto;
overflow-x: hidden !important;
position: absolute;
margin-top: 00px;
display: block;
}
ul#selectMenuBox > li {
display: block;
padding: 10px;
border-radius: 00px;
cursor: pointer;
}
ul#selectMenuBox > li.option {
color: gray;
padding: 10px;
}
ul#selectMenuBox > li.option:hover {
color: #333;
background: #e1e1e1;
transition: .2s;
}
Особых сложностей тут нет, если вы владеете азами верстки и разметки средствами HTML и CSS3 соответственно.
А теперь к вкусностям! Рассмотрим исходный код плагина selectbox() для jQuery, файл selectbox.js :
selectbox.js
(function($) {
$.fn.selectbox = function() {
// начальные параметры
// задаем стандартную высоту div"a.
var selectDefaultHeight = $("#selectBox").height();
// угол поворота изображения в div"e
var rotateDefault = "rotate(0deg)";
// после нажатия кнопки срабатывает функция, в которой
// вычисляется исходная высота нашего div"a.
// очень удобно для сравнения с входящими параметрами (то, что задается в начале скрипта)
$("#selectBox > p.valueTag").click(function() {
// вычисление высоты объекта методом height()
var currentHeight = $("#selectBox").height();
// проверка условия на совпадение/не совпадение с заданной высотой вначале,
// чтобы понять. что делать дальше.
if (currentHeight < 100 || currentHeight == selectDefaultHeight) {
// если высота блока не менялась и равна высоте, заданной по умолчанию,
// тогда мы открываем список и выбираем нужный элемент.
$("#selectBox").height("250px"); // «точка остановки анимации»
// здесь стилизуем нашу стрелку и делаем анимацию средствами CSS3
$("img.arrow").css({borderRadius: "1000px", transition: ".2s", transform: "rotate(180deg)"});
}
// иначе если список развернут (высота больше или равна 250 пикселям),
// то при нажатии на абзац с классом valueTag, сворачиваем наш список и
// и присваиваем блоку первоначальную высоту + поворот стрелки в начальное положение
if (currentHeight >= 250) {
$("#selectBox").height(selectDefaultHeight);
$("img.arrow").css({transform: rotateDefault});
}
});
// так же сворачиваем список при выборе нужного элемента
// и меняем текст абзаца на текст элемента в списке
$("li.option").click(function() {
$("#selectBox").height(selectDefaultHeight);
$("img.arrow").css({transform: rotateDefault});
$("p.valueTag").text($(this).text());
});
};
})(jQuery);
Кода было больше, но удалось сжать благодаря методам css() и height(). Оформил в виде плагина для удобства и многократного использования. Можно сделать так, как вам нравится, лишь бы работало, так что я не обижусь, если кто-то оптимизирует мой костыль. Для вызова достаточно подключить внешний файл скрипта и вызвать плагин следующим образом:
$("selector").selectbox();
Предварительно, включив вызов в метод ready() объекта document, чтобы плагин загружался после полноценной загрузки документа. Подробнее, что такое плагин на jQuery, можно ознакомиться
Внимание! Дальнейшее развитие и поддержка плагина остановлены в связи с тем, что теперь он является частью .
Одна из самых неприятных (и я бы даже сказал ужасных) вещей в веб-разработке — это верстка html-форм. К сожалению, не существует единого стандарта отображения элементов форм, независимо от браузера и операционной системы, так же, как и нет возможности произвольно оформить некоторые из этих элементов, используя каскадные таблицы стилей.
Не поддаются полной стилизации следующие элементы html-форм:
- раскрывающийся список ;
- флажок ;
- переключатель .
- поле для отправки файла .
Как уже понятно из заголовка поста, здесь речь пойдет только про селекты.
Существует немало готовых решений в виде jQuery-плагинов для стилизации раскрывающихся списков. Но я (ввиду того, что ни один из плагинов меня не устроил по тем или иным причинам) решил пойти путем изобретения своего колеса и написал собственный плагин, которым и делюсь в данной статье.
Сразу хочу заметить, что данный плагин не подходит для всех возможных случаев применения селектов (читайте недостатки).
Демонстрация работы плагинаНа вы можете посмотреть пример стилизации селектов с помощью моего плагина. Их оформление я сделал без использования изображений.
Достоинства- При отключенном JavaScript отображаются стандартные селекты.
- Небольшой размер скрипта, примерно 4 килобайта.
- Работает в IE6+ и всех современных десктопных браузерах.
- Выводится внутристрочно.
- Легко поддается оформлению через CSS.
- Позволяет задать максимальную высоту для выпадающего списка (CSS-свойством max-height).
- Автоматически подстраивает ширину, если она не указана.
- Поддерживает прокрутку колесом мыши.
- Имеет «умное позиционирование», т.е. не уходит за видимую часть страницы при открытии списка.
- Умеет «ловить» нажатие клавиши Tab и переключаться стрелками на клавиатуре.
- Поддерживает атрибут «disabled».
- Работает и с динамически добавляемыми/изменяемыми селектами.
- Не поддерживает атрибут multiple , т.е. не позволяет выбирать несколько пунктов (мультиселект).
- Не поддерживает группировку элементов списка (тег ).
- Не поддерживает переключение стрелками на клавиатуре, когда список раскрыт кликом мыши.
Плагин недоступен, т.к. он уже не актуален.
jQuery-плагин «SelectBox Styler»Версия: 1.0.1 | Загрузок: 11103 | Размер: 7 Кб | Последнее обновление: 07.10.2012
Обновления 22.09.2012 Переделал скрипт в плагин (в том числе сделал минимизированный вариант), а также добавил поддержку динамического добавления/изменения селектов. 07.10.2012 Исправлено поведение скрипта при использовании метода onchange у тега . Подключение плагинаЕсли на сайте еще не подключен jQuery, то добавьте следующую строку перед тегом :
Сразу после jQuery подключите файл со скриптом:
(function($) { $(function() { $("select").selectbox(); }) })(jQuery)
Этот код поместите перед тегом после вышеуказанных файлов.
При динамическом изменении селектов необходимо запустить триггер refresh , например:
(function($) { $(function() { $("button").click(function() { $("select").find("option:nth-child(5)").attr("selected", true); $("select").trigger("refresh"); }) }) })(jQuery)
HTML-код после выполнения плагинаЕго структура выглядит следующим образом:
-- Выберите --
- -- Выберите --
- Пункт 1
- Пункт 2
- Пункт 3
Чтобы оформить селекты с помощью CSS, используйте следующие классы:
.selectbox | родительский контейнер для всего селекта |
.selectbox .select | селект в свернутом состоянии |
.selectbox.focused .select | фокус на селекте, когда нажата клавиша Tab |
.selectbox .select .text | вложенный тег для свернутого селекта на случай вставки фонового изображения по технике «раздвижных дверей» |
.selectbox .trigger | правая часть свернутого селекта (условный переключатель) |
.selectbox .trigger .arrow | вложенный тег для переключателя (стрелка) |
.selectbox .dropdown | обертка для выпадающего списка |
.selectbox .dropdown ul | выпадающий список |
.selectbox li | пункт (опция) селекта |
.selectbox li.selected | выбранный пункт селекта |
.selectbox li.disabled | отключенный (недоступный для выбора) пункт селекта |
Создание подобного скрипта — довольно кропотливое занятие, поскольку приходится учитывать множество различных моментов. Очень надеюсь, что никаких серьезных багов не вылезет. Но, если что, сообщайте в комментариях.
Soldatov NikolayСтилизация selectСтилизация select на чистом CSS без использования сторонних библиотек или JavaScript кода. А также бонус: рассмотрим как стилизовать select option при помощи JavaScript и jQuery Стилизация select
Структура будет стандартной
Слон Бегемот ЖирафЧтобы в select отображаемая строка была одна используем атрибут size со значением 1.
Стилизация для нашего селекта
-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 JavaScript PHP .select { display : block ; max-width : 215px ; width : 100% ; position : relative ; } .new-select { border : 1px solid #ced4da ; padding : 10px 15px ; cursor : pointer ; position : relative ; } .new-select__list { border : 1px solid #ced4da ; cursor : pointer ; position : absolute ; top : 45px ; left : 0 ; width : 100% ; } .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 ; -webkit-transition : all .27s ease-in-out ; -o-transition : all .27s ease-in-out ; transition : all .27s ease-in-out ; -webkit-transform : rotate (0deg ); -ms-transform : rotate (0deg ); -o-transform : rotate (0deg ); transform : rotate (0deg ); } .new-select.on :after { -webkit-transform : rotate (180deg ); -ms-transform : rotate (180deg ); -o-transform : rotate (180deg ); 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 (" " ); $ (" " , { class : " new-select " , text : _this . children (" option:disabled " ). text () }). insertAfter (_this ); const selectHead = _this . next (" .new-select " ); $ (" " , { class : " new-select__list " }). insertAfter (selectHead ); const selectList = selectHead . next (" .new-select__list " ); for (let i = 1 ; i < selectOptionLength ; i ++ ) { $ (" " , { class : " new-select__item " , html : $ (" " , { 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 ); } }); });Около года назад, я уже делал подробный обзор jQuery-плагинов для стилизации селектов . Итог остался неутешительным, у каждого из них были свои недостатки, и я так и не смог найти то, что хотел. В комментариях отписалось довольно много разработчиков, но все мы сошлись на том, что идеального плагина нет, и что над любым из них приходится хорошо поработать напильником.
Недавно на хабре проскакивал Selectik - довольно неплохой плагин, но не без недостатков . Работа над ним, судя по GitHub , ещё идёт, но пока он не очень удобен, и его основные проблемы ещё имеют место быть.
Недавно мне написал незнакомый человек, и попросил протестировать его плагин ikSelect , который он старался написать максимально приближенным к идеалу. Плагин мне настолько понравился, что после всестороннего тестирования и багфиксинга, я решил написать его обзор и поставить точку в данной теме, а также помочь толковому разработчику попасть на хабр.
В двух словах: он умеет практически всё, что умеет стандартный селект, при этом отлично стилизируется и подстраивается под особенности реализации селектов разных браузеров. Плагин полностью копирует внешний вид родного селекта Mac OS X, но его без проблем можно стилизировать через css.
Вот так он выглядит в закрытом виде:
Вот так в открытом:
Достоинства:
- работает во всех браузерах (IE6+, FF, Opera, Chrome, Safari), в том числе в мобильных
- автоматически подстраивает ширину
- открывается всегда на видимую часть страницы (так называемое «умное позиционирование»), как в горизонтальном, так и в вертикальном положении
- позволяет задавать максимальную высоту выпадающего списка
- позволяет группировать опции (optgroup)
- полностью управляется с клавиатуры (в т.ч. реагирует на переход Tab"ом, PgUp, PgDown, Home, End)
- имеет подбор по первым буквам (не только по одной, но и по последующим)
- поддерживает скролл колёсиком мышки
- вставляется инлайново (inline-block)
- замечательно работает с огромными списками (1000+ элементов)
- оставляет стандартный селект при отключенном javascript
- имеет отличный API
- не позволяет выделять сразу несколько пунктов (multiselect)
- не стилизирует скроллбар выпадающего списка (т.к. слишком сильно влияет на скорость работы)
- не бегает за пивом
В Opera mini остаются стандартные селекты, во избежание перезагрузки страницы при открытии списка. В Opera mobile работает так же, как и в настольной версии.
Кто серьёзно занимается вёрсткой страниц, знает, что возможности стилизации select в CSS крайне сильно ограничены. Но очень часто в дизайн стандартный select не вписывается вообще никак, поэтому приходится делать стилизацию select через JavaScript . Фактически, в этой статье мы с Вами создадим свой собственный select с помощью JavaScript .
Есть масса готовых плагинов, в том числе и на jQuery , которые позволяют всё это сделать. Но если Вам не нужно что-то сверхсложное, то проще сделать всё самому с нуля на чистом JavaScript .
Первым делом, давайте создадим HTML-структуру нашего будущего select :
Элемент 1
Элемент 2
Элемент 3
Элемент 1
Элемент 2
Элемент 3
Как видите, тега select тут и близко нет. Теперь мы можем как угодно стилизовать наш собственный select с помощью CSS :
Select {
background-color: #0ee;
border-radius: 10px;
padding: 10px 0;
width: 200px;
}
.select p {
cursor: pointer;
margin: 0;
padding: 5px 20px;
}
.select p.active {
background-color: #ee0;
}
Безусловно, Вы здесь можете сделать всё, что пожелаете. И, наконец, надо превратить внешний вид в функциональность select , то есть выбор и подстветка только одного элемента из нескольких, а также последующая отправка вместе с формой. Для этого мы воспользуемся JavaScript :
Function select(element) {
var value = element.getAttribute("data-value"); // Считываем значение выбранного элемента
var nodes = element.parentNode.childNodes; // Получаем все остальные элементы
for (var i = 0; i < nodes.length; i++) {
/* Отфильтровываем посторонние элементы text и input */
if (nodes[i] instanceof HTMLParagraphElement) {
/* Добавляем active у выбранного элемента, стирая данный класс у всех остальных */
if (value == nodes[i].getAttribute("data-value")) nodes[i].className = "active";
else nodes[i].className = "";
}
}
document.getElementById("my_select").value = value; // Устанавливаем в hidden-поле выбранное значение
}
Ключевым моментом реализации функциональности select является hidden-поле , в которое записывается значение из нашего select . И именно это значение будет отправлено при отправке формы.
Вот таким нехитрым образом делается абсолютно любая стилизация select на JavaScript . Если использовать jQuery , то код будет ещё проще.
Безусловно, стандартный select обладает большей функциональностью. Например, он реагирует на tab , также можно в нём перебирать элементы стрелками на клавиатуре. Но всё это Вы так же можете реализовать при необходимости на JavaScript .
И последняя рекомендация. В коде был использован тег noscript , и это было неслучайно. Поскольку не у всех JavaScript включён, и чтобы форма была вообще рабочей для таких пользователей, нужно вывести хотя бы стандартный select . А все, у кого JavaScript включён, увидят наш красивый select .
Устройства