161

How can you programmatically tell an HTML select to drop down (for example, due to mouseover)?

5
  • 7
    I'd recommend not screwing with the behavior of the default <select>, as people expect it to behave a certain way and you'll be preventing people on other platforms (like mobile) from using your site. Commented Dec 26, 2010 at 23:47
  • We shouldn't be doing this anymore. stackoverflow.com/a/39635285/4015856 Commented Oct 9, 2017 at 6:34
  • Well now it's 2020, but for someone who is still struggling to get this thing to work, html nativeElements have methods that can be used to do exactly these kind of things, & has a method called click() which simulates a mouse click on an element, this can be used in javascript - referenced from w3schools.com/jsref/dom_obj_all.asp Commented Apr 20, 2020 at 4:43
  • @Hasintha Abeykoon calling click on a <select> element does not open it in Chrome 109 Commented Mar 20, 2023 at 6:23
  • Have a look at Caleb Hillary's answer stackoverflow.com/a/68036061/5263950 . Works perfectly in 2024 with several browers, even with old Interne Explorer. Preserves CSS styles, native focusability and keyboard navigation. Does not require any CSS. Commented Jan 26, 2024 at 19:36

20 Answers 20

129
+50

This used to actually be possible with HTML+Javascript, despite everywhere else people say it is not, but it was deprecated later on and does not work now.

However, this only worked in Chrome. Read more if you're interested.


According to W3C Working Draft for HTML5, Section 3.2.5.1.7. Interactive Content:

Certain elements in HTML have an activation behavior, which means that the user can activate them. This triggers a sequence of events dependent on the activation mechanism [...] for instance using keyboard or voice input, or through mouse clicks.

When the user triggers an element with a defined activation behavior in a manner other than clicking it, the default action of the interaction event must be to run synthetic click activation steps on the element.

<select> being an Interactive Content, I believed that it is possible to programatically display its <option>s. After a few hours of playing around, I discovered that using document.createEvent() and .dispatchEvent() works.

That said, demo time. Here is a working Fiddle.

// <select> element displays its options on mousedown, not click. showDropdown = function(element) { var event; event = document.createEvent('MouseEvents'); event.initMouseEvent('mousedown', true, true, window); element.dispatchEvent(event); }; // This isn't magic. window.runThis = function() { var dropdown = document.getElementById('dropdown'); showDropdown(dropdown); };
<select id="dropdown"> <option value="Red">Red</option> <option value="Green">Green</option> <option value="Blue">Blue</option> </select> <br> <button id="fire" type="button" onclick="runThis()">Show dropdown items</button>​

If anyone finds a way to do the same but not in Chrome, please feel free to modify this fiddle. ​

Sign up to request clarification or add additional context in comments.

9 Comments

I am saddened to report that while this method does appear to work in Android webviews (e.g. Phonegap), the same can not be said for iOS. As of 2013-07-25, tested on iOS6 and Android 4.2.2.
Not working on: IE10, FF 24. Works on: Chrome 30, Safari 6.0.5, Opera 16
@AdamTuttle It does not work on Android 4.4.2 either
@Hernant_Negi initMouseEvent() is Deprecated developer.mozilla.org/en-US/docs/Web/API/MouseEvent/…
It is now deprecated on Chrome 53+
|
54

Xavier Ho's answer is covering how to solve the issue in most browsers currently out there. But, it's good practice 'not to dispatch/modify' events by JavaScript anymore. (Like, mousedown in this case)

From version 53+, Google Chrome will not perform default action for un-trusted events. Such as events created or modified by script, or dispatched via dispatchEvent method. This change is for aligning with Firefox and IE which I think already not performing the action.

