Creating a Smooth Drop Down Menu with CSS and jQuery
Join the DZone community and get the full member experience.
Join For FreeLet me explain the HTML structure that will be used here. In this example we will use a short list of 8 countries. List is created using Definition List (DL) element. Why this element? It is similar to unordered/ordered list - the only difference is that DL consists of two elements: DT (term) and DD (definition). This makes it perfect candidate for Drop Down element. Element DT can be used to show collapsed state with currently selected option while DD can show all the available options in nested UL. Here is the sample structure:
<dl class="dropdown">
<dt><a href="#"><span>Please select the country</span></a></dt>
<dd>
<ul>
<li><a href="#">Brazil</a></li>
<li><a href="#">France</a></li>
<li><a href="#">Germany</a></li>
<li><a href="#">India</a></li>
<li><a href="#">Japan</a></li>
<li><a href="#">Serbia</a></li>
<li><a href="#">United Kingdom</a></li>
<li><a href="#">United States</a></li>
</ul>
</dd>
</dl>
In order to make Drop Down functional we have to add several important CSS styles. First of all we have to reset margins and paddings for DD, DT and UL. DD will be positioned relatively, so that nested UL can be absolutely positioned. As I mentioned earlier, in collapsed state, only DT will be visible. It contains link with span inside it and two elements make sliding doors, a technique that is often used for creating buttons and tabs. Styling UL is simple, it will be positioned 2px below DT and initially hidden.
<dl class="dropdown">
<dt><a href="#"><span>Please select the country</span></a></dt>
<dd>
<ul>
<li><a href="#">Brazil</a></li>
<li><a href="#">France</a></li>
<li><a href="#">Germany</a></li>
<li><a href="#">India</a></li>
<li><a href="#">Japan</a></li>
<li><a href="#">Serbia</a></li>
<li><a href="#">United Kingdom</a></li>
<li><a href="#">United States</a></li>
</ul>
</dd>
</dl>
After adding some colors, borders and hover effects (check out source code on demo page), the result so far will be something that really looks like Drop Down.
Let's make it work
It's time to involve jQuery. Each click on DT (actually link inside DT) will toggle nested UL.
$(".dropdown dt a").click(function() {
$(".dropdown dd ul").toggle();
});
This was the simplest part. Now let's simulate other features of Select element. When you choose an option from the list (UL) it become selected option and is shown inside the link in DT. The function below replaces the HTML of currently selected item with the inner HTML of clicked link. At the end, it hides nested UL.
$(".dropdown dd ul li a").click(function() {
var text = $(this).html();
$(".dropdown dt a span").html(text);
$(".dropdown dd ul").hide();
});
This looks more like Drop Down, but there are still some things that need to be done. First, once you reveal nested UL by clicking on Drop Down it remains visible. And that's a bug. Although there can be better solutions, I've came up with this one:
$(document).bind('click', function(e) {
var $clicked = $(e.target);
if (! $clicked.parents().hasClass("dropdown"))
$(".dropdown dd ul").hide();
});
The function above checks each click on a page and if click occurred on some elements outside the dropdown it hides nested UL. Now this looks like regular Select element.
What about selected value?
Although it looks fine it will surely become a headache for developers. Select element has "value" attribute where you can store some data then needs to be sent to the server. This attribute is usually populated by ID's of records stored in the database. In our example with list of countries, it is more likely that some country ID will be needed for any serious processing on the server. So how to store these values and how to get selected one?
Let's modify HTML structure from the beginning of this tutorial and add <span> element inside links in UL. Each <span> have class "value" and real value inside it.
<dl class="dropdown">
<dt><a href="#"><span>Please select the country</span></a></dt>
<dd>
<ul>
<li><a href="#">Brazil<span class="value">BR</span></a></li>
<li><a href="#">France<span class="value">FR</span></a></li>
<li><a href="#">Germany<span class="value">DE</span></a></li>
<li><a href="#">India<span class="value">IN</span></a></li>
<li><a href="#">Japan<span class="value">JP</span></a></li>
<li><a href="#">Serbia<span class="value">CS</span></a></li>
<li><a href="#">United Kingdom<span class="value">UK</span></a></li>
<li><a href="#">United States<span class="value">US</span></a></li>
</ul>
</dd>
</dl>
It would be strange to have codes next to country names in the list, so let's hide these spans.
.dropdown span.value { display:none;}
And that is the only change we'll need to make in order to make this Drop Down fully functional. Take one more look at click handler for links in UL - it replaces inner HTML of link in DT with inner HTML of clicked link. This means tha tlink in DT element will have <span> with value included.
var text = $(this).html();
$(".dropdown dt a span").html(text);
It's easy now to get selected value from our Drop Down. You can create a function like the one below to extract selected value. As the matter of fact, the very same function extracts selected value in the demo and shows this value under the Drop Down.
function getSelectedValue(id) {
return $("#" + id).find("dt a span.value").html();
}
The code works in all major browsers: Firefox, Safari, Google Chrome, Opera(9.64), Internet Explorer 7 and 8. It works even in IE6, althoug it needs some polishing :)
Wasn't that simple?
I think that reinvention of Drop Down wasn't that hard, although it might seems as is it. There are several features that need to be implemented in order to have a credible simulation, but each one of those is simple and straightforward. Have you ever had a need for reinventing Drop Down? What are your experiences? In any case, let me know your thoughts!
Published at DZone with permission of Janko Jovanovic. See the original article here.
Opinions expressed by DZone contributors are their own.
Trending
-
Clear Details on Java Collection ‘Clear()’ API
-
Cypress Tutorial: A Comprehensive Guide With Examples and Best Practices
-
Testing Applications With JPA Buddy and Testcontainers
-
Fun Is the Glue That Makes Everything Stick, Also the OCP
Comments