Grow your CSS skills. Land your dream job.

Last updated on:

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. 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?

    • 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. 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. Permalink to comment#

    just a minor:

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

    aloows you to have multiple elements…

    kr, tara

  4. Ross
    Permalink to comment#

    doesn’t work in IE6 of course…

    (do people still code for IE6?)

  5. 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. mdennisa
    Permalink to comment#

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

  7. 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. Asif

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

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

  10. 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. 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

    • 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. Yousef
    Permalink to comment#

    How to assign actions when an option is selected ?

  13. 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. 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

Leave a Comment

Current ye@r *

*May or may not contain any actual "CSS" or "Tricks".