selectmenu
by Kim Ara
HTML
<!-- 1 -->
<selectmenu class="my-custom-select1">
<option>Option 1</option>
<option>Option 2</option>
<option>Option 3</option>
</selectmenu>
<!-- 2 -->
<selectmenu class="my-custom-select2">
<div slot="button">
<button behavior="button">Open</button>
<span class="label">Choose an option</span>
</div>
<option>Option 1</option>
<option>Option 2</option>
<option>Option 3</option>
</selectmenu>
<!-- 3 -->
<selectmenu class="my-custom-select3">
<div slot="listbox">
<div popup behavior="listbox">
<option>Option 1</option>
<option>Option 2</option>
<option>Option 3</option>
<option>Option 4</option>
<option>Option 5</option>
</div>
</div>
</selectmenu>
<!-- 4 -->
<selectmenu class="my-custom-select4">
<div slot="button">
<span class="label">Choose a plant</span>
<span behavior="selected-value" slot="selected-value"></span>
<button behavior="button"></button>
</div>
<div slot="listbox">
<div popup behavior="listbox">
<div class="section">
<h3>Flowers</h3>
<option>Rose</option>
<option>Lily</option>
<option>Orchid</option>
<option>Tulip</option>
</div>
<div class="section">
<h3>Trees</h3>
<option>Weeping willow</option>
<option>Dragon tree</option>
<option>Giant sequoia</option>
</div>
</div>
</div>
</selectmenu>
<selectmenu class="multiselect">
<div slot="button" behavior="button">
<ul class="selected-values"><li><span class="label">Black olives</span><span class="remove"><svg viewBox="64 64 896 896" focusable="false" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5...
CSS
selectmenu {
display: block;
max-width: 300px;
}
/* 1 */
.my-custom-select1::part(button) {
color: white;
background-color: #f00;
padding: 5px;
border-radius: 5px;
}
.my-custom-select1::part(listbox) {
padding: 10px;
margin-top: 5px;
border: 1px solid red;
border-radius: 5px;
}
/* 2 */
.my-custom-select2 [slot='button'] {
display: flex;
align-content: center;
}
.my-custom-select2 button {
padding: 5px;
border: none;
background: #f06;
border-radius: 5px 0 0 5px;
color: white;
font-weight: bold;
}
.my-custom-select2 .label {
padding: 5px;
border: 1px solid #f06;
border-radius: 0 5px 5px 0;
}
/* 3 */
.my-custom-select3 [popup] {
width: 300px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
gap: 10px;
padding: 10px;
box-shadow: none;
margin: 10px 0;
border: 1px solid;
background: #f7f7f7;
}
/* 4 */
.my-custom-select4 [slot='button'] {
display: flex;
align-items: center;
gap: 1rem;
}
.my-custom-select4 button {
border: none;
margin: 0;
padding: 0;
width: 2rem;
height: 2rem;
border-radius: 50%;
display: grid;
place-content: center;
}
.my-custom-select4 button::before {
content: '\25BC';
}
.my-custom-select4 [popup] {
padding: 0;
}
.my-custom-select4 .section {
padding: 1rem 0 0;
background: radial-gradient(ellipse 60% 50px at center top, #000a 0%, transparent 130%);
}
.my-custom-select4 h3 {
margin: 0 0 1rem 0;
text-align: center;
color: white;
}
.my-custom-select4 option {
text-align: center;
padding: 0.5rem;
}
.multiselect [slot="button"] {
background-color: rgb(255, 255, 255);
border-width: 1px;
border-style: solid;
border-color: rgb(217, 217, 217);
border-radius: 2px;
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1) 0s;
width: 300px;
min-height: 32px;
}
.multiselect:focus-within [slot="button"] {
box-shadow: 0 0 0 2px...
JavaScript
const multiselect = document.querySelector('.multiselect');
const multiSelectedValuesContainer = multiselect.querySelector('.selected-values');
let multiValues = [];
multiselect.addEventListener('click', e => {
const option = e.target.closest('option');
if (!option) return;
const newValue = option.value;
if (multiValues.includes(newValue)) {
multiRemove(newValue);
} else {
multiAdd(newValue);
}
});
multiselect.addEventListener('click', e => {
const removeIcon = e.target.closest('.remove');
const selectedValue = e.target.closest('.selected-values li');
if (!removeIcon) return;
e.stopPropagation();
multiRemove(selectedValue.textContent);
}, true);
function multiAdd(value) {
multiValues.push(value);
multiRefreshSelectedValues();
multiRefreshOptions();
}
function multiRemove(toRemove) {
multiValues = multiValues.filter(value => value !== toRemove);
multiRefreshSelectedValues();
multiRefreshOptions();
}
function multiRefreshSelectedValues() {
multiSelectedValuesContainer.innerHTML = '';
multiValues.forEach(value => {
const label = document.createElement('span');
label.classList.add('label');
label.textContent = value;
const remove = document.createElement('span');
remove.classList.add('remove');
remove.innerHTML = '<svg viewBox="64 64 896 896" focusable="false" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8...