141

The client has given me a design which has a Select Option menu containing a checkbox together with the item name as individual items in the list. Is there anyway possible to add a checkbox inside a Select Option menu?

NB: Developer needs to add his own id to make the menu effective, I only need the HTML CSS code if it is possible.

TylerH
  • 20,799
  • 66
  • 75
  • 101
Hero Tra
  • 1,443
  • 2
  • 10
  • 3

12 Answers12

239

You cannot place checkbox inside select element but you can get the same functionality by using HTML, CSS and JavaScript. Here is a possible working solution. The explanation follows.

enter image description here


Code:

var expanded = false;

function showCheckboxes() {
  var checkboxes = document.getElementById("checkboxes");
  if (!expanded) {
    checkboxes.style.display = "block";
    expanded = true;
  } else {
    checkboxes.style.display = "none";
    expanded = false;
  }
}
.multiselect {
  width: 200px;
}

.selectBox {
  position: relative;
}

.selectBox select {
  width: 100%;
  font-weight: bold;
}

.overSelect {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
}

#checkboxes {
  display: none;
  border: 1px #dadada solid;
}

#checkboxes label {
  display: block;
}

#checkboxes label:hover {
  background-color: #1e90ff;
}
<form>
  <div class="multiselect">
    <div class="selectBox" onclick="showCheckboxes()">
      <select>
        <option>Select an option</option>
      </select>
      <div class="overSelect"></div>
    </div>
    <div id="checkboxes">
      <label for="one">
        <input type="checkbox" id="one" />First checkbox</label>
      <label for="two">
        <input type="checkbox" id="two" />Second checkbox</label>
      <label for="three">
        <input type="checkbox" id="three" />Third checkbox</label>
    </div>
  </div>
</form>

Explanation:

At first we create a select element that shows text "Select an option", and empty element that covers (overlaps) the select element (<div class="overSelect">). We do not want the user to click on the select element - it would show an empty options. To overlap the element with other element we use CSS position property with value relative | absolute.

To add the functionality we specify a JavaScript function that is called when the user clicks on the div that contains our select element (<div class="selectBox" onclick="showCheckboxes()">).

We also create div that contains our checkboxes and style it using CSS. The above mentioned JavaScript function just changes <div id="checkboxes"> value of CSS display property from "none" to "block" and vice versa.

The solution was tested in the following browsers: Internet Explorer 10, Firefox 34, Chrome 39. The browser needs to have JavaScript enabled.


More information:

CSS positioning

How to overlay one div over another div

http://www.w3schools.com/css/css_positioning.asp

CSS display property

http://www.w3schools.com/cssref/pr_class_display.asp

Stephen Kennedy
  • 20,585
  • 22
  • 95
  • 108
vitfo
  • 9,781
  • 6
  • 29
  • 30
  • 2
    FYI: This solution will require more effort if the more than one select list is required to be modified. I suggest going in for some actively maintained plugin. –  Feb 13 '15 at 12:47
  • how to get the value of selected checkboxes ? Very good answer but it would be very helpfull if you provide plnkr or something like that. – Pardeep Jain Feb 01 '16 at 07:40
  • 9
    also to select box is not disappear when user select any options – Pardeep Jain Feb 01 '16 at 09:14
  • There is an issue with this. When you click on the drop down, the "Select an option" text hovers over First Check box unless you click somewhere else on app – Aiden Aug 10 '16 at 11:57
  • This solution doesn't work in my case if copied as is. The select box appears, however, I am not able to manipulate it. Also, the checkboxes appear outside the drop-down. – nader Oct 13 '17 at 16:32
  • 1
    This answer is great and it worked for me. There is however one improvement I made on it. Instead of the `overselect` div that could potentially cause some problems in a complex interface I used ``. It might not be the best use of `hidden` but it works. – Syknapse Apr 25 '18 at 08:24
  • 1
    Could we display the selected items? – CodeQuestor Aug 13 '18 at 14:42
  • 5
    but how to hide the dropdown, when we click outside? – saurabh kumar Nov 12 '18 at 08:05
  • `showCheckboxes()` is a very poor name for the function you use, because it inaccurately describes what the function does. The function actually *toggles* the visibility of the checkboxes. Thus, it would be *much* more appropriate to call it something like `toggleCheckboxesVisibility()`, or `toggleVisibilityCheckboxes()`. – Makyen Jul 15 '19 at 18:48
  • 1
    Any suggestions on how to count the checked checkboxes inside each select separately ? – ShashankAC May 18 '20 at 10:40
  • Thanks. I would like to avoid `overselect`. I see @Syknapse 's response above and I'm doing the same thing but it doesn't work. How can I get the default dropdown box to be completely gone when clicking on the select area? – McCrockett Jul 10 '20 at 22:59
  • a little thing, the styling must be done. – Muhammad Ali Sep 11 '21 at 07:26
