Красивый Select для сайта и форума на phpbb
Стилизация выпадающего списка Select.
По умолчанию Select не поддаётся какой либо стилизации, можно разве что поменять цвета и размер шрифта.
Чтобы сделать Select красивым нам понадобятся стили и небольшой скрипт.
Для начала посмотрим как это выглядит.
В демо примере по умолчанию тема тёмная:
Чтобы включить светлую кликните на соответствующую кнопку внизу экрана.
Теперь давайте разберёмся со структурой, в принципе для изменения существующих на сайте Select менять структуру и не нужно, нужно лишь добавить соответствующий класс:
<select class="dropdown" placeholder="Сделайте выбор">
<option>Пункт списка #1</option>
<option>Пункт списка #2</option>
<option>Пункт списка #3</option>
<option>Пункт списка #4</option>
</select>
Далее будут стили. Здесь я хочу сделать одну небольшую заметку, дело в том что добавлять класс к тегу это не всегда удобно, если у тега уже есть свой класс — используйте его, просто замените класс dropdown в стилях расположенных ниже на свой.
Начнём свои стили с разбора цветовых версий, выглядит это примерно так:
.dropdown {
--max-scroll: 8;
--text: #3F4656;
--border: #2F3545;
--borderActive: #23C4F8;
--background: #151924;
--arrow: #6C7486;
--arrowActive: #E4ECFA;
--listText: #99A3BA;
--listBackground: #F5F9FF;
--listActive: #E4ECFA;
--listTextActive: #6C7486;
--listBorder: none;
--textFilled: #99A3BA;
width: 220px;
position: relative;
}
.dropdown.light {
--text: #CDD9ED;
--border: #CDD9ED;
--borderActive: #23C4F8;
--background: #fff;
--arrow: #99A3BA;
--arrowActive: #6C7486;
--listText: #99A3BA;
--listBackground: #fff;
--listActive: #F5F9FF;
--listTextActive: #6C7486;
--listBorder: #E4ECFA;
--textFilled: #6C7486;
}
Первая часть, это тёмная версия, вторая светлая.
Т.е. если вы хотите использовать светлую версию оформления select, то просто замените стили первого фрагмента из второго. Выглядеть это будет так:
.dropdown {
--max-scroll: 8;
--text: #CDD9ED;
--border: #CDD9ED;
--borderActive: #23C4F8;
--background: #fff;
--arrow: #99A3BA;
--arrowActive: #6C7486;
--listText: #99A3BA;
--listBackground: #fff;
--listActive: #F5F9FF;
--listTextActive: #6C7486;
--listBorder: #E4ECFA;
--textFilled: #6C7486;
width: 220px;
position: relative;
}
Остальные стили:
.dropdown select {
display: none;
}
.dropdown > span {
cursor: pointer;
padding: 9px 16px;
border-radius: 6px;
display: block;
position: relative;
color: var(--text);
border: 1px solid var(--border);
background: var(--background);
transition: all .3s ease;
}
.dropdown > span:before, .dropdown > span:after {
content: '';
display: block;
position: absolute;
width: 8px;
height: 2px;
border-radius: 1px;
top: 50%;
right: 15px;
background: var(--arrow);
transition: all .3s ease;
}
.dropdown > span:before {
margin-right: 4px;
-webkit-transform: scale(0.96, 0.8) rotate(50deg);
transform: scale(0.96, 0.8) rotate(50deg);
}
.dropdown > span:after {
-webkit-transform: scale(0.96, 0.8) rotate(-50deg);
transform: scale(0.96, 0.8) rotate(-50deg);
}
.dropdown ul {
margin: 0;
padding: 0;
list-style: none;
opacity: 0;
visibility: hidden;
position: absolute;
max-height: calc(var(--max-scroll) * 42px);
top: 42px;
left: 0;
z-index: 1;
right: 0;
background: var(--listBackground);
border-radius: 6px;
overflow-x: hidden;
overflow-y: auto;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
transition: opacity 0.2s ease, visibility 0.2s ease, -webkit-transform 0.3s cubic-bezier(0.4, 0.6, 0.5, 1.32);
transition: opacity 0.2s ease, visibility 0.2s ease, transform 0.3s cubic-bezier(0.4, 0.6, 0.5, 1.32);
transition: opacity 0.2s ease, visibility 0.2s ease, transform 0.3s cubic-bezier(0.4, 0.6, 0.5, 1.32), -webkit-transform 0.3s cubic-bezier(0.4, 0.6, 0.5, 1.32);
-webkit-transform: scale(0.8) translate(0, 4px);
transform: scale(0.8) translate(0, 4px);
border: 1px solid var(--listBorder);
}
.dropdown ul li {
opacity: 0;
-webkit-transform: translate(6px, 0);
transform: translate(6px, 0);
transition: all .3s ease;
}
.dropdown ul li a {
cursor: pointer;
display: block;
padding: 10px 16px;
color: var(--listText);
text-decoration: none;
outline: none;
position: relative;
transition: all .3s ease;
}
.dropdown ul li a:hover {
color: var(--listTextActive);
}
.dropdown ul li.active a {
color: var(--listTextActive);
background: var(--listActive);
}
.dropdown ul li.active a:before, .dropdown ul li.active a:after {
--scale: .6;
content: '';
display: block;
width: 10px;
height: 2px;
position: absolute;
right: 17px;
top: 50%;
opacity: 0;
background: var(--listText);
transition: all .2s ease;
}
.dropdown ul li.active a:before {
-webkit-transform: rotate(45deg) scale(var(--scale));
transform: rotate(45deg) scale(var(--scale));
}
.dropdown ul li.active a:after {
-webkit-transform: rotate(-45deg) scale(var(--scale));
transform: rotate(-45deg) scale(var(--scale));
}
.dropdown ul li.active a:hover:before, .dropdown ul li.active a:hover:after {
--scale: .9;
opacity: 1;
}
.dropdown ul li:first-child a {
border-radius: 6px 6px 0 0;
}
.dropdown ul li:last-child a {
border-radius: 0 0 6px 6px;
}
.dropdown.filled > span {
color: var(--textFilled);
}
.dropdown.open > span {
border-color: var(--borderActive);
}
.dropdown.open > span:before, .dropdown.open > span:after {
background: var(--arrowActive);
}
.dropdown.open > span:before {
-webkit-transform: scale(0.96, 0.8) rotate(-50deg);
transform: scale(0.96, 0.8) rotate(-50deg);
}
.dropdown.open > span:after {
-webkit-transform: scale(0.96, 0.8) rotate(50deg);
transform: scale(0.96, 0.8) rotate(50deg);
}
.dropdown.open ul {
opacity: 1;
visibility: visible;
-webkit-transform: scale(1) translate(0, 12px);
transform: scale(1) translate(0, 12px);
transition: opacity 0.3s ease, visibility 0.3s ease, -webkit-transform 0.3s cubic-bezier(0.4, 0.6, 0.5, 1.32);
transition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s cubic-bezier(0.4, 0.6, 0.5, 1.32);
transition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s cubic-bezier(0.4, 0.6, 0.5, 1.32), -webkit-transform 0.3s cubic-bezier(0.4, 0.6, 0.5, 1.32);
}
.dropdown.open ul li {
opacity: 1;
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
.dropdown.open ul li:nth-child(1) {
transition-delay: 80ms;
}
.dropdown.open ul li:nth-child(2) {
transition-delay: 160ms;
}
.dropdown.open ul li:nth-child(3) {
transition-delay: 240ms;
}
.dropdown.open ul li:nth-child(4) {
transition-delay: 320ms;
}
.dropdown.open ul li:nth-child(5) {
transition-delay: 400ms;
}
.dropdown.open ul li:nth-child(6) {
transition-delay: 480ms;
}
.dropdown.open ul li:nth-child(7) {
transition-delay: 560ms;
}
.dropdown.open ul li:nth-child(8) {
transition-delay: 640ms;
}
.dropdown.open ul li:nth-child(9) {
transition-delay: 720ms;
}
.dropdown.open ul li:nth-child(10) {
transition-delay: 800ms;
}
select {
--text: #3F4656;
--border: #2F3545;
--background: #151924;
}
select.dropdown {
padding: 9px 16px;
border-radius: 6px;
color: var(--text);
border: 1px solid var(--border);
background: var(--background);
line-height: 22px;
font-size: 16px;
font-family: inherit;
-webkit-appearance: none;
}
Со стилями всё. Теперь очередь скрипта:
$('select.dropdown').each(function() {
var dropdown = $('<div />').addClass('dropdown selectDropdown');
$(this).wrap(dropdown);
var label = $('<span />').text($(this).attr('placeholder')).insertAfter($(this));
var list = $('<ul />');
$(this).find('option').each(function() {
list.append($('<li />').append($('<a />').text($(this).text())));
});
list.insertAfter($(this));
if($(this).find('option:selected').length) {
label.text($(this).find('option:selected').text());
list.find('li:contains(' + $(this).find('option:selected').text() + ')').addClass('active');
$(this).parent().addClass('filled');
}
});
$(document).on('click touch', '.selectDropdown ul li a', function(e) {
e.preventDefault();
var dropdown = $(this).parent().parent().parent();
var active = $(this).parent().hasClass('active');
var label = active ? dropdown.find('select').attr('placeholder') : $(this).text();
dropdown.find('option').prop('selected', false);
dropdown.find('ul li').removeClass('active');
dropdown.toggleClass('filled', !active);
dropdown.children('span').text(label);
if(!active) {
dropdown.find('option:contains(' + $(this).text() + ')').prop('selected', true);
$(this).parent().addClass('active');
}
dropdown.removeClass('open');
});
$('.dropdown > span').on('click touch', function(e) {
var self = $(this).parent();
self.toggleClass('open');
});
$(document).on('click touch', function(e) {
var dropdown = $('.dropdown');
if(dropdown !== e.target && !dropdown.has(e.target).length) {
dropdown.removeClass('open');
}
});
Если вы всё же решили не добавлять класс к своим тегам, а обойтись уже существующими и уже поменяли в стилях класс dropdown
на свой, то не забудьте его поменять и в скрипте, их в нём четыре штуки.
В принципе на этом всё, да не всё. В заголовке же указан форумный движок phpbb, значит будем пробовать прикручивать к нему. Для места где он будет использоваться я выбрал личный раздел, поэтому в стилях и скрипте будет дополнительный класс.
Структуру для форума нам менять не нужно, чтобы добавить класс придётся править кучу файлов, мы лучше используем дополнительные классы. Классы использованные выше нам тоже не подойдут, класс dropdown
в phpbb уже используется, даже dropdown-select
тоже не получится использовать, сделаю так ca_dropdown-select
.
.ca_dropdown-select {
--max-scroll: 8;
width: 220px;
position: relative;
}
.ca_dropdown-select {
--text: #CDD9ED;
--border: #CDD9ED;
--borderActive: #bf0000;
--background: #fff;
--arrow: #99A3BA;
--arrowActive: #6C7486;
--listText: #8b93a7;
--listBackground: #fff;
--listActive: #cadceb;
--listTextActive: #333333;
--listBorder: #E4ECFA;
--textFilled: #6C7486;
}
.ca_dropdown-select select {
display: none;
}
.ca_dropdown-select > span {
cursor: pointer;
padding: 5px 12px;
border-radius: 5px;
display: block;
position: relative;
color: var(--text);
border: 1px solid var(--border);
background: var(--background);
transition: all .3s ease;
}
.ca_dropdown-select > span:before, .ca_dropdown-select > span:after {
content: '';
display: block;
position: absolute;
width: 8px;
height: 2px;
border-radius: 1px;
top: 50%;
right: 15px;
background: var(--arrow);
transition: all .3s ease;
}
.ca_dropdown-select > span:before {
margin-right: 4px;
-webkit-transform: scale(0.96, 0.8) rotate(50deg);
transform: scale(0.96, 0.8) rotate(50deg);
}
.ca_dropdown-select > span:after {
-webkit-transform: scale(0.96, 0.8) rotate(-50deg);
transform: scale(0.96, 0.8) rotate(-50deg);
}
.ca_dropdown-select ul {
margin: 0;
padding: 0;
list-style: none;
opacity: 0;
visibility: hidden;
position: absolute;
max-height: calc(var(--max-scroll) * 34px);
top: 28px;
left: 0;
z-index: 1;
right: 0;
background: var(--listBackground);
border-radius: 6px;
overflow-x: hidden;
overflow-y: auto;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
transition: opacity 0.2s ease, visibility 0.2s ease, -webkit-transform 0.3s cubic-bezier(0.4, 0.6, 0.5, 1.32);
transition: opacity 0.2s ease, visibility 0.2s ease, transform 0.3s cubic-bezier(0.4, 0.6, 0.5, 1.32);
transition: opacity 0.2s ease, visibility 0.2s ease, transform 0.3s cubic-bezier(0.4, 0.6, 0.5, 1.32), -webkit-transform 0.3s cubic-bezier(0.4, 0.6, 0.5, 1.32);
-webkit-transform: scale(0.8) translate(0, 4px);
transform: scale(0.8) translate(0, 4px);
border: 1px solid var(--listBorder);
}
.ca_dropdown-select ul li {
opacity: 0;
-webkit-transform: translate(6px, 0);
transform: translate(6px, 0);
transition: all .3s ease;
}
.ca_dropdown-select ul li a {
cursor: pointer;
display: block;
padding: 6px 12px;
color: var(--listText);
text-decoration: none;
outline: none;
position: relative;
transition: all .3s ease;
}
.ca_dropdown-select ul li a:hover {
color: var(--listTextActive);
}
.ca_dropdown-select ul li.active a {
color: var(--listTextActive);
background: var(--listActive);
}
.ca_dropdown-select ul li.active a:before, .ca_dropdown-select ul li.active a:after {
--scale: .6;
content: '';
display: block;
width: 10px;
height: 2px;
position: absolute;
right: 17px;
top: 50%;
opacity: 0;
background: var(--listText);
transition: all .2s ease;
}
.ca_dropdown-select ul li.active a:before {
-webkit-transform: rotate(45deg) scale(var(--scale));
transform: rotate(45deg) scale(var(--scale));
}
.ca_dropdown-select ul li.active a:after {
-webkit-transform: rotate(-45deg) scale(var(--scale));
transform: rotate(-45deg) scale(var(--scale));
}
.ca_dropdown-select ul li.active a:hover:before, .ca_dropdown-select ul li.active a:hover:after {
--scale: .9;
opacity: 1;
}
.ca_dropdown-select ul li:first-child a {
border-radius: 5px 5px 0 0;
}
.ca_dropdown-select ul li:last-child a {
border-radius: 0 0 6px 6px;
}
.ca_dropdown-select.filled > span {
color: var(--textFilled);
}
.ca_dropdown-select.open-select > span {
border-color: var(--borderActive);
}
.ca_dropdown-select.open-select > span:before, .ca_dropdown-select.open-select > span:after {
background: var(--arrowActive);
}
.ca_dropdown-select.open-select > span:before {
-webkit-transform: scale(0.96, 0.8) rotate(-50deg);
transform: scale(0.96, 0.8) rotate(-50deg);
}
.ca_dropdown-select.open-select > span:after {
-webkit-transform: scale(0.96, 0.8) rotate(50deg);
transform: scale(0.96, 0.8) rotate(50deg);
}
.ca_dropdown-select.open-select ul {
opacity: 1;
visibility: visible;
-webkit-transform: scale(1) translate(0, 12px);
transform: scale(1) translate(0, 12px);
transition: opacity 0.3s ease, visibility 0.3s ease, -webkit-transform 0.3s cubic-bezier(0.4, 0.6, 0.5, 1.32);
transition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s cubic-bezier(0.4, 0.6, 0.5, 1.32);
transition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s cubic-bezier(0.4, 0.6, 0.5, 1.32), -webkit-transform 0.3s cubic-bezier(0.4, 0.6, 0.5, 1.32);
}
.ca_dropdown-select.open-select ul li {
opacity: 1;
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
.ca_dropdown-select.open-select ul li:nth-child(1) {
transition-delay: 80ms;
}
.ca_dropdown-select.open-select ul li:nth-child(2) {
transition-delay: 160ms;
}
.ca_dropdown-select.open-select ul li:nth-child(3) {
transition-delay: 240ms;
}
.ca_dropdown-select.open-select ul li:nth-child(4) {
transition-delay: 320ms;
}
.ca_dropdown-select.open-select ul li:nth-child(5) {
transition-delay: 400ms;
}
.ca_dropdown-select.open-select ul li:nth-child(6) {
transition-delay: 480ms;
}
.ca_dropdown-select.open-select ul li:nth-child(7) {
transition-delay: 560ms;
}
.ca_dropdown-select.open-select ul li:nth-child(8) {
transition-delay: 640ms;
}
.ca_dropdown-select.open-select ul li:nth-child(9) {
transition-delay: 720ms;
}
.ca_dropdown-select.open-select ul li:nth-child(10) {
transition-delay: 800ms;
}
#ucp dd select {
--text: #3F4656;
--border: #bdbdbd;
--background: #ffffff;
}
#ucp dd select {
padding: 5px 12px;
border-radius: 5px;
color: var(--text);
border: 1px solid var(--border);
background: var(--background);
line-height: 22px;
font-size: 13px;
font-family: inherit;
-webkit-appearance: none;
}
#ucp fieldset dl {
overflow: visible;
}
#ucp fieldset dl:after {
clear: both;
content: '';
display: block;
}
И скрипт:
$('#ucp dd select').each(function() {
var dropdown = $('<div />').addClass('ca_dropdown-select selectDropdown');
$(this).wrap(dropdown);
var label = $('<span />').text($(this).attr('placeholder')).insertAfter($(this));
var list = $('<ul />');
$(this).find('option').each(function() {
list.append($('<li />').append($('<a />').text($(this).text())));
});
list.insertAfter($(this));
if($(this).find('option:selected').length) {
label.text($(this).find('option:selected').text());
list.find('li:contains(' + $(this).find('option:selected').text() + ')').addClass('active');
$(this).parent().addClass('filled');
}
});
$(document).on('click touch', '.selectDropdown ul li a', function(e) {
e.preventDefault();
var dropdown = $(this).parent().parent().parent();
var active = $(this).parent().hasClass('active');
var label = active ? dropdown.find('select').attr('placeholder') : $(this).text();
dropdown.find('option').prop('selected', false);
dropdown.find('ul li').removeClass('active');
dropdown.toggleClass('filled', !active);
dropdown.children('span').text(label);
if(!active) {
dropdown.find('option:contains(' + $(this).text() + ')').prop('selected', true);
$(this).parent().addClass('active');
}
dropdown.removeClass('open-select');
});
$('.ca_dropdown-select > span').on('click touch', function(e) {
var self = $(this).parent();
self.toggleClass('open-select');
});
$(document).on('click touch', function(e) {
var dropdown = $('.ca_dropdown-select');
if(dropdown !== e.target && !dropdown.has(e.target).length) {
dropdown.removeClass('open-select');
}
});
#ucp dd select
в начале позволяет скрипту отрабатывать только на странице личного раздела.
Пробуйте!