<div class="grid place-items-center h-screen">
<div class="-mt-[200px] min-w-[300px]">
<select id="test">
<option value="Дети небес">Дети небес</option>
<option value="Вечное сияние чистого разума">Вечное сияние чистого разума</option>
<option value="Паразиты">Паразиты</option>
<option value="Три билборда на границе Эббинга, Миссури">Три билборда на границе Эббинга, Миссури</option>
<option value="Прежде чем мы расстанемся">Прежде чем мы расстанемся</option>
</select>
</div>
</div>
.awesome-select {
position: relative;
display: block;
}
.awesome-select__button {
border: none;
background: none;
text-align: left;
width: 100%;
position: relative;
padding: .5rem 2.5rem .5rem 1rem;
box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
border-radius: 4px;
}
.awesome-select__button::after {
position: absolute;
top: 0;
right: 0;
content: '';
background: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGNsYXNzPSJpY29uIGljb24tdGFibGVyIGljb24tdGFibGVyLWNhcmV0LWRvd24iIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBzdHJva2Utd2lkdGg9IjEiIHN0cm9rZT0iY3VycmVudENvbG9yIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwYXRoIHN0cm9rZT0ibm9uZSIgZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSI+PC9wYXRoPjxwYXRoIGQ9Ik0xOCAxNWwtNiAtNmwtNiA2aDEyIiB0cmFuc2Zvcm09InJvdGF0ZSgxODAgMTIgMTIpIj48L3BhdGg+PC9zdmc+') no-repeat center center / 60%;
width: 2rem;
height: 100%;
}
.awesome-select._opened .awesome-select__button::after {
transform: rotate(180deg);
}
.awesome-select__list {
z-index: 10;
display: none;
position: absolute;
top: calc(100% - 1px);
width: 100%;
background-color: white;
padding: .25rem 0;
box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
}
.awesome-select._opened .awesome-select__list {
display: block;
}
.awesome-select__item {
padding: .5rem 1rem;
white-space: nowrap;
cursor: pointer;
overflow-x: hidden;
text-overflow: ellipsis;
}
.awesome-select__item._selected,
.awesome-select__item:hover {
background-color: #f1f1f1;
}
class AwesomeSelect {
_selectedClass = '_selected';
_openedClass = '_opened';
constructor (el) {
this.el = typeof el === 'string' ? document.querySelector(el) : el;
if (!(this.el instanceof HTMLSelectElement)) {
throw new Error('Element is undefined');
}
this.$wrapper = document.createElement('div');
this.$wrapper.classList.add('awesome-select');
this.$button = document.createElement('button');
this.$button.classList.add('awesome-select__button');
this.$button.innerText = this.el.options[this.defaultIndex].text;
this.$button.addEventListener('click', e => {
e.preventDefault();
this.toggle();
});
this.$wrapper.append(this.$button);
this.$list = document.createElement('ul');
this.$list.classList.add('awesome-select__list');
for (const { innerText, index } of this.el.options) {
const item = document.createElement('li');
item.classList.add('awesome-select__item');
item.innerText = innerText;
item.setAttribute('title', innerText);
if (this.defaultIndex === index) {
item.classList.add(this._selectedClass);
}
item.addEventListener('click', () => {
this.el.selectedIndex = index;
this.el.dispatchEvent(new Event('change'));
});
this.$list.append(item);
}
this.$wrapper.append(this.$list);
this.el.after(this.$wrapper);
this.el.style.display = 'none';
this.el.form?.addEventListener('reset', () => {
this.el.selectedIndex = this.defaultIndex;
this.el.dispatchEvent(new Event('change'));
});
this.el.addEventListener('change', () => this.update());
document.addEventListener('click', e => {
if (!this.$wrapper.contains(e.target) && this.isOpened) {
this.close();
}
});
}
open () {
this.$wrapper.classList.add(this._openedClass);
Array.from(document.querySelectorAll('.awesome-select'))
.filter(el => el.classList.contains(this._openedClass) && el !== this.$wrapper)
.forEach(el => el.classList.remove(this._openedClass));
}
close () {
this.$wrapper.classList.remove(this._openedClass);
}
toggle () {
if (this.isOpened) {
this.close();
} else {
this.open();
}
}
update (index = this.el.selectedIndex) {
const option = this.el.options[index];
this.$button.innerText = option.text || option.value;
this.$list.querySelectorAll('li').forEach((el, i) => el.classList[i === index ? 'add' : 'remove'](this._selectedClass));
this.close();
}
get defaultIndex () {
const index = Array.from(this.el.options).findIndex(option => option.defaultSelected);
return index > -1 ? index : 0;
}
get isOpened () {
return this.$wrapper.classList.contains(this._openedClass);
}
}
new AwesomeSelect('#test');
This Pen doesn't use any external CSS resources.