75

The best plugin so far is Bootstrap Multiselect

EDIT: I wrote this a very long time ago. I would not recommend using jQuery anymore. You should rather learn a reactive framework like Vue.js, React, or Angular where you have plenty of modules to choose from. I'm sure you'll find what you need. I found this one for instance from a quick Google search.

<html xmlns="http://www.w3.org/1999/xhtml">
<head>

<title>jQuery Multi Select Dropdown with Checkboxes</title>

<link rel="stylesheet" href="css/bootstrap-3.1.1.min.css" type="text/css" />
<link rel="stylesheet" href="css/bootstrap-multiselect.css" type="text/css" />

<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.2.js"></script>
<script type="text/javascript" src="js/bootstrap-3.1.1.min.js"></script>
<script type="text/javascript" src="js/bootstrap-multiselect.js"></script>

</head>

<body>

<form id="form1">

<div style="padding:20px">

<select id="chkveg" multiple="multiple">
    
    <option value="cheese">Cheese</option>
    <option value="tomatoes">Tomatoes</option>
    <option value="mozarella">Mozzarella</option>
    <option value="mushrooms">Mushrooms</option>
    <option value="pepperoni">Pepperoni</option>
    <option value="onions">Onions</option>

</select>

<br /><br />

<input type="button" id="btnget" value="Get Selected Values" />

<script type="text/javascript">

$(function() {
    
    $('#chkveg').multiselect({
        
        includeSelectAllOption: true
    });
    
    $('#btnget').click(function(){
        
        alert($('#chkveg').val());
    });
});

</script>

</div>

</form>

</body>
</html>

Here's a demo:

$(function() {

  $('#chkveg').multiselect({
    includeSelectAllOption: true
  });

  $('#btnget').click(function() {
    alert($('#chkveg').val());
  });
});
.multiselect-container>li>a>label {
  padding: 4px 20px 3px 20px;
}
<link href="https://unpkg.com/bootstrap@3.3.2/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/jquery@3.3.1/dist/jquery.min.js"></script>
<script src="https://unpkg.com/bootstrap@3.3.2/dist/js/bootstrap.min.js"></script>
<script src="https://unpkg.com/bootstrap-multiselect@0.9.13/dist/js/bootstrap-multiselect.js"></script>
<link href="https://unpkg.com/bootstrap-multiselect@0.9.13/dist/css/bootstrap-multiselect.css" rel="stylesheet"/>

<form id="form1">
  <div style="padding:20px">

    <select id="chkveg" multiple="multiple">
      <option value="cheese">Cheese</option>
      <option value="tomatoes">Tomatoes</option>
      <option value="mozarella">Mozzarella</option>
      <option value="mushrooms">Mushrooms</option>
      <option value="pepperoni">Pepperoni</option>
      <option value="onions">Onions</option>
    </select>
    
    <br /><br />

    <input type="button" id="btnget" value="Get Selected Values" />
  </div>
</form>
pmrotule
  • 9,065
  • 4
  • 50
  • 58
  • 3
    You need not to use these much of libraries for your solution. You can just use regular HTML Multiple select option. Thanks! – Power Star Apr 13 '15 at 10:22
  • 6
    I know I can use HTML multiple select option, but I found it ugly and not user friendly. – pmrotule Apr 13 '15 at 20:26
  • 4
    I like this plugin's behaviour, but want to use it without bootstrap... anything similar? – singpolyma Feb 02 '16 at 20:38
  • 2
    this plugin is so buggy... they have 150 open issues and maintainer said that he doesn't have time. so after some issues I switched to the accepted answer and vue – Oleg Abrazhaev Nov 15 '17 at 16:56
  • 2
    @Erbureth The external script/stylesheet paths were outdated in the demo (dead links). I updated the urls to fix it. – pmrotule Mar 20 '18 at 07:28
  • Currently, this doesn't work, even the demo and code snippet generates errors. – Gustavo Rodríguez Nov 19 '21 at 12:51
  • @GustavoRodríguez Thanks for pointing it out. I updated the script and stylesheet paths to fix it (now using unpkg.com which should not break anytime soon). I also added a note since I wrote that 7 years ago and I would not recommend using jQuery anymore, but rather a reactive framework like Vue.js or React. – pmrotule Nov 20 '21 at 19:35
