JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<ul class="select" data-placeholder="Role" data-name="role">
<li data-value="admin">Administrator</li>
<li data-value="mod">Moderator</li>
<li data-value="user">User</li>
</ul>
CSS
.li-select-container {
width: 200px;
display: table;
position: relative;
margin: .5em 0;
font-family: sans-serif;
font-size: 1em;
}
.li-select-container input {
background-color: white;
width: 100%;
padding: 2px 5px;
box-sizing: border-box;
border: 1px solid hsl(0, 0%, 60%);
user-select: none;
-webkit-user-select: none;
cursor: default;
font-size: inherit;
}
.li-select-container input.placeholder {
color: rgba(0,0,0,.5);
}
.li-select-container input:focus {
border: 1px solid hsl(210, 100%, 56%);
box-shadow: 0 0 1px hsl(210, 100%, 56%, .5);
}
.li-select-container .arrow {
font-size: .7em;
opacity: 0.75;
position: absolute;
right: 5px;
top: 50%;
transform: translateY(-50%);
user-select: none;
cursor: default;
}
.li-select-container:hover input:not(:focus) {
border: 1px solid hsla(0, 0%, 30%);
}
.li-select-container:hover .arrow {
opacity: 1;
}
.li-select-container ul {
background-color: white;
border: 1px solid hsl(0, 0%, 60%);
border-top: none;
user-select: none;
display: none;
position: absolute;
width: 100%;
z-index: 999;
box-sizing: border-box;
padding: 0;
list-style: none;
margin: 0;
}
.li-select-container.visible ul {
display: block;
}
.li-select-container ul li {
padding: 2px 5px;
cursor: default;
}
.li-select-container ul li.placeholder {
opacity: 0.5;
}
.li-select-container ul li.hover {
background-color: dodgerblue;
color: white;
}
.li-select-container ul li.placeholder.hover {
background-color: rgba(0,0,0,.1);
color: initial;
}
JavaScript
// helper function to create elements faster/easier
// https://github.com/akinuri/js-lib/blob/master/element.js
var elem = function (tagName, attributes, children, isHTML) {
let parent;
if (typeof tagName == "string") {
parent = document.createElement(tagName);
} else if (tagName instanceof HTMLElement) {
parent = tagName;
}
if (attributes) {
for (let attribute in attributes) {
parent.setAttribute(attribute, attributes[attribute]);
}
}
var isHTML = isHTML || null;
if (children || children == 0) {
elem.append(parent, children, isHTML);
}
return parent;
};
elem.append = function (parent, children, isHTML) {
if (parent instanceof HTMLTextAreaElement || parent instanceof HTMLInputElement) {
if (children instanceof Text || typeof children == "string" || typeof children == "number") {
parent.value = children;
}
else if (children instanceof Array) {
children.forEach(function (child) {
elem.append(parent, child);
});
}
else if (typeof children == "function") {
elem.append(parent, children());
}
} else {
if (children instanceof HTMLElement || children instanceof Text) {
parent.appendChild(children);
}
else if (typeof children == "string" || typeof children == "number") {
if (isHTML) {
parent.innerHTML += children;
} else {
parent.appendChild(document.createTextNode(children));
}
}
else if (children instanceof Array) {
children.forEach(function (child) {
elem.append(parent, child);
});
}
else if (typeof children == "function") {
elem.append(parent, children());
}
}
};
// ============================== HELPER FUNCTIONS
HTMLElement.prototype.getIndex = function () {
...