Дизайнеры всё время изощряются с тенями и красивыми формами.
Вопрос такой — как проще всего сверстать нестандартный <select>?
Артём Поликарпов
Если вы в раю и верстаете только под Вебкит, то воспользуйтесь правилом -webkit-appearance: button, чтобы стилизовать кнопку селекта как угодно.
Обычный селект:
Немного ЦСС:
.ap-select_special {
-webkit-appearance: button;
-webkit-border-radius: 20px;
/* Подмешал вебкитовский градиент,
чтобы не показывать стрелку в других браузерах */
background: url(select-arrow.png) no-repeat right center,
-webkit-linear-gradient(#fff, #fff);
border: 2px solid #adcbe2;
padding: 0 29px 0 7px;
height: 24px;
font-size: 13px;
line-height: 16px;
text-overflow: ellipsis;
white-space: nowrap;
outline: none;
color: #3e94c5;
font: -webkit-small-control;
}
.ap-select_special:focus {
-webkit-box-shadow: 0 0 5px #879eb0;
}
И «дизайнерский» селект готов, но работает он только в Сафари и Хроме:
В остальных браузерах свойство appearance не поддерживается или поддерживается очень слабо, поэтому, если вы не в раю, такое решение не годится.
По сути, селект — это кнопка и поповер со списком вариантов. Зная джаваскрипт, можно написать собственный элемент. Но сначала лучше поискать что-то готовое.
Вот, например, Chosen. Тут уже реализованы навигация по списку стрелками и поиск.
Неплохо, осталось написать нужные стили, спрятать поле поиска и заодно исправить неопрятные моменты(например, убрать четырёх-пиксельный отступ вокруг списка):
Изменить поведение при вводе с клавиатуры, чтобы приблизиться к стандартному селекту — после ввода каждой буквы есть 1,5 секунды для ввода следующей, затем значение невидимого поля поиска сбрасывается:
$(function() {
var clearChznSearch = function(chznSearch) {
clearTimeout(chznSearch.data('timeout'));
chznSearch.val('').trigger('keyup');
}
var chznSpecial = $('.ap-chosen_special');
$('input', chznSpecial).bind('keypress', function() {
var chznSearch = $(this);
// Очищаю заданный ранее таймаут
clearTimeout(chznSearch.data('timeout'));
chznSearch.data({
timeout: setTimeout(function() {
// Очищаю поиск по списку через 1,5 секунды
clearChznSearch(chznSearch);
}, 1500)
});
});
$('li', chznSpecial).bind('mouseover', function() {
// Очищаю поиск по списку по наведению на значения
var chznSearch = $('input', $(this).parents('.ap-chosen_special'));
if (chznSearch.val()) {
clearChznSearch(chznSearch);
}
});
});
Результат, работает в ИЕ8+ и всех остальных браузерах:
Для второго элемента с вашей картинки(выбор количества звёзд) ни стандартный селект, ни Chosen не подойдут — придётся написать его самостоятельно.
В бюро всегда осторожно используют нестандартные элементы интерфейса. О целесообразности использования подобных«дизайнерских» контролов я предлагаю высказаться уважаемым советчикам-дизайнерам.
P. S.
Это был совет о разработке веб-интерфейсов. Хотите узнать всё об умной вёрстке, правильных скриптах, грациозной деградации, трюках и работе технолога с дизайнером? Присылайте вопросы.
Основная проблема с «дизайнерскими» контролами в том, что в каждой операционной системе есть различные хоткеи, включая редкоиспользуемые. Даже если рассмотреть только Windows: хоть я давно пользуюсь Маком, но помню свою привычку раскрывать селекты по «Альт+вниз». Ни одна из виденных мной JS-реализаций эту комбинацию клавиш не поддерживала, включая те, где разработчики заявляли о «полной эмуляции» родных селектов.
А сколько таких «дизайнерских» селектов сделаны до появления айфонов, и сколько людей мучаются с этим «дизайном» на маленьких тачскринах?
С приведенным вариантом проблема: pgup/pgdn/home/end просто прокручивают страницу.
Да и с простой стилизацией селектов надо быть аккуратнее. Вот, например, на этой странице я ввожу комментарий в узком «иллюминаторе», перемещаясь по элементам формы исключительно табуляцией. На других страницах «Советов» все хорошо — так что логика подсказывает, что виноваты подключенные на этой странице ЦСС :-)
Есть ещё один способ, близкий к первому, но чуть более сложный и требующий немного JS и дополнительной разметки.
Под стандартный select подкладывается div, выглядящий так как, как должен выглядеть желаемый select, а самому селекту делается opacity:0 (и filter:Alpha(opacity=0)). Далее остаётся только перехватывать события селекта focus и blur (ну и mouseover/mouseout если нужно) и устанавливать на div соответствующие классы-состояния. А по change и keyup записывать в div текст выбранного в select пункта.
Выглядеть и работать будет точно так вариант с webkit-appearance. Прекрасно работает в ИЕ8+ (про более старые не уверен). Как это работает можно посмотреть, например, на новой главной Мэйл.ру (выбор домена в форме входа).
P. S. Понравился хак с градиентом. Артём, а почему button, а не none?
Спасибо Саше и Константину за баг-репорты. Форма не открывалась не из-за ЦСС, а из-за несовместимости с Джейквери 1.7.1, который я подключил для Чозена. Теперь скрипт формы модернизирован и работает.
И я немного поправил сам Чозен — убрал произвольное выпрыгивание клавиатуры на айпаде, починил потерю фокуса и ещё какие-то интерфейсные мелочи. Мои исправления можно найти в файле chosen.jquery.customized.js по четырём слешам (////):
Артём, разницы между button и none при тестировании я не заметил. Выбрал первое из-за семантики и гипотетически более надёжного определения ширины и умещения невлезающего текста.