For testing purposes, Fiddle provided Xavier's answer won't work in chrome 53+. (I don't test it FF and IE).

Links for reference:

https://www.chromestatus.com/features/5718803933560832 https://www.chromestatus.com/features/6461137440735232

And initMouseEvent is also deprecated

Comments

50

I have this same problem and the easier way I found to solve this was with HTML and CSS.

First, make you <select> transparent (opacity: 0;). Then, place your button over the <select>. The click over the button will be caught by the <select> component.

select{ opacity: 0; position: absolute; } select:hover~button { background: orange; } div * { width: 100px; }
<div> <select> <option>option 1</option> <option>option 2</option> <option>option 3</option> </select> <button>click</button> </div>

6 Comments

Been a long time since I've seen this approach, and is the reference I was hoping to find. Better with extra CSS to match hidden select's size to trigger (button, img, div, etc)... 1) Ensures clickable region fills trigger 2) Menu opens directly below trigger. Note: Might also need to add a z-index to ensure the clickable region is the top-most element in some layouts.
however, if the user scrolls down the page, then the button moves accordingly but the select keeps at the same position; not really as expected. any solution for this?
Perfect solution. But better maybe wrap button and select on div like this <div style='position:relative'><select> <option>option 1</option> <option>option 2</option> <option>option 3</option> </select> <button>click</button></div> @DavidPortabella
Any idea how to get a hover effect on the <button> with this technique?
@MattKleinsmith, I edited the style to get a :hover effect on the button. I used this as a reference stackoverflow.com/questions/54974024/…
|
42

This is the closest I could get, change the size of the element onmouseover, and restore the size onmouseout:

<select onMouseOut="this.size=1;" onMouseOver="this.size=this.length;"> <option>1</option> <option>2</option> <option>3</option> <option>4</option> <option>5</option> </select>

5 Comments

or <SELECT onMouseOut="this.size=1;" onMouseOver="this.size=this.length;"> ... </SELECT>
Also need to add onchange="this.size=1" so that the menu collapses as soon as selection is made. The element's CSS rules need to be configured as well.
It seems to work. The select width shrinks and then that causes a mouse out event reseting the select to it's original width. This causes a seizure effect. Setting a fixed width seems to fix it. With more than a few items the list expands past the view.
Don't do this if you have mobile visitors. Some popular smartphone browsers don't honour the size attribute, see stackoverflow.com/questions/43077171/…
Good solution for its simplicity. If you have more advanced needs, look at the solution provided by Caleb Hillary, which was the best for me: stackoverflow.com/a/68036061/5263950 . Another decent solution for those wanting to style their droplists is here: cssscript.com/select-styleable-dropdown-selectal It preserves some native look of the drop list. A basic setup is easy to configure, but does not allow proper keyboard navigation and will kill the CSS styles or your droplist, although you can easily set them again by modifying the provided stylesheet.
24

You can use the new showPicker() method:

if ("showPicker" in HTMLSelectElement.prototype) { document.querySelector('button').addEventListener('click', function() { document.querySelector('select').showPicker(); }); } 

4 Comments

Now supported on Firefox and all major browsers
Worked on Safari and Brave browser!
No, in the current version 18.6 (20621.3.11.11.3) of Safari for macOS, there is no showPicker method on select elements. Also, developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/… reports it as only available in Safari Technology Preview. I find that the method outlined in stackoverflow.com/a/77333229/2416627 works as a fallback solution in Safari for Mac (i.e., if there is no showPicker method, dispatch a mouse event instead).
2025: Works fine in all Chromium browsers and latest Firefox, does not work in Safari v26.1
19

You can't do this with a HTML select tag, but you can do it with JavaScript and HTML. There are variety of existing controls that do this - for instance, the "suggest" list attached to the SO "interesting/ignored tag" entry, or Gmail's lookup for email adresses.

There are many JavaScript+HTML controls that provide this capability--look for autocomplete controls for ideas.

See this link for the Autocomplete control...http://ajaxcontroltoolkit.codeplex.com/

Comments

8

I think this is no longer possible in Chrome.

It seems version 53 of chrome disables this functionality as stated by Asim K T.

According to the spec http://www.w3.org/TR/DOM-Level-3-Events/#trusted-events

Trusted Events should not fire the default action (except click event).

They have however enabled it in webview, but I have not tested this.

We have found that some webviews are using fastclick inside them and due to a risk of breakage we are going to allow mousedown on selects even if they are untrusted.

And in this discussion the idea to let developers open a dropdown programatically is abandoned.

Comments

7

If any one is still looking for this :

<select id="dropdown"> <option value="Red">Red</option> <option value="Green">Green</option> <option value="Blue">Blue</option> </select> <br> <button id="fire" type="button" >Show dropdown items</button> 

Javascript:

var is_visible=false; $(document).ready(function(){ $('#fire').click(function (e) { var element = document.getElementById('dropdown'); if(is_visible){is_visible=false; return;} is_visible = true; var event; event = document.createEvent('MouseEvents'); event.initMouseEvent('mousedown', true, true, window); element.dispatchEvent(event); /* can be added for i.e. compatiblity. optionsSelect.focus(); var WshShell = new ActiveXObject("WScript.Shell"); WshShell.SendKeys("%{DOWN}"); */ e.stopPropagation(); return false; }); $(document).click(function(){is_visible=false; }); }); 

Update:

One till there is no perfect solution to this problem, But you can try to avoid this scenario. Why do you want to do this. i was wondering for a solution few months back to make a select plugin for mobile devices

https://github.com/HemantNegi/jquery.sumoselect

Finally ended up with masking the custom div (or any other element) with a transparent select element, so that it can directly interacts with user.

2 Comments

Plugins like github.com/HemantNegi/jquery.sumoselect are the only cross-browser solution that actually look better than the default control.
iniMouseEvent seems to work, but why does $(select).trigger('mousedown') doesn't work ?
3

Here's the best way I found. NOTE It only works with IE on Windows and your web would probably need to be in a secure zone - because we access the shell. The trick is that ALT-Down Arrow is a shortcut key to open a select drop down.

<button id="optionsButton" style="position:absolute;top:10px;left:10px;height:22px;width:100px;z-index:10" onclick="doClick()">OPTIONS</button> <select id="optionsSelect" style="position:absolute;top:10px;left:10px;height:20px;width:100px;z-index:9"> <option>ABC</option> <option>DEF</option> <option>GHI</option> <option>JKL</option> </select> <script type="text/javascript"> function doClick() { optionsSelect.focus(); var WshShell = new ActiveXObject("WScript.Shell"); WshShell.SendKeys("%{DOWN}"); } </script> 

3 Comments

It won't work unless you do this.
@Knu Internet Explorer automatically adds the ID's of elements as references to the element to the global scope.
@KlasMellbourn probably. They're trying to make their browsers more compliant now. Use the "size" solution mentioned.
3

If anyone is still looking for this, This is how I solved it.

This is a solution based on the fact that the selection looks like it is expanded when the size in increased. We can increase size to make it look expanded. And reduce to make it seem closed. This way we can handle most use-cases by just having focus and blur listeners.

Select element needs to be absolutely positioned because increasing size will increase vertical height of element. If you have elements below, they will be pushed down if this is not done.

I have a wrapper code, that wraps the element and provides open and close methods.

Check this fiddle for usage: https://jsfiddle.net/10ar2ebd/16/