31

For a Pure CSS approach, you can use the :checked selector combined with the ::before selector to inline conditional content.

Just add the class select-checkbox to your select element and include the following CSS:

.select-checkbox option::before {
  content: "\2610";
  width: 1.3em;
  text-align: center;
  display: inline-block;
}
.select-checkbox option:checked::before {
  content: "\2611";
}

You can use plain old unicode characters (with an escaped hex encoding) like these:

Or if you want to spice things up, you can use these FontAwesome glyphs

Screenshot

Demo in jsFiddle & Stack Snippets

select {
  width: 150px;
}

.select-checkbox option::before {
  content: "\2610";
  width: 1.3em;
  text-align: center;
  display: inline-block;
}
.select-checkbox option:checked::before {
  content: "\2611";
}

.select-checkbox-fa option::before {
  font-family: FontAwesome;
  content: "\f096";
  width: 1.3em;
  display: inline-block;
  margin-left: 2px;
}
.select-checkbox-fa option:checked::before {
  content: "\f046";
}
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css">

<h3>Unicode</h3>
<select multiple="" class="form-control select-checkbox" size="5">
  <option>Dog</option>
  <option>Cat</option>
  <option>Hippo</option>
  <option>Dinosaur</option>
  <option>Another Dog</option>
</select>

<h3>Font Awesome</h3>
<select multiple="" class="form-control select-checkbox-fa" size="5">
  <option>Dog</option>
  <option>Cat</option>
  <option>Hippo</option>
  <option>Dinosaur</option>
  <option>Another Dog</option>
</select>

Note: Beware of IE compatibility issues however

KyleMit
  • 30,350
  • 66
  • 462
  • 664
  • 3
    It's a problem when the `multiple` attribute makes the ` – vsync Apr 17 '18 at 08:23
  • @vsync, can you elaborate on what problem you're having, maybe even fork the fiddle and include a screenshot. The goal here is to apply to a ` – KyleMit Apr 17 '18 at 15:02
  • 2
    Highly recommend this elegant solution if you're looking for a pure CSS approach. – Anish Sana Jun 18 '18 at 16:55
  • 2
    @KyleMit Nice solution !!! but the problem is if i want to select multiple items then i have to use the Ctrl button as like the simple select element. – Lalit Rajput Feb 12 '19 at 14:37
  • @LalitRajput, sure, that the default Interaction Design for all multiple select controls in all browsers. I agree that it's kind of wonky or unintuitive. You can always find ways to override that default behavior if you want per [How to avoid the need for ctrl-click in a multi-select box using Javascript?](https://stackoverflow.com/q/8641729/1366033) - see this [updated fiddle](https://jsfiddle.net/KyleMit/mqcp7f3s/413/) – KyleMit Feb 12 '19 at 18:41
  • I made something similar to this before I find this answer. Here it is if anyone needs it: https://codepen.io/sntran/pen/abbJXrP. The main difference is that it uses both pseudo-elements to style the checkbox and the label separately. Still having issue with IE11 ignoring pseudo-elements inside ` – Sơn Trần-Nguyễn Oct 23 '19 at 19:46
19

Try multiple-select, especially multiple-items. Looks to be much clean and managed solution, with tons of examples. You can also view the source.

<div>
  <div class="form-group row">
    <label class="col-sm-2">
      Basic Select
    </label>

    <div class="col-sm-10">
      <select multiple="multiple">
        <option value="1">1</option>
        <option value="2">2</option>
      </select>
    </div>
  </div>

  <div class="form-group row">
    <label class="col-sm-2">
      Group Select
    </label>

    <div class="col-sm-10">
      <select multiple="multiple">
        <optgroup label="Group 1">
          <option value="1">1</option>
          <option value="2">2</option>
        </optgroup>
        <optgroup label="Group 2">
          <option value="6">6</option>
          <option value="7">7</option>
        </optgroup>
        <optgroup label="Group 3">
          <option value="11">11</option>
          <option value="12">12</option>
        </optgroup>
      </select>
    </div>
  </div>
