HTML proporciona una forma nativa de crear un cuadro de selección que soporta la selección de múltiples elementos con el atributo múltiple en los elementos de selección, pero la representación de esto realmente no es muy compacta o bonita, y no hay mucho que puedas hacer en cuanto a estilo con las opciones en un cuadro de selección tampoco. No pude encontrar ningún diseño personalizado que se ajustara al estilo que buscaba, así que acabé creando el mío propio. El código completo está disponible en mi GitHub aquí junto con una barra de búsqueda correspondiente.
Esto está construido desde cero debido a las dificultades para cambiar el comportamiento y el estilo de un select normal. La parte normalmente visible del select es un simple botón. El menú desplegable es un div oculto por la clase de utilidad de Bootstrap d-none, con redondeo y sombra aplicados a través de las clases de utilidad de Bootstrap shadow y rounded. Las opciones son simples casillas de verificación con etiquetas. Estas podrían ser reemplazadas por botones de radio si se desea una caja de selección única que coincida.
Aquí está el HTML final para el botón y el menú
<div> <button onclick="dropDown(event);" class="menu-btn" type="button"> Menu 1 ⌵ </button> <div class="d-none shadow rounded menu"> <span class="d-block menu-option"><label><input type="checkbox"> Option 1</label></span> <span class="d-block menu-option"><label><input type="checkbox"> Option 2</label></span> <span class="d-block menu-option"><label><input type="checkbox"> Option 3</label></span> </div></div>
Quería que el botón del menú fuera redondeado y bastante pequeño, así que le di el estilo correspondiente (puedes darle el estilo que quieras, por supuesto, no afecta a la función en absoluto):
.menu-btn { border-radius: 48px; border: 0.5px solid lightgrey; font-size: 0.9em; padding: 2px 10px; background-color: white;}
Para el menú en sí, añadí un poco de relleno para que el texto no se encontrara con la parte superior del menú y algo de margen para que no se superpusiera con el botón (ambos completamente opcionales). También añadí un índice z alto (para que se mostrara por encima de otras cosas), un color de fondo (por defecto es transparente, lo que parece una tontería en este contexto), y fijé la posición en absoluto para que no empujara otras cosas hacia abajo en la página.
.menu { padding-top: 10px; z-index: 200; margin-top: 4px; background-color: white; position: absolute;}
Para las opciones del menú, añadí un poco de relleno para separarlas.
.menu-option { padding: 6px 20px 6px;}
Necesitamos una forma de detectar cuando se hacen clics fuera del menú desplegable para que pueda ser descartado haciendo clic fuera de él como un cuadro de selección normal. Esto lo he hecho creando un div que cubre toda la pantalla con un índice z menor que el del menú. Esto nos permite detectar todos los clics fuera del menú
<div class="d-none" onclick="hide(event)"></div>
#overlay { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; z-index: 100;}
Para que esto funcione realmente, necesitamos funciones de JavaScript que hagan aparecer y desaparecer los menús y la superposición.
Esta función elimina las clases d-none del menú y la superposición, activándolos. En lugar de manejar esto vía ID, simplemente toma el segundo elemento del padre del objetivo (botón) y asume que ese es el menú. Esta es la razón por la que el menú y el botón están envueltos en un div vacío.
function dropDown(event) { event.target.parentElement.children.classList.remove("d-none"); document.getElementById("overlay").classList.remove("d-none");}
Esta función añade la clase d-none a la superposición y a todos los elementos con la clase menú, ocultándolos.
function hide(event) { var items = document.getElementsByClassName('menu'); for (let i = 0; i < items.length; i++) { items.classList.add("d-none"); } document.getElementById("overlay").classList.add("d-none");}
Si te ha parecido útil, puede que también te guste mi diseño de barra de búsqueda a juego.