JSFiddle - React, Tailwind, and code Playground
HTML
<select name="s" id="select">
<option value="111">1text1</option>
<option value="222">2text2</option>
<option value="333">3text3</option>
<option value="444">4text4</option>
<option value="555">5text5</option>
<option value="666">6text6</option>
<option value="777">7text7</option>
</select>
CSS
/* Было */
body{
display: flex;
align-items: center;
justify-content: center;
}
#dropdown{
border: 1px solid;
width: 200px;
border-radius: 2px;
}
#dropdown .value:hover,
#dropdown :checked + .value{
background-color: #dadada;
}
#dropdown .value{
width: 100%;
display: flex;
align-items: center;
text-indent: 10px;
}
/* Логика */
#dropdown{
position: relative;
--item-height: 30px;
--list-height: 200px;
}
#dropdown,
#dropdown .options .value{
height: var(--item-height);
}
#dropdown input{
opacity: 0;
position: absolute;
}
#dropdown .options{
position: absolute;
width: 100%;
top: 0;
padding-top: var(--item-height);
overflow: hidden;
height: 0;
transition: 0s .1s height;
}
#dropdown > :focus + .options{
height: var(--list-height);
overflow-y: scroll;
}
#dropdown .options :checked + .value{
position: absolute;
top: 0;
}
#dropdown > input:not(:focus){
width: 100%;
height: 100%;
display: block;
z-index: 3;
}
#dropdown > input{
position: relative;
}
/* Добавили */
#dropdown > input{
width: 100%;
height: 100%;
display: block;
z-index: 3;
}
#dropdown > input:focus{
opacity: 1;
transform: translateY(calc(100% - 2px));
margin: 0;
padding: 0;
}
#dropdown .options{
padding-top: calc(var(--item-height) * 2);
}
JavaScript
class Select{
constructor(id, search){
let replacement = document.querySelector(`#${id}`);
if(replacement.tagName != 'SELECT') return;
let dropDown = document.createElement('div');
dropDown.id = 'dropdown';
dropDown.innerHTML = `
<input type="text">
<div class="options">
${this.getList(replacement.querySelectorAll('option'))}
</div>
`;
this.options = dropDown.querySelector('.options');
this.name = replacement.name;
replacement.parentNode.replaceChild(dropDown, replacement);
if(search) this.initSearchable(dropDown);
}
getList(options){
let dd_options = '';
for(let option of options){
dd_options += this.getOption(option);
}
return dd_options;
}
getOption(option){
return `
<label>
<input type="radio" name="${this.name}" value="${option.value}">
<div class="value">${option.innerText}</div>
</label>
`;
}
get value(){
return this.options.querySelector(':checked').value;
}
initSearchable(dropDown){
var self = this;
let style = document.createElement('style');
dropDown.appendChild(style);
dropDown.querySelector(':scope > input').addEventListener('input', function () {
style.innerHTML = self.generateCSS(this.value);
})
}
generateCSS(value){
if(!value) return '';
return `
#dropdown .options :not(:checked):not([value*="${value}"]) + .value {
display:none;
}
`;
}
}
// Инициализируем
const mySelect = new Select('select', true);