</div>

<script>
  $(function() {
    $('select').multipleSelect({
      multiple: true,
      multipleWidth: 60
    })
  })
</script>
Azghanvi
  • 934
  • 10
  • 22
10

Alternate Vanilla JS version with click outside to hide checkboxes:

let expanded = false;
const multiSelect = document.querySelector('.multiselect');

multiSelect.addEventListener('click', function(e) {
  const checkboxes = document.getElementById("checkboxes");
    if (!expanded) {
    checkboxes.style.display = "block";
    expanded = true;
  } else {
    checkboxes.style.display = "none";
    expanded = false;
  }
  e.stopPropagation();
}, true)

document.addEventListener('click', function(e){
  if (expanded) {
    checkboxes.style.display = "none";
    expanded = false;
  }
}, false)

I'm using addEventListener instead of onClick in order to take advantage of the capture/bubbling phase options along with stopPropagation(). You can read more about the capture/bubbling here: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

The rest of the code matches vitfo's original answer (but no need for onclick() in the html). A couple of people have requested this functionality sans jQuery.

Here's codepen example https://codepen.io/davidysoards/pen/QXYYYa?editors=1010

davidysoards
  • 309
  • 2
  • 7
9

I started from @vitfo answer but I want to have <option> inside <select> instead of checkbox inputs so i put together all the answers to make this, there is my code, I hope it will help someone.

$(".multiple_select").mousedown(function(e) {
    if (e.target.tagName == "OPTION") 
    {
      return; //don't close dropdown if i select option
    }
    $(this).toggleClass('multiple_select_active'); //close dropdown if click inside <select> box
});
$(".multiple_select").on('blur', function(e) {
    $(this).removeClass('multiple_select_active'); //close dropdown if click outside <select>
});
 
$('.multiple_select option').mousedown(function(e) { //no ctrl to select multiple
    e.preventDefault(); 
    $(this).prop('selected', $(this).prop('selected') ? false : true); //set selected options on click
    $(this).parent().change(); //trigger change event
});

 
 $("#myFilter").on('change', function() {
      var selected = $("#myFilter").val().toString(); //here I get all options and convert to string
      var document_style = document.documentElement.style;
      if(selected !== "")
        document_style.setProperty('--text', "'Selected: "+selected+"'");
      else
        document_style.setProperty('--text', "'Select values'");
 });
:root
{
 --text: "Select values";
}
.multiple_select
{
 height: 18px;
 width: 90%;
 overflow: hidden;
 -webkit-appearance: menulist;
 position: relative;
}
.multiple_select::before
{
 content: var(--text);
 display: block;
  margin-left: 5px;
  margin-bottom: 2px;
}
.multiple_select_active
{
 overflow: visible !important;
}
.multiple_select option
{
 display: none;
    height: 18px;
 background-color: white;
}
.multiple_select_active option
{
 display: block;
}

