Custom HTML dropdown with jQuery

Table of Contents

Why to use pre-created or pre-packed features if you can create and build your own? Default dropdown inputs does not look good at all and options to style through CSS are quite limited. If you have few minutes and are not afraid of jQuery, you can create your own dropdown according to your ideas. Let’s quite talking and start working …

Assets

I used two stylesheets in this project:
– reset stylesheet – you can use HTML5 Doctor reset stylesheet here or Meyer web reset stylesheet here
– fontawesome you can get here

HTML

First thing is to setup HTML structure for the dropdown. Dropdown will be created from div with class “dropdown”. Inside this element we will nest anchor tag for default text visible while options will be hidden. <a> element will have class “js-link”. Default text is “Select one option”. Inside this element will be also nested <i> element for icon from font awesome. To display an icon, we will give this element class “fa” and “fa-chevron-down”. I will explain how to use fontawesome more in-depth in future post. After anchor tag will be unordered list for options to select with, let’s say, four list items – “Option 1”, “Option 2”, “Option 3” and “* Reset”- (one for resetting to default text). List will have class “js-dropdown-list”. I use “js-” prefix in classes to use manipulate elements strictly via JavaScript. I never use those classes for styling and other stuff, only JS.

HTML:

<div class="dropdown">
 <a href="#" class="js-link">Select one option <i class="fa fa-chevron-down"></i></a>
 <ul class="js-dropdown-list">
 <li>Option 1</li>
 <li>Option 2</li>
 <li>Option 3</li>
 <li>* Reset</li>
 </ul>
</div>

CSS

Backbones for dropdown is complete so it is time to put some styles in work. First is to set the “Base” and “Typography” part of stylesheet. For “Base” we will declare rule for universal selector with with box-sizing property set to “border-box”.

CSS:

/*Base*/
* {
 -webkit-box-sizing: border-box;
 -moz-box-sizing: border-box;
 box-sizing: border-box;
}

In “Typography” we will set the default font size for document to 16 pixels. H1 size will be 1.2em and list items 1em.

CSS:

/*Typography*/
html {font: 16px Verdana;}
h1 {font-size: 1.2em;}
li {font-size: 1em;}

Now we will work in “Layout” part of stylesheet (everything what is not in Base or Typography). For start, we will style the dropdown div. For width I used 14.5em. You can choose what ever value you like. I also added light border of .1em solid #c0cdd1 (shade of gray).

CSS:

/*Layout*/
.dropdown {
 width: 14.5em;
 border: .1em solid #c0cdd1;
}

Anchor tag or the default text of dropdown has following setting. Display property is set to block. Padding is .5em (thanks to box-sizing property padding will push the text inside .5em from borders without changing width or height of element). Color of text is #000 – black and text-decoration value is none.

CSS:

a {
 display: block;
 padding: .5em;
 color: #000;
 text-decoration: none;
}

For focus, hover and active states the only change will be in background. On focus and hover it will be #ecf0f1 (shade of grey) and on active #fbfcfc (almost white).

CSS:

