Styled Popup Menu

This idea is from Veer.com and how they handle the dropdowns for things like T-Shirt sizes. Thank you to Dennis Sa.

View Demo

HTML

We'll wrap a regular text input inside an <div>, which also contains an unordered list which will represent the values for the popup menu.

<div class="size">
	<input type="text" name="test" value="choose your size" class="field" readonly="readonly" />
	<ul class="list">
		<li>Male - M</li>
		<li>Female - M</li>
		<li>Male - S</li>
		<li>Female - S</li>
	</ul>
</div>

CSS

The lists will be hidden by default, but still all styled up and ready to go when a click triggers them to be shown.

.size { position:relative }
.size .field {
	width:300px; background:#EC6603; color:#fff; padding:5px; border:none; cursor:pointer;
	font-family:'lucida sans unicode',sans-serif; font-size:1em;
	border:solid 1px #EC6603;
	-webkit-transition: all .4s ease-in-out;
	transition: all .4s ease-in-out;
}
.size .field:hover {
	border:solid 1px #fff;
	-moz-box-shadow:0 0 5px #999; -webkit-box-shadow:0 0 5px #999; box-shadow:0 0 5px #999
}
.size>ul.list { display:none;
	position:absolute; left:30px; top:-30px; z-index:999;
	width:300px;
	margin:0; padding:10px; list-style:none;
	background:#fff; color:#333;
	-moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px;
	-moz-box-shadow:0 0 5px #999; -webkit-box-shadow:0 0 5px #999; box-shadow:0 0 5px #999
}
.size>ul.list li {
	padding:10px;
	border-bottom: solid 1px #ccc;
}
.size>ul.list li:hover {
	background:#EC6603; color:#fff;
}
.size>ul.list li:last-child { border:none }

jQuery

We'll throw a quick plugin together, so that this functionality can be called on any div wrapper that contains this same HTML setup.=

(function($){
	$.fn.styleddropdown = function(){
		return this.each(function(){
			var obj = $(this)
			obj.find('.field').click(function() { //onclick event, 'list' fadein
			obj.find('.list').fadeIn(400);
			
			$(document).keyup(function(event) { //keypress event, fadeout on 'escape'
				if(event.keyCode == 27) {
				obj.find('.list').fadeOut(400);
				}
			});
			
			obj.find('.list').hover(function(){ },
				function(){
					$(this).fadeOut(400);
				});
			});
			
			obj.find('.list li').click(function() { //onclick event, change field value with selected 'list' item and fadeout 'list'
			obj.find('.field')
				.val($(this).html())
				.css({
					'background':'#fff',
					'color':'#333'
				});
			obj.find('.list').fadeOut(400);
			});
		});
	};
})(jQuery);

Usage

Then we just call the plugin, when the DOM is ready of course.

$(function(){
	$('.size').styleddropdown();
});

