Create a dropdown using a list <ul>

Posted by _R on August 8, 2014 in CSS, Tutorials

We’ve all been there – that moment when you see your wonderful layout ending up with fugly default browser styling. If only all browsers would adopt the same styling for our dear HTML elements and let us add sparkles and colors. Ok, maybe not sparkles but at least style that darn dropdown. And please don’t get me started on mobile.

For one project I worked on, the only option I had was to not use <select> for the dropdown but style a list <ul> instead and make it look like the styled dropdown the client wanted – Dropdown Select Design This is the dropdown code using a <select> as we all know –

	<select>
		<option>Gummi Bears</option>
		<option>Tiramisu</option>
		<option>Carrot Cake</option>
		<option>Chocolate</option>
		<option>Jelly Beans</option>
		<option>Cotton Candy</option>
		<option>Marzipan</option>
		<option>Lollipop</option>
		<option>Fruitcake</option>
		<option>Donut</option>
	</select> 

First, let’s break down what are the parts of this module we’re creating. This will help us figure out what we’re dealing with as were transforming a simple list to a <select> dropdown and then adding some nice styling.

 

A simple list:

Select your favorite

  • Gummi Bears
  • Tiramisu
  • Carrot Cake
  • Chocolate
  • Jelly Beans
  • Cotton Candy
  • Marzipan
  • Lollipop
  • Fruitcake
  • Donut

The code:

    Select your favorite
	<ul>
		<li>Gummi Bears</li>
		<li>Tiramisu</li>
		<li>Carrot Cake</li>
		<li>Chocolate</li>
		<li>Jelly Beans</li>
		<li>Cotton Candy</li>
		<li>Marzipan</li>
		<li>Lollipop</li>
		<li>Fruitcake</li>
		<li>Donut</li>
	</ul>

 

We should be able to transform the above code to a dropdown with the following parts: dropdown guide

  1. Container
    • Our dropdown needs to be in a container where we can control the position of the  contents of a dropdown which we’ll set as …
  2. Trigger
    • This is the part of the dropdown that you click to show the list options available
  3. List options
    • The contents of the dropdown are the options available with the <select>

 

Right. So, first we write the markup we need –

<div class="dropdown">
	<a class="trigger">Select your favorite</a>
	<ul class="options">
		<li>Gummi Bears</li>
		<li>Tiramisu</li>
		<li>Carrot Cake</li>
		<li>Chocolate</li>
		<li>Jelly Beans</li>
		<li>Cotton Candy</li>
		<li>Marzipan</li>
		<li>Lollipop</li>
		<li>Fruitcake</li>
		<li>Donut</li>
	</ul>
</div>

 

  1. The container is thus a <div> with a class of dropdown.
  2. The trigger is an anchor <a> with a class of trigger
  3. The list options is a <ul> list with a class of options

 

Side note: You sure can just use class .dropdown for your CSS and not use the classes .trigger and .options. You’ll just have  the chains .dropdown a and .dropdown ul  to style the elements.

 

Container:

	.dropdown{
	     position:relative;
	     width:480px; height:38px;
 	}

We’ll add a specific width and height for our container to box up the contents. Set position:relative as we need to be able to control the contents inside with position as well. (You’ll see why later).

 

Trigger:

    .dropdown .trigger{	
	     background:#fff;
	     margin:0; padding:6px 10px;
	     display:block;
	     border:1px solid #9a9a9a;
	     text-align:left; cursor:pointer;
	}

My trigger is an anchor so I can use :hover selector for when the trigger is clicked. We’ll style it as above to set it as a block element to span the whole container (display:block;) nicely with a blue border, and added cursor:pointer;  so I can have that nice little hand when I hover the area and not just a default arrow pointer. Yes. Details, details.

 

Here’s something: The triangle is not an image (whoah) css triangle

Notice in the design that the regular dropdown arrow was replaced by a neat triangle arrow on the bottom right corner of the box. This is how we code that nice little thing:

