Уж не помню почему, но оформление тега select вызывало какие-то адские трудности. Свидетельство тому – множество постов на просторах интернета, инструктирующих по данному вопросу и зачастую обладающих теми или иными надостатками. Более того, помню что и сам как-то мучился, приводя сей тег в соответствие макету заказчика и что-то попутно высказывая в сторону неуемной фантазии дизайнеров.
И вдруг – столкнувшись снова с этой задачей после долгого перерыва – обнаружил что все трудности куда-то делись. Все уместилось в маленький файл js и несколько строк css – при этом селект остается селектом и не подменяется сложной конструкцией из копирующих его блоков div, например.
Итак, решение:
Копируем файл select-wrap.js и подключаем его к нашей странице. Все как обычно, через тег script в заголовке <head> (<script src=”путь к файлу/select-wrap.js” type=”text/javascript”></script>, как-то так).
После его подключения обнаруживаем что все селекты на странице вида:
автоматом превращаются в:
Text111
Обертка в виде div’а с классом wselect будет изображать наш селект, для чего мы придадим ей соответствующий background и прочее – все как на макете. Т.е. это будет фон нашего селекта.
Span с классом selecttext внутри обертки будет выдавать текст, копируя значение select’а (и опять же, его нужно привести в соответствие макету – цвет, высота шрифта и проч). Т.е., опять же, это текст внутри селекта.
А сам селект мы сделаем прозрачным, но кликабельным и поместим его поверх нашей div’ной обертки. Чтобы все это случилось, добавим в страницу следующие стили:
.wselect { position: relative; /* Чтобы он ограничил собой завернутый select. Далее добавляем ему background, border-radius, тени, бордеры, размеры, в общем все, что нашей душе угодно */ } .selecttext { overflow: hidden; /* Чтобы не вылезал за пределы div-обертки */ display: block; /* Чтобы заполнил собой весь div. И, далее, опять – стили для текста внутри, заданные макетом – высота шрифта, цвет и проч. и проч. */ } select { position: absolute; /* Чтоб он выводился поверх обертки и был кликабельным */ top: 0; left: 0; /* Перемещаем его в верхний левый угол div-обертки */ width: 100%; /* …и растягиваем по длине на всю эту обертку. А чтоб и по высоте, лучше добавить соответствующий line-height */ opacity: 0; /* И делаем его при этом прозрачным */ cursor: pointer; /* На всякий случай */ }
(Не забудьте только удалить все пояснения между /* и */. Комментарии, как говорится, излишни).
И все.
В результате видим мы div-обертку и span-текст, а кликаем по настоящему select’у. Выпадающие options’ы при этом остаются вполне даже видимыми. Их оформление мы уже рассматривать не будем – оно зачастую и не требуется, как показывает практика.
Кстати, на всякий случай: у каждого span’а с классом selecttext есть свой id selecttext0, selecttext1, selecttext2 и далее до бесконечности, где число после selecttext равно индексу соответствующего селекта на странице.
В довесок тем, кому это интересно, предлагаю рассмотреть что же происходит в js файле. Собственно, большая его часть и без того прокомментирована:
window.onload = function() { /* Объявление переменных. slct - массив тегов select страницы, L - их количество, i - счетчик циклов, tmp - контейнер для создаваемого тега*/ var slct = document.getElementsByTagName('select'), L = slct.length, i, tmp; // Отключаем процесс для IE-8 if (window.navigator.userAgent.indexOf('IE 8') != -1) {L = 0;} /* Перебираем select'ы, оборачиваем их в div с классом wselect и добавляем span с классом selecttext для вывода текста из select'а*/ for (i = 0; i < L; i++) { tmp = document.createElement('div'); tmp.className = 'wselect'; slct[i].parentNode.insertBefore(tmp, slct[i]); tmp.appendChild(slct[i]); tmp.innerHTML = '' + tmp.innerHTML; }; //Селекты обернуты и готовы к использованию /*Создаем функцию, которая в селекте с индексом nn определяет активный option, берет из него текст и вставляет его в span с классом selecttext, после чего увеличивает счетчик (nn) на один и, если еще есть селекты с этим индексом, запускает сама себя, обрабатывая следующий select (таким образом перебираются все селекты страницы)*/ function goSelect(nn, L) { myid = 'selecttext' + nn; fgm = 0; for (i = 0; i < document.getElementsByTagName('select')[nn].options.length; i++) { if (document.getElementsByTagName('select')[nn].options[i].selected) {fgm = i;} } document.getElementById(myid).innerHTML = document.getElementsByTagName('select')[nn].options[fgm].text; nn++; if (nn < L) {goSelect(nn, L);} } // Функция, запускающая предыдущую со стартовым индексом nn = 0 function goSelectPlus(){ goSelect(0, L); } // И, наконец, функция, периодически запускающая предыдущую с интервалом 100 setInterval(goSelectPlus, 100); }
Что же происходит? Когда window готов и загружен, в первом цикле мы оборачиваем все селекты в уже известную нам конструкцию. В конце скрипта с определенной периодичностью мы начинаем запуск функции goSelectPlus, которая стартует функцию goSelect, которая, в свою очередь, каждый раз перебирает все селекты и вставляет их текущее значение в span selecttext.
Все нормально функционирует, только для ie8 предусмотрено отключение оборачивания (а также следует сделать для него обычные стили select), ибо в нем не работает. Ну и ладно.