HTML Dropdown Menu–with CSS and JavaScript
This post gives step-by-step instruction to build a cool HTML dropdown menu as below or here (as a separate page),
1. Structure the Menu by HTML
HTML is originally designed to be a markup language to indicate the different parts of a document. This is how HTML is used in our dropdown menu. Below is the HTML code,
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="robots" content="noindex" />
<title>Dropdown Menu Step 1</title>
</head>
<body>
<div class="nav">
<ul class="menu" id="menu">
<li><a href="#">Home</a></li>
<li><a href="#">Menu One</a>
<ul>
<li><a href="#">Menu Item 1</a></li>
<li><a href="#">Menu Item 2</a></li>
<li class="submenu">
<a href="#">Menu Item 3</a>
<ul>
<li><a href="#">Menu Item 31</a></li>
<li><a href="#">Menu Item 32</a></li>
<li><a href="#">Menu Item 33</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#">Menu Two</a>
<ul>
<li><a href="#">Menu Item 21</a></li>
<li><a href="#">Menu Item 22</a></li>
<li><a href="#">Menu Item 23</a></li>
<li class="submenu">
<a href="#">Menu Item 24</a>
<ul>
<li><a href="#">Menu Item 241</a></li>
<li><a href="#">Menu Item 242</a></li>
<li><a href="#">Menu Item 243</a></li>
<li><a href="#">Menu Item 244</a></li>
<li><a href="#">Menu Item 245</a></li>
</ul>
</li>
<li><a href="#">Menu Item 25</a></li>
<li><a href="#">Menu Item 26</a></li>
</ul>
</li>
<li><a href="#">Menu Three</a>
<ul>
<li><a href="#">Menu Item 31</a></li>
<li><a href="#">Menu Item 32</a></li>
<li><a href="#">Menu Item 33</a></li>
</ul>
</li>
<li><a href="#">Menu Four</a>
</li>
</ul>
</div>
</body>
</html>
The web page will look like below,
2. Apply CSS Style to HTML
After defining the structure of the dropdown menu, we’ll need to apply CSS style to make it looks like a dropdown menu, the html code is as below,
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="robots" content="noindex" />
<link rel="stylesheet" href="dropdown_menu_step2.css" />
<title>Dropdown Menu Step 2</title>
</head>
<body>
<div class="nav">
<ul class="menu" id="menu">
<li><a href="#">Home</a></li>
<li><a href="#">Menu One</a>
<ul>
<li><a href="#">Menu Item 1</a></li>
<li><a href="#">Menu Item 2</a></li>
<li class="submenu">
<a href="#">Menu Item 3</a>
<ul>
<li><a href="#">Menu Item 31</a></li>
<li><a href="#">Menu Item 32</a></li>
<li><a href="#">Menu Item 33</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#">Menu Two</a>
<ul>
<li><a href="#">Menu Item 21</a></li>
<li><a href="#">Menu Item 22</a></li>
<li><a href="#">Menu Item 23</a></li>
<li class="submenu">
<a href="#">Menu Item 24</a>
<ul>
<li><a href="#">Menu Item 241</a></li>
<li><a href="#">Menu Item 242</a></li>
<li><a href="#">Menu Item 243</a></li>
<li><a href="#">Menu Item 244</a></li>
<li><a href="#">Menu Item 245</a></li>
</ul>
</li>
<li><a href="#">Menu Item 25</a></li>
<li><a href="#">Menu Item 26</a></li>
</ul>
</li>
<li><a href="#">Menu Three</a>
<ul>
<li><a href="#">Menu Item 31</a></li>
<li><a href="#">Menu Item 32</a></li>
<li><a href="#">Menu Item 33</a></li>
</ul>
</li>
<li><a href="#">Menu Four</a>
</li>
</ul>
</div>
</body>
</html>
The code is almost the same as the previous page, with the addition of
<link rel=”stylesheet” href=”dropdown_menu_step2.css” />
The CSS file dropdown_menu_step2.css is as below,
* {
margin:0px;
padding:0px;
}
.nav {
height:36px;
background:#aaaaaa;
color:#ffffff;
text-shadow:1px 1px #888888;
z-index:1000;
margin:0px;
}
.menu {
list-style:none;
font-family:Arial,Verdana,Serif;
font-size:16px;
text-align:center;
width:600px;
margin:0 auto;
}
.menu a {
float:left;
color: #eeeeee;
text-decoration:none;
width:120px;
height:26px;
padding:8px 0px 0px 0px;
}
.menu a:hover {
color:#ffffff;
}
.menu li {
position:relative;
float:left;
width:120px;
}
.menu ul {
list-style:none;
font-family:Arial,Verdana,Serif;
font-size:13px;
font-weight:normal;
background:#aaaaaa;
position:absolute;
top:36px;
left:0;
}
.menu ul ul {
left:120px;
top:0;
}
.menu li.submenu {
font-weight:bold;
}
.menu li.submenu li {
z-index:1001; /*uncomment this line to see the overlapping effect of menu item 31, 32, 33 with 23, 24, 25*/
}
The key idea is to set the list-style as none so the menu items won’t appear as menu items. The dropdown menu items and the submenu are put into relative layout, so they will appear right under the top menu and at the right side of the menu item respectively. The page will look like below,
3. Add JavaScript for Dynamic Effect and Update CSS
There is only one simple change to the CSS file, which is simply set the drop down menu item display as display:none.
The CSS file dropdown_menu_step3.css is as below,
* {
margin:0px;
padding:0px;
}
.nav {
height:36px;
background:#aaaaaa;
color:#ffffff;
text-shadow:1px 1px #888888;
z-index:1000;
margin:0px;
}
.menu {
list-style:none;
font-family:Arial,Verdana,Serif;
font-size:16px;
text-align:center;
width:600px;
margin:0 auto;
}
.menu a {
float:left;
color: #eeeeee;
text-decoration:none;
width:120px;
height:26px;
padding:8px 0px 0px 0px;
}
.menu a:hover {
color:#ffffff;
}
.menu li {
position:relative;
float:left;
width:120px;
}
.menu ul {
list-style:none;
font-family:Arial,Verdana,Serif;
font-size:13px;
font-weight:normal;
background:#aaaaaa;
position:absolute;
top:36px;
left:0;
display:none; /*only this line is added compared with step 2*/
}
.menu ul ul {
left:120px;
top:0;
}
.menu li.submenu {
font-weight:bold;
}
.menu li.submenu li {
z-index:1001; /*uncomment this line to see the overlapping effect of menu item 31, 32, 33 with 23, 24, 25*/
}
The dynamic effects are programmed using JavaScript, the code is as below,
var TINY = {};
TINY.dropdown = function() {
var p = {fade:1, slide:1, active:0, timeout:200};
var init = function(n, o) {
for(s in o) {
p[s] = o[s]; //p.id = "menu", active = "menuhover"
}
p.n = n; //p.n = "dropdown"
this.build();
};
init.prototype.build = function() {
this.h = [];
this.c = [];
this.z = 1000; //the initial z-index value
var s=document.getElementById(p.id).getElementsByTagName('ul'); //get all ul elements
var l = s.length;
var i = 0;
p.speed = p.speed? p.speed*.1:.75; //note that the speed is slower as the value increase
for (; i < l; ++i) {
var h = s[i].parentNode; //get the li element for each ul element
this.h[i] = h;
this.c[i] = s[i];
h.onmouseover = new Function(p.n + '.show(' + i + ', 1)');
h.onmouseout = new Function(p.n + '.show(' + i + ')');
}
};
init.prototype.show = function(x, d) { //the element index and the direction
var c = this.c[x]; //get the sub menu ul
var h = this.h[x]; //get the top level menu item li
clearInterval(c.t);
clearInterval(c.i);
c.style.overflow = 'hidden'; //The overflow is clipped, and the rest of the content will be invisible
if (d) { //show the dropdown menu
if (p.active && h.className.indexOf(p.active) == -1) {
h.className += ' ' + p.active;
}
if (p.fade || p.slide) {
c.style.display = 'block';
if (!c.m) {
//the menu is mouse over for the first time, we do some initializaition here.
if (p.slide) {
c.style.visibility = 'hidden';
c.m = c.offsetHeight;
c.style.height = '0';
c.style.visibility = '';
} else {
c.m = 100;
c.style.opacity = 0;
c.style.filter = 'alpha(opacity=0)';
}
c.v = 0;
}
if (p.slide) {
if (c.m == c.v) { //if the element is fully shown
c.style.overflow = 'visible'; //The overflow is not clipped. It renders outside the element's box.
} else {
c.style.zIndex = this.z;
++this.z;
c.i = setInterval(function() {
slide(c, c.m, 1) //open up the submenu
}, 20);
}
} else {
c.style.zIndex = this.z;
++this.z;
c.i = setInterval(function() {
slide(c, c.m, 1); //open up the submenu
}, 20);
}
} else {
c.style.zIndex = this.z;
c.style.display = 'block';
}
} else {
c.t = setTimeout(function() {
hide(c, p.fade||p.slide? 1:0, h, p.active);
}, p.timeout);
}
}
function hide(c, t, h, s) {
if (s) {
h.className = h.className.replace(s, '');
}
if (t) { //if fade or slide effect is defined
c.i = setInterval(function() {
slide(c, 0, -1); //close up the sub menu
}, 20);
} else { //if no special effect, just make the submenu not visible
c.style.display = 'none';
}
}
function slide(c, t, d) { //d is the slide direction
if (c.v == t) { //when the visible part (c.v) reached the preset limit (t), we stop the function
clearInterval(c.i);
c.i = 0;
if (d == 1) {
if (p.fade) {
c.style.filter = '';
c.style.opacity = 1;
}
c.style.overflow = 'visible';
}
} else {
c.v = (t - Math.floor(Math.abs(t - c.v) * p.speed) * d);
if (p.slide) {
c.style.height = c.v + 'px';
}
if (p.fade) {
var o = c.v/c.m;
c.style.opacity = o;
c.style.filter = 'alpha(opacity=' + (o*100) + ')';
}
}
}
return {init:init}
}();
The dynamic effects are using event handler for onmouseover and onmouseout events of the menu, including the submenu.
The basic idea for slide effect is to use the overflow property. When set to hidden, the content of the html element will be clipped. In our case, the menu item will be shown partially. As we increase the html element height, more and more content will be shown, therefore a slide effect is seen.
For the fade effect, the opacity property is used. For IE, one shall use filter:alpha(opacity=x), where x is in the range of 0 to 100. For other browsers, use opacity:x, where x is from 0.0 to 1.0.
The web page is also similar to step 2. The main difference is the line that links to javascript file,
<script type=”text/javascript” src=”dropdown_menu.js”></script>
and the script to call the function defined in dropdown_menu.js right before the closing tag of body element,
<script type=”text/javascript”>
var dropdown=new TINY.dropdown.init(“dropdown”, {id:’menu’, active:’menuhover’});
</script>
The dropdown menu will be like what you saw at the beginning of this post.
Note: This post is the study notes of the HTML dropdown menu written by Michael Leigeber. One can find the original post at here.
Leave a Reply Cancel reply
40% Discount on My Book — Android NDK Cookbook
Android NDK Cookbook ebook 40% discount with promotion code MREANC40 at Packt Publishing The promotion code is valid until 15th June.Categories
- Android Apps (18)
- Android Audio Editor (1)
- TS 2 (3)
- Video Converter Android (8)
- Video2Gif (1)
- Android Tutorial (26)
- Android Dev Tools (1)
- API illustrated (8)
- Multimedia API (3)
- ffmpeg on Android (4)
- NDK (6)
- UI (5)
- Animation (1)
- Code Snippet (2)
- Coding Beyond Technique (18)
- a word, a world (4)
- Bug Rectified (4)
- Programming Habit (1)
- Software as a Career (1)
- Software as User Experience (1)
- Compilers and Related (2)
- ELF (2)
- Computer Languages (31)
- C/C++ (13)
- Java (9)
- JavaScript (2)
- PHP (1)
- Python (8)
- Data Structure & Algorithms (29)
- Bits (1)
- Data Structure (5)
- Integers (10)
- BigInteger (1)
- Prime (4)
- Search (3)
- Sorting (5)
- Strings (5)
- Database (1)
- SQLite (1)
- Digital Signal Processing (33)
- Distributed Systems (17)
- Apache Cassandra (6)
- Apache Hadoop (8)
- Apache Avro (3)
- Apache Nutch (3)
- Apache Solr (1)
- Linux Study Notes (40)
- crontab (1)
- Linux Kernel Programming (8)
- Linux Programming (12)
- IPC (2)
- Linux Network Programming (5)
- Linux Signals (2)
- Linux Shell Scripting (1)
- ssh (3)
- Machinery (30)
- misc (1)
- My Ideas (1)
- My Project (3)
- Mobile Caching (1)
- Selective Decoding (2)
- My Publication (1)
- My Readings (1)
- Networking (15)
- Program for Performance (8)
- Uncategorized (1)
- Virtual Machine (2)
- Web Dev (8)
- web components (3)
- Android Apps (18)
Recent Comments
Archives
- May 2013 (1)
- April 2013 (1)
- March 2013 (4)
- December 2012 (2)
- November 2012 (6)
- October 2012 (6)
- September 2012 (3)
- August 2012 (13)
- July 2012 (15)
- June 2012 (3)
- May 2012 (8)
- April 2012 (4)
- March 2012 (13)
- February 2012 (19)
- January 2012 (9)
- December 2011 (11)
- November 2011 (12)
- October 2011 (4)
- September 2011 (12)
- August 2011 (16)
- July 2011 (15)
- June 2011 (6)
- May 2011 (10)
- April 2011 (13)
- March 2011 (20)
- February 2011 (4)
- November 2010 (2)
- May 2010 (1)
- April 2010 (1)
- February 2010 (1)