Triangle as arrow on the bottom corner:

	.dropdown .trigger:after {
		content: ""; position:absolute; 
		top:26px; right:0; width:0; height:0;
		border-bottom:12px solid #2397e9;
		border-left:12px solid rgba(0, 0, 0, 0);
	}

It uses border styles to make the illusion that is has formed the triangle shape. Pretty neat. I recommend trying out combinations and see the shape that you’d create. (I’ll post another article about it).

It is then set after the trigger with an empty content and  has position:absolute to set it to bottom right. We are able to do that because we set position:relative for it’s parent container which is .dropdown; the triangle is positioned absolutely with respect to it’s parent. [ More about CSS position ]

 

The list 

Now we  work on our list items. We’re simply putting it all in a box, really. Add a background color change for when a list item is hovered.

	.dropdown .options{
	background:#f8f8f8;
	margin:0; padding:0;
	width:auto; list-style:none;	

	border-left:1px solid #2397e9;
	border-right:1px solid #2397e9;
	border-bottom:1px solid #2397e9;
	}	
		.dropdown .options li{
		margin:0; padding:6px 10px; text-align:left; 
		display:block; clear:both;
		cursor:pointer;		
		}	
			.dropdown .options li:hover{
			margin:0; padding:6px 10px; text-align:left; 
			background:#dedede;
			}

 

Here’s what our code will create. So far so good. dropdown list itemas

 

Hide the list

Of course we need to be able to hide and close this list. That’s how select works. In order to do that we’ll first need to hide the list items by default by adding the following to .options .

        .dropdown .options{
	    background:#f8f8f8;
	    margin:0; padding:0;
	    width:auto; list-style:none;	

	    visibility:hidden;   /* add this to hide the list items */

	    border-left:1px solid #2397e9;
	    border-right:1px solid #2397e9;
	    border-bottom:1px solid #2397e9;
        }

Resulting to – dropdown-list-hide

We need visibility:hidden to hide the whole list. It’s also good to point out that all the pudding muffin cotton candy content after .dropdown follows as it should and is not affected by the height of the list because .dropdown has a defined height and set to position:relative. [ More about CSS visibility ]    

 

Show the list

Our .trigger should, well, trigger  opening the list items of our dropdown. We can achieve this by setting visibility:visible to .options when the trigger is clicked or hovered.  To do this, we’ll use a the adjacent sibling combinator, the plus symbol (+); and it will work because .options is a sibling of .trigger . Tadah. [ More about adjacent sibling selectors ]

	.dropdown .trigger:hover + .options, 
	.dropdown .options:hover{ visibility:visible; }

 

Tidy up a bit

Just a little cleaning up then. We’ll add a maximum height for the list items area so we can have the scroll that appears in select dropdowns when the items are over a certain number.

.dropdown .options{
	background:#f8f8f8;
	margin:0; padding:0;
	width:auto; list-style:none;	

	max-height:200px; overflow:auto; /* add this */
	visibility:hidden; 

	border-left:1px solid #2397e9;
	border-right:1px solid #2397e9;
	border-bottom:1px solid #2397e9;
}

 

And  here it is, our (wannabe select) dropdown made with list items! dropdown-list-max

We’ve completed the transformation now all with CSS. The next part is to make sure the item selected swaps with the content of the .trigger . This requires a little bit of script and for this I have used jQuery. Make sure you link the jQuery library.

	<script>
	$(document).ready(function(){
		var dd = $('.dropdown');
		var opt = $('.dropdown .options li');
		
		dd.on('click', function(){
			$(this).find('.options').addClass('active');	
			optclick();					
		}).on('mouseleave', function(){
			$(this).find('.options').removeClass('active');			
		});	

		function optclick(){
			opt.on('click', function(){			
				$(this).parent().prev().html($(this).text());
				$(this).parent().removeClass('active');
				return false;
			});		
		}
	});	
	</script>

Creating a dropdown from a list

 

I hope you try  it out for yourself as I’d love to know what you think.  Do you have another way around this? I sure would like to know, too. Thanks!

Tags: , , ,

@rjene