var SelectionWrapper = function(element, maxSize, selectCb) { var preventDefault = function(e) { e.preventDefault(); e.stopPropagation(); } var isOpen = false; var open = function() { if (!isOpen) { element.size = maxSize; // Remove prevent default so that user will be able to select the option // Check why we prevent it in the first place below element.removeEventListener('mousedown', preventDefault); // We focus so that we can close on blur. element.focus(); isOpen = true; } }; var close = function() { if (isOpen) { element.size = 1; // Prevent default so that the default select box open behaviour is muted. element.addEventListener('mousedown', preventDefault); isOpen = false; } }; // For the reason above element.addEventListener('mousedown', preventDefault); // So that clicking elsewhere closes the box element.addEventListener('blur', close); // Toggle when click element.addEventListener('click', function(e) { if (isOpen) { close(); // Call ballback if present if(selectCb) { selectCb(element.value); } } else { open(); } }); return { open: open, close: close }; }; // Usage var selectionWrapper = SelectionWrapper(document.getElementById("select_element"), 7, function(value) { var para = document.createElement("DIV"); para.textContent = "Selected option: " + value; document.getElementById("result").appendChild(para); }); document.getElementById("trigger").addEventListener('click', function() { selectionWrapper.open(); }); 

2 Comments

Excellent solution which should be much above in the stack. Tested as working with Brave (Chrome), Firefox, and even Internet Explorer 11. Pure Javascript, not requiring jQuery, nor any CSS. Elements preserve their original focusability and keyboard navigation, as well as their CSS styles. The SelectionWrapper() function can be used for different <select> drop lists. It is worth having a look at the code and demo at the provide link on jsfiddle. The script must be placed after the <select> list(s) and the element that triggers the dropdown (not necessarily ab button).
I like you solution but see a small drawback: I want a thin drop list, but the dropmenu to expand to the width required by the options. Example: for a regular <select style="max-width:3em;"> the droplist widens automatically. But with the wrapped list, it does not and its width stays at 3em. Any patch?
2

Here is the solution on https://jsfiddle.net/NickU/ahLy83mk/50/

It uses size="x" to open the dropdown while maintaining the dropdown and parent positions. The code also uses CSS styles to hide the right scroll area when it is not needed. I modified the code I found on stackoverflow, fixed the problems and added styling.

HTML:

<div>DIV example: <select id="dropdownDiv"> <option value="Alpha">Alpha</option> <option value="Beta">Beta</option> <option value="Gamma">Gamma</option> </select> </div> <table id='tab1'> <tr><td>Empty Cell</td></tr> <tr><td> <select id="dropdown1"> <option value="Red">Red</option> <option value="Green">Green</option> <option value="Blue">Blue</option> </select> </td> <tr><td><select id="dropdown2"> <option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option><option value="6">6</option><option value="7">7</option><option value="8">8</option><option value="9">9</option><option value="10">10</option><option value="11">11</option><option value="12">12</option><option value="13">13</option><option value="14">14</option><option value="15">15</option><option value="15">1</option><option value="16">16</option><option value="17">17</option><option value="18">18</option><option value="19">19</option><option value="20">20</option><option value="21">21</option></select> </td></tr> <tr><td>Empty Cell</td></tr></table> <br><button id="fire" type="button" onclick="openDropdown('dropdownDiv', this)" >Show dropdownDiv items</button> <button id="fire" type="button" onclick="openDropdown('dropdown1', this)" >Show dropdown1 items</button> <button id="fire" type="button" onclick="openDropdown('dropdown2', this)" >Show dropdown2 items</button> 

JavaScript:

 var lastClosedElem = null; var maxItemsInDropDown = 12; function openDropdown(elementId, opener) { if (lastClosedElem !== null && lastClosedElem === opener) { lastClosedElem = null; return; } lastClosedElem = opener; function down() { var $this = $(this); var td = $this.closest('td,div'); if (td && td.length > 0) td.height(td.height()); var pos = $this.offset(); var len = $this.find("option").length; if (len > 1 && len < maxItemsInDropDown) { $this.addClass('no-scroll'); $this.addClass('noArrow'); } else if (len > maxItemsInDropDown) { len = maxItemsInDropDown; } $this.css("position", "absolute"); var _zIndex = $this.css("zIndex"); if (!_zIndex) _zIndex = 'auto'; $this.attr("_zIndex", _zIndex); $this.css("zIndex", 9999); $this.attr("size", len); // open dropdown $this.unbind("focus", down); $this.focus(); } var up = function() { var $this = $(this); $this.css("position", "static"); $this.attr("size", "1"); $this.removeClass('no-scroll'); $this.removeClass('noArrow'); var _zIndex = $this.attr("zIndex"); if (_zIndex) { $this.css("zIndex", _zIndex); } $this.unbind("blur", up); $this.unbind("click", upClick); $this.focus(); } function upClick(e) { up.call(this); lastClosedElem = null; } $("#" + elementId).focus(down).blur(up).click(upClick).trigger('focus'); } 

CSS:

.no-scroll { cursor: pointer;} .no-scroll::-webkit-scrollbar {display:none;} .no-scroll::-moz-scrollbar {display:none;} .no-scroll::-o-scrollbar {display:none;} .no-scroll::-google-ms-scrollbar {display:none;} .no-scroll::-khtml-scrollbar {display:none;} .noArrow { -webkit-appearance: none; -moz-appearance: none; appearance: none; padding-left: 3px; padding-right: 3px; } /* Cosmetic styles */ #tab1 tbody tr:nth-child(even) > td, div { background: linear-gradient( 180deg, #efefef 1%, #eeeeee 15%, #e2e2e2 85%); } #tab1 tbody tr td { padding: 4px; } #tab1 { border: 1px solid silver; } 

Comments

0

I may be wrong, but I don't believe that is possible with the default select box. You could do something with JS & CSS that achieves the desired result, but not (to my knowledge) the vanilla SELECT.

Comments

0

This is not exactly what you asked for, but I like this solution for its simplicity. In most cases where I am wanting to initiate a dropdown, it is because I'm validating that the user has actually made a selection. I change the size of the dropdown and focus it, which nicely highlights what they've skipped:

$('#cboSomething')[0].size = 3; $('#cboSomething')[0].focus(); 

1 Comment

Not sure why you got down-voted as it's not the "worst" way to do it. I would avoid this simply because it shifts the layout of surrounding elements. Though I think the solution from @CMS is more easily understood with the focus/blur events at the control.
0

Opening an "HTML select" is possible through some workarounds mentioned in this question and similar ones. However a cleaner way of doing this is to add a select library to your project like "select2" or "chosen". For instance, opening a select2 programmatically would be as easy as:

$('#target-select').select2('open'); 

Comments

0

I've actually found a way to do it with plain javascript. According to MDN docs you have the showPicker method, but it only works with a user gesture.

So, with that said here's how we could achieve it in code:

function simulateMouseEvent( element, eventName, coordX, coordY ) { element.dispatchEvent( new MouseEvent(eventName, { view: window, bubbles: true, cancelable: true, clientX: coordX, clientY: coordY, button: 0 }) ); }; // The select menu's element const selectMenu = document.getElementById('mySelectMenu'); function openSelectMenu(selectMenu) { // Get the coordinates of where we want to click to simulate const box = selectMenu.getBoundingClientRect(), coordX = box.left + (box.right - box.left) / 2, coordY = box.top + (box.bottom - box.top) / 2; // According to MDN docs the showPicker function inside the HTMLSelectElement can only be activated by user gesture, so we simulate it here simulateMouseEvent(selectMenu, 'mousedown', coordX, coordY); simulateMouseEvent(selectMenu, 'mouseup', coordX, coordY); simulateMouseEvent(selectMenu, 'click', coordX, coordY); selectMenu.showPicker(); }
<select id="mySelectMenu"> <option>1</option> <option>2</option> <option>3</option> </select> <button onclick="openSelectMenu(selectMenu)">Open select menu</button>

NOTE: This won't work in the snippet due to it being in an iframe and causing a security error, try it locally :)

Hope this helps!

Comments

-1

No built-in function, but it could be mimicked in the following way.

Could require some fine-tunning if the styling is fancy, and after that it's fairly usable.

const openSelect = me => { me.size = me.length } const closeSelect = me => { me.size = 1 }
<button onclick="openSelect(models)">Open selector</button> <button onclick="closeSelect(models)">Close selector</button> <hr> <select id="models"><option value="SERIE 1">SERIE 1</option><option value="SERIE 3">SERIE 3</option><option value="SERIE 4">SERIE 4</option><option value="SERIE 5">SERIE 5</option><option value="SERIE 6">SERIE 6</option><option value="SERIE 7">SERIE 7</option><option value="SERIE I">SERIE I</option><option value="SERIE M">SERIE M</option><option value="SERIE X">SERIE X</option><option value="SERIE Z">SERIE Z</option></select>

1 Comment

BTW, this approach (bumping size attribute up to length with user action) seems to be proposed in this question more than once already, e.g. stackoverflow.com/a/249219/540955. Does this answer bring anything new to the topic here?
-1

A creative solution

// Options displayed initially

var showedOptions = document.querySelector("#select_pa_taglia").size; // at the beginning 0

// Total number of options available

var numberOfOptions = document.querySelector("#select_pa_taglia").length;

// Show all options

document.querySelector("#select_pa_taglia").size = numberOfOptions;

// Style reposition

document.querySelector("#select_pa_taglia").style.cssText = 'position:absolute; top: 0%; z-index:10;';

1 Comment

does not really answer the question and is going against usability standards
-2
<style> select{ overflow:hidden; } </style> <select id="select"> <option value="1">First option</option> <option value="2">Second second</option> <option value="3">Third option</option> </select> <script> select.size = select.length; select.onclick =()=> { select.size = 1; } </script> 

Comments

-3

I don't know if I'm fully understanding the question, but to open a dropdown, this simple approach worked for me.

You have an element:

<span onclick="openDropdown();">Open dropdown</span> 

You have a dropdown:

<select class="dropdown"> <option value="A">Value A</option> <option value="B">Value B</option> <option value="C">Value C</option> </select> 

And with JavaScript you can do the following:

document.querySelector('.dropdown').focus(); 

Comments

-3
let elSelected = null; function bindSelectClick(el){ if(el.target !== elSelected){ $(elSelected).trigger('blur'); $(document).unbind('click', bindSelectClick) } } $('select.shared_date').on('focus', function (){ // do something elSelected = this; $(document).on('click', bindSelectClick) }).on('blur', function (){ // do something }).on('change', function (){ // do something }) 

Select does not lose focus after its menu is closed. With a separate function, we check whether the click was on the select or elsewhere. If the elements are not equal, then you can fire some kind of event

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.