.multiple_select option::before {
  content: "\2610";
}
.multiple_select option:checked::before {
  content: "\2611";
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="myFilter" class="multiple_select" multiple>
  <option>A</option>
  <option>B</option>
  <option>C</option>
  <option>D</option>
  <option>E</option>
</select>
pavelbere
  • 964
  • 10
  • 21
3

Use this code for checkbox list on option menu.

.dropdown-menu input {
   margin-right: 10px;
}   
<div class="btn-group">
    <a href="#" class="btn btn-primary"><i class="fa fa-cogs"></i></a>
    <a href="#" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
      <span class="caret"></span>
    </a>
    <ul class="dropdown-menu" style="padding: 10px" id="myDiv">
        <li><p><input type="checkbox" value="id1" > OA Number</p></li>
        <li><p><input type="checkbox" value="id2" >Customer</p></li>
        <li><p><input type="checkbox" value="id3" > OA Date</p></li>
        <li><p><input type="checkbox" value="id4" >Product Code</p></li>
        <li><p><input type="checkbox" value="id5" >Name</p></li>
        <li><p><input type="checkbox" value="id6" >WI Number</p></li>
        <li><p><input type="checkbox" value="id7" >WI QTY</p></li>
        <li><p><input type="checkbox" value="id8" >Production QTY</p></li>
        <li><p><input type="checkbox" value="id9" >PD Sr.No (from-to)</p></li>
        <li><p><input type="checkbox" value="id10" > Production Date</p></li>
        <button class="btn btn-info" onClick="showTable();">Go</button>
    </ul>
</div>
KyleMit
  • 30,350
  • 66
  • 462
  • 664
Rupesh Wankhede
  • 457
  • 5
  • 16
  • For a fully fleshed out example on this basic approach of building a `dropdown-menu` with checkbox elements in each row, here's an answer for [putting checkboxes in a Bootstrap dropdown](https://stackoverflow.com/a/52517790/1366033) – KyleMit Sep 26 '18 at 12:34
  • read the question again, it is in the dropdown. not a list. – Muhammad Ali Sep 11 '21 at 07:28
2

You can use this library on git for this purpose https://github.com/ehynds/jquery-ui-multiselect-widget

for initiating the selectbox use this

    $("#selectBoxId").multiselect().multiselectfilter();

and when you have the data ready in json (from ajax or any method), first parse the data & then assign the js array to it

    var js_arr = $.parseJSON(/*data from ajax*/);
    $("#selectBoxId").val(js_arr);
    $("#selectBoxId").multiselect("refresh");
Jaya Parwani
  • 167
  • 1
  • 6
1

You might be loading multiselect.js file before the option list updated with AJAX call so while execution of multiselect.js file there is empty option list is there to apply multiselect functionlaity. So first update the option list by AJAX call then initiate the multiselect call you will get the dropdown list with the dynamic option list.

Hope this will help you out.

Multiselect dropdown list and related js & css files

// This function should be called while loading page
var loadParentTaskList = function(){
    $.ajax({
        url: yoururl,
        method: 'POST',
        success: function(data){
            // To add options list coming from AJAX call multiselect
            for (var field in data) {
                $('<option value = "'+ data[field].name +'">' + data[field].name + '</option>').appendTo('#parent_task');
            }
   
            // To initiate the multiselect call 
            $("#parent_task").multiselect({
                includeSelectAllOption: true
            })
        }
    });
}
// Multiselect drop down list with id parent_task
<select id="parent_task" multiple="multiple">
</select>
clearlight
  • 12,255
  • 11
  • 57
  • 75
1

You can try Bootstrap-select. It has a live search too!

saee
  • 433
  • 1
  • 3
  • 15
0

If you want to create multiple select dropdowns in the same page:

.multiselect {
  width: 200px;
}

.selectBox {
  position: relative;
}

.selectBox select {
  width: 100%;
  font-weight: bold;
}

.overSelect {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
}

#checkboxes {
  display: none;
  border: 1px #dadada solid;
}

#checkboxes label {
  display: block;
}

#checkboxes label:hover {
  background-color: #1e90ff;
}

Html:

 <form>
<div class="multiselect">
<div class="selectBox" onclick="showCheckboxes()">
<select>
<option>Select an option</option>
</select>
<div class="overSelect"></div>
</div>
<div id="checkboxes">
<label for="one">
<input type="checkbox" id="one" />First checkbox</label>
<label for="two">
<input type="checkbox" id="two" />Second checkbox</label>
<label for="three">
<input type="checkbox" id="three" />Third checkbox</label>
</div>
</div>
<div class="multiselect">
<div class="selectBox" onclick="showCheckboxes()">
<select>
<option>Select an option</option>
</select>
<div class="overSelect"></div>
</div>
<div id="checkboxes">
<label for="one">
<input type="checkbox" id="one" />First checkbox</label>
<label for="two">
<input type="checkbox" id="two" />Second checkbox</label>
<label for="three">
<input type="checkbox" id="three" />Third checkbox</label>
</div>
</div>

</form>

Using Jquery:

 function showCheckboxes(elethis) {
        if($(elethis).next('#checkboxes').is(':hidden')){
            $(elethis).next('#checkboxes').show();
            $('.selectBox').not(elethis).next('#checkboxes').hide();  
        }else{
            $(elethis).next('#checkboxes').hide();
            $('.selectBox').not(elethis).next('#checkboxes').hide();
        }
 }
Ashish
  • 174
  • 2
  • 13
-2

Only add class create div and add class form-control. iam use JSP,boostrap4. Ignore c:foreach.

<div class="multi-select form-control" style="height:107.292px;">
        <div class="checkbox" id="checkbox-expedientes">
            <c:forEach var="item" items="${postulantes}">
                <label class="form-check-label">
                    <input id="options" class="postulantes" type="checkbox" value="1">Option 1</label>
            </c:forEach>
        </div>
    </div>