Comments

  1. User Avatar
    Hendra
    Permalink to comment#

    This is a really nice plugin. I just wonder if there’s a way to do it with select element.

    Then use jQuery to convert the select element into the above markups. Is it possible?

    • User Avatar
      Chris Coyier
      Permalink to comment#

      You could probably do it with the select element as well. It would take some extra special tweaking though. Instead of an input like there is now, it would have to just be a div or something. When JavaScript is loaded, it would make a UL out of the select element, but keep both it and the select hidden. Then when you click the div, it would show the UL like it does now, and when an list item is clicked, it would set the text of the div to show the choice AND change the value of the hidden select element. A bit more complicated but doable and probably a better choice in fallback scenarios.

  2. User Avatar
    Mike Richards
    Permalink to comment#

    The demo is broken because of a typo in the closing title tag.

    This sounds really interesting, I’ll be trying to integrate it into my next design.

  3. User Avatar
    zara
    Permalink to comment#

    just a minor:

    ===
    var obj = $(this)
    ===
    instead of
    obj = $(this)

    aloows you to have multiple elements…

    kr, tara

  4. User Avatar
    Ross
    Permalink to comment#

    doesn’t work in IE6 of course…

    (do people still code for IE6?)

  5. User Avatar
    John Valis
    Permalink to comment#

    thanks a lot, for sharing such an informative post. All i have learned from your code is the keyup,keydown event handling. thanks

  6. User Avatar
    mdennisa
    Permalink to comment#

    Thx Chris, for featuring the snippet.
    @John Valis , I somehow thought that key-event might be useful :)

  7. User Avatar
    Ricardo
    Permalink to comment#

    Wonderful effect, I always thought I would need to tweak an option field to acheive this styling. In mobile sites this should prove to be a valuable UX addition. On the other hand, I would recommend adding the unselectable=”on” property to the input.

    If you test this on IE 7/8, you’ll get the blinking cursor even underneath the list, and adding that property makes sure it goes away.

    Thanks!

  8. User Avatar
    Asif

    I’m trying to add multiple selectboxes but it’s js not working properly.

  9. User Avatar
    al-jerreau

    Nice one, but would be much cooler if it had keyboard support :-) like the mac style popup though, keep up the good work

  10. User Avatar
    James
    Permalink to comment#

    Is it just me, or does this break if you make the .size class anything with a hyphen in it? If I change all references to .size to say .tool-tip for example, nothing works.

  11. User Avatar
    nz warrior
    Permalink to comment#

    got this working and used this on the toolbar in magento 1.5.1.0 (using jq 1.4.2) ….

    Used for both the “sort by” and “show per page” pagination.

    For two instances add this to jquery with no conflict (you may need to change the selector jQuery() to $() )

    
    		jQuery(function(){
            jQuery('.size').styleddropdown();
            });
    		
    				jQuery(function(){
            jQuery('.sizeshow').styleddropdown();
            });
    

    added/changed jquery so i had a preloader for when a link was clicked (uses the magento checkout preloader!)

    (add this to the file template/page/html/head.phtml)

    
    <script type="text/javascript">
    (function($){
            $.fn.styleddropdown = function(){
                    return this.each(function(){
                           var obj = $(this)
                            obj.find('.field').click(function() { //onclick event, 'list' fadein
                            obj.find('.list').fadeIn(400);
    
                            $(document).keyup(function(event) { //keypress event, fadeout on 'escape'
                                    if(event.keyCode == 27) {
                                    obj.find('.list').fadeOut(400);
                                    }
                            });
    
                            obj.find('.list').hover(function(){ },
                                    function(){
                                            $(this).fadeOut(400);
                                    });
                            });
    
                            obj.find('.list li').click(function() { //onclick event, change field value with selected 'list' item and fadeout 'list'
                            obj.find('.field')
                                    
                                    .css({
                                            'background':'#fff url(<?php echo $this->getSkinUrl() ?>images/opc-ajax-loader.gif) no-repeat right',
                                            'color':'#333'
                                    });
                            obj.find('.list').fadeOut(400);
                            });
                    });
            };
    })(jQuery);
    </script>
    

    added this to the css ( used to fix bug in second instance )

    
    .size { position:relative }
    .size .field {
            width:300px; background:#EC6603; color:#fff; padding:5px; border:none; cursor:pointer;
            font-family:'lucida sans unicode',sans-serif; font-size:1em;
            border:solid 1px #EC6603;
            -webkit-transition: all .4s ease-in-out;
            transition: all .4s ease-in-out;
    }
    .size .field:hover {
            border:solid 1px #fff;
            -moz-box-shadow:0 0 5px #999; -webkit-box-shadow:0 0 5px #999; box-shadow:0 0 5px #999
    }
    .size>ul.list { display:none;
            position:absolute; left:30px; top:-30px; z-index:999;
            width:300px;
            margin:0; padding:10px; list-style:none;
            background:#fff; color:#333;
            -moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px;
            -moz-box-shadow:0 0 5px #999; -webkit-box-shadow:0 0 5px #999; box-shadow:0 0 5px #999
    }
    .size>ul.list li a {
            padding:10px;
            border-bottom: solid 1px #ccc;width:90%;text-decoration:none;
    }
    .size>ul.list li a:hover {
            background:#ff8000; color:#fff;width:90%;text-decoration:none;
    }
    .size>ul.list li a:last-child { border:none }
    
    .sizeshow { position:relative }
    .sizeshow .field {
            width:120px; background:#EC6603; color:#fff; padding:5px; border:none; cursor:pointer;
            font-family:'lucida sans unicode',sans-serif; font-size:1em;
            border:solid 1px #EC6603;
            -webkit-transition: all .4s ease-in-out;
            transition: all .4s ease-in-out;
    }
    .sizeshow .field:hover {
            border:solid 1px #fff;
            -moz-box-shadow:0 0 5px #999; -webkit-box-shadow:0 0 5px #999; box-shadow:0 0 5px #999
    }
    .sizeshow>ul.list { display:none;
            position:absolute; left:30px; top:-30px; z-index:999;
            width:300px;
            margin:0; padding:10px; list-style:none;
            background:#fff; color:#333;
            -moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px;
            -moz-box-shadow:0 0 5px #999; -webkit-box-shadow:0 0 5px #999; box-shadow:0 0 5px #999
    }
    .sizeshow>ul.list li a {
            padding:10px;
            border-bottom: solid 1px #ccc;width:90%;text-decoration:none;font-size:14px;display:inline-block;vertical-align:middle;
    }
    .sizeshow>ul.list li a:hover {
            background:#ff8000; color:#fff;width:90%;text-decoration:none;font-size:14px;padding:10px;display:inline-block;vertical-align:middle;
    }
    .sizeshow>ul.list li a:last-child { border:none } 
    

    once the sucussefully loaded the jquery & css are in place

    ..I then edited template/catalog/product/list/toolbar.phtml with…

    commentted out lines 53 to 65 using and paste this code inbetween the div class “sort-by”…

    (all based on the “sort” config (found in system->configuration->catalog) is set in the admin – so set/match paramiters as saved in admin)

    
    <div class="size">
    			<input type="text" unselectable="on" name="test" value="sort page by..." class="field" readonly="readonly" />
    			<ul class="list">
    			
    <li> <a href="<?php echo $this->getCurrentUrl() ?>?dir=asc&order=position">Position</a></li>
    <li> <a href="<?php echo $this->getCurrentUrl() ?>?dir=asc&order=name">Name</a></li>
    <li> <a href="<?php echo $this->getCurrentUrl() ?>?dir=asc&order=price">Price</a></li>
    <li> <a href="<?php echo $this->getCurrentUrl() ?>?dir=asc&order=created_at">Newest</a></li>
    <li> <a href="<?php echo $this->getCurrentUrl() ?>?dir=asc&order=updated_at">Last Updated</a></li>
                			
                </ul>
    			</div>
    

    and also on lines 70 to 77 comment them out via <!– –>

    and in the div class “limiter” place this code….

    (all based on the “sort” config (found in system->configuration->catalog) is set in the admin – so set/match paramiters as saved in admin)

    
    <div class="sizeshow">
    			<input type="text" unselectable="on" name="test" value="show per page..." class="field" readonly="readonly" />
    			<ul class="list">
    			
    <li> <a href="<?php echo $this->getCurrentUrl() ?>?limit=5">5</a></li>
    <li> <a href="<?php echo $this->getCurrentUrl() ?>?limit=10">10</a></li>
    <li> <a href="<?php echo $this->getCurrentUrl() ?>?limit=15">15</a></li>
    <li> <a href="<?php echo $this->getCurrentUrl() ?>?limit=20">20</a></li>
    <li> <a href="<?php echo $this->getCurrentUrl() ?>?limit=25">25</a></li>
    <li> <a href="<?php echo $this->getCurrentUrl() ?>?limit=all">All</a></li>
                			
                </ul>
    			</div>
     

    performs how what i wanted

    • User Avatar
      Sergey
      Permalink to comment#

      Have you ever heard that in PHP you can use loops (like ‘for’ and ‘while’) too?

      So instead of this:

      <a href="getCurrentUrl() ?>?limit=5">5
      <a href="getCurrentUrl() ?>?limit=10">10
      <a href="getCurrentUrl() ?>?limit=15">15
      <a href="getCurrentUrl() ?>?limit=20">20
      <a href="getCurrentUrl() ?>?limit=25">25
      <a href="getCurrentUrl() ?>?limit=all">All

      you could write something like this:

      <?php printf("%s", $this->getCurrentUrl(), $limit, ucfirst("$limit")) ?>

  12. User Avatar
    Yousef
    Permalink to comment#

    How to assign actions when an option is selected ?

  13. User Avatar
    bdubbs
    Permalink to comment#

    I’m having an issue with this in iOS Safari. The issue is there is no way to close the menu once it’s opened. Is there a solution to this? Thanks!

  14. User Avatar
    Umang Goyal

    I am not able to create two simultaneous styledropdown with different set of values on same page..
    Could you please provide me the working example for this?
    Also the code for two styledropdrown mentioned above in the comments is not working

    Thanks,
    Umang

  15. User Avatar
    Satyam
    Permalink to comment#

    great!

Submit a Comment

Posting Code

You may write comments in Markdown. This makes code easy to post, as you can write inline code like `<div>this</div>` or multiline blocks of code in triple backtick fences (```) with double new lines before and after.

Code of Conduct

Absolutely anyone is welcome to submit a comment here. But not all comments will be posted. Think of it like writing a letter to the editor. All submitted comments will be read, but not all published. Published comments will be on-topic, helpful, and further the discussion or debate.

Want to tell us something privately?

Feel free to use our contact form. That's a great place to let us know about typos or anything off-topic.

icon-anchoricon-closeicon-emailicon-linkicon-logo-staricon-menuicon-nav-guideicon-searchicon-staricon-tag