a:focus, a:hover {background: #ecf0f1;}
a:active {background: #fbfcfc;}

We will quickly position the chevron icon to right with float property.

CSS:

.fa {float: right;}

Now we will focus on styling the unordered list. Prepare display property with value of “none” (don’t use it yet). Set the border-top to same value as for dropdown to divide default text from options.

CSS:

ul {
 display: none;
 border-top: .1em solid #c0cdd1;
}

For individual list items we will use padding of .5em to create a bit of space around the text and then set the cursor property to pointer – to imitate clickable option.

CSS:

li {
 padding: .5em;
 cursor: pointer;
}

To divide list items (except the first one) somehow, we will use border-top set to .1em dashed and color of #dde4e6 (shade of grey). Last list item (last-child) – which is a reset option – will have color of #ad0000 (shade of red) to make it stand out. Focus, hover and active states will be same as for anchor tag. one more thing for our CSS … Why not to add light transition to anchor tag and list items to animate the change of background on focus, hover and active?

CSS:

li:not(:first-child) {border-top: .1em dashed #dde4e6;}
li:last-child {color: #ad0000;}
li:focus, li:hover {background: #ecf0f1;}
li:active {background: #fbfcfc;}
a, li {
 -webkit-transition: background .35s ease;
 transition: background .35s ease;
}

– note: don’t forget to use “display: none” rule in unordered list now

jQuery

HTML and CSS is complete and the last thing to make the dropdown work is to setup control mechanism via jQuery. First step is to define $(function() {}) for our wrapping our code – it is the same as writing $(document).ready(function() {}) – and inside this function declare variables for list and link (anchor tag / default text of dropdown). Accessing content via variables, if you use that content multiple times, is faster because JavaScript will save that variable in cache and does not have to look for it every time.

jQuery:

$(function() {
 var list = $('.js-dropdown-list');
 var link = $('.js-link');
)};

Next we will use link variable with click() event handler and declare function with “e” as parameter (e is for event) to handle behavior that will happen when you click on anchor tag (default text). First we have to disable default behavior of anchor tag – reloading the page on click. For this, we used the “e” parameter. This will allow us to watch for event – click – and then do some actions, like blocking it default behavior. To do that, we will use “e” parameter with preventDefault() command. On the next line use list variable with slideToggle(200) command. This will show / hide list on click. The number in parenthesis is for setting speed in milliseconds. Write following code after link variable.

jQuery:

link.click(function(e) {
 e.preventDefault();
 list.slideToggle(200);
});

Now we will take care of selecting individual options and changing the default text to text of list item. Write following code after click function. To select individual list item on click, we will use find() function with parameter “li” – we are looking for <li> element – next we will use click function for wrapping code for select behavior. Inside this function we will create text variable for storing text of clicked list item and another variable to store html code for icon. After selecting option we will change the default text of anchor tag to html inside text variable and add content of icon variable. Otherwise, the icon would disappear after selecting any option. Write following code after “list.slideToggle(‘fast’);” line.

jQuery:

list.find('li').click(function() {
 var text = $(this).html();
 var icon = '<i class="fa fa-chevron-down"></i>';
});

To switch the text use link variable with html function. For html function we will use parameter (content inside parenthesis) “text+icon”. This means that function will use content of text variable and also content of icon variable – text of selected list item with icon. It will concatenate and then use it. The result will be anchor tag with text of selected option plus icon on right. After selecting option the list should disappear. Let’s do it by using list variable with slideTogge function with parameter of 200 (200 milliseconds). Put following code after line with icon variable.

jQuery:

link.html(text+icon);
list.slideToggle(200);

One last thing to do … Resetting mechanism. We will use if condition. If the selected list item will be “* Reset”, it will change the text of anchor tag into the default state. To do this, we will use link variable and html function. Parameter (text in parenthesis) will be “‘Select one option’+icon”. This will switch the text of <a> tag and add icon so it will look exactly like default. Following code should be put after “list.slideToggle(200);” line.

jQuery:

if (text === '* Reset') {
 link.html('Select one option'+icon);
}

Complete jQuery code:

$(function() {
 var list = $('.js-dropdown-list');
 var link = $('.js-link');
 link.click(function(e) {
 e.preventDefault();
 list.slideToggle(200);
 });
 list.find('li').click(function() {
 var text = $(this).html();
 var icon = '<i class="fa fa-chevron-down"></i>';
 link.html(text+icon);
 list.slideToggle(200);
 if (text === '* Reset') {
 link.html('Select one option'+icon);
 }
 });
});

It took a while, but you did it! You have your own fully working dropdown and maybe also learned something new. If you have any questions, write comment or write me message on twiter – AlexDevero.

P.S: In future posts I will share some techniques I used in redesigning website of Tag Heuer and creating its mobile-first layout.

Codepen:

http://codepen.io/d3v3r0/pen/Kpfut

Do you have any questions, recommendations, thoughts, advice or tip you would like to share with other readers of this blog, and me? Please share it in a comment. You can also send me a mail. I would love to hear from you.

Did you like this article? Please subscribe.

Are you on social media? Let's connect! You can find me on Twitter, GitHub and Dribbble.

Alex Devero

I'm Founder/CEO of DEVERO Corporation. Entrepreneur, designer, developer. My mission and MTP is to accelerate the development of humankind through technology.

2 Comments

  1. Well considering Tag Heuer is not a responsive mobile first website I highly doubt you did design their site.

    1. Thank you for comment. I’m working on redesign now. It is not online.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: