{"id":119,"date":"2008-05-12T14:51:24","date_gmt":"2008-05-12T19:51:24","guid":{"rendered":"http:\/\/cssnewbie.com\/?p=119"},"modified":"2008-05-12T14:51:24","modified_gmt":"2008-05-12T19:51:24","slug":"easy-css-dropdown-menus","status":"publish","type":"post","link":"https:\/\/cssdeck.com\/blog\/easy-css-dropdown-menus\/","title":{"rendered":"Easy CSS Dropdown Menus"},"content":{"rendered":"<p><a href=\"\/example\/css-dropdown-menu\/\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/cssdeck.com\/blog\/wp-content\/uploads\/2008\/05\/dropdown-400.gif\" alt=\"\" width=\"400\" height=\"115\" class=\"alignnone size-full wp-image-121\" \/><\/a><\/p>\n<p>Attractive dropdown menus have long been the realm of Flash developers and advanced JavaScript gurus. But that needn\u2019t be the case. This tutorial will walk you through developing a clean, semantic dropdown menu using XHTML and CSS that works in all modern browsers!<\/p>\n<p>Let\u2019s start with the XHTML first and foremost. It\u2019s surprisingly simple:<\/p>\n<pre lang=\"html4strict\" escaped=\"true\" line=\"1\">&lt;ul id=&quot;navbar&quot;&gt;\n\t&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Item One&lt;\/a&gt;&lt;ul&gt;\n\t\t&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Subitem One&lt;\/a&gt;&lt;\/li&gt;\n\t\t&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Second Subitem&lt;\/a&gt;&lt;\/li&gt;\n\t\t&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Numero Tres&lt;\/a&gt;&lt;\/li&gt;&lt;\/ul&gt;\n\t&lt;\/li&gt;\n\t&lt;!-- ... and so on ... --&gt;\n&lt;\/ul&gt;<\/pre>\n<p>As you can see, our navigation bar consists of nested unordered lists and anchor tags. The key to this working correctly is to properly nest your unordered lists, wrapping the list item around the unordered list that is nested under it (for more on that topic, <a href=\"\/word-style-outline\/\" title=\"Create a Microsoft Word-Style Outline with CSS\">see this article on styling nested lists<\/a>). The main list items will be our main navigation bar, while the nested unordered lists will become our subnavigation elements. The navigation bar also works without submenus, so you can mix and match as needs be. Also note that, other than an ID on our primary containing unordered list, there are no additional classes or IDs required!<\/p>\n<p>Next, we\u2019ll start adding a few styles to our navigation bar:<\/p>\n<pre lang=\"css\" escaped=\"true\" line=\"1\">#navbar {\n\tmargin: 0;\n\tpadding: 0;\n\theight: 1em; }\n#navbar li {\n\tlist-style: none;\n\tfloat: left; }\n#navbar li a {\n\tdisplay: block;\n\tpadding: 3px 8px;\n\tbackground-color: #5e8ce9;\n\tcolor: #fff;\n\ttext-decoration: none; }<\/pre>\n<p>Here, I\u2019ve removed the margin and padding from the main list, removed all list styling from all the list items, and floated the individual items left. I\u2019ve also added a bit of styling to the anchors, just to make it look a little more like a navigation bar. As you can see, this really isn\u2019t any different than making <a href=\"\/tab-based-navigation\/\" title=\"Tab-Based Navigation in Six (or Seven) Easy Steps\">any other sort of navigation bar<\/a> to start out with. <\/p>\n<p>The only real oddity here is the \u201cheight: 1em;\u201d rule on the navbar ID: this forces the navbar to have a specific height (1em) and width (100% by default), meaning I don\u2019t have to do anything special to \u201cclear\u201d the navigation afterwards. Without that rule, I\u2019d generally need to apply a \u201cclear: left;\u201d to whatever came immediately after the navigation to prevent it from trying to fill the space voided by those left-floated list items. The actual height is arbitrary: as long as a height is specified, the list will retain its block-level status.<\/p>\n<p>Next, we can apply some styles to the subnavigation section:<\/p>\n<pre lang=\"css\" escaped=\"true\" line=\"1\">#navbar li ul {\n\tdisplay: none; \n\twidth: 10em; \/* Width to help Opera out *\/\n\tbackground-color: #69f;}<\/pre>\n<p>This is pretty straightforward: we\u2019re applying a display: none to prevent the submenu from displaying by default, and giving it a background color to make it stand out against the background. The only odd bit is the width property, which is mostly there to prevent Opera from doing some weird things with the width of the submenus (Opera makes them strangely small without a width specified). However, it also ads a nice bit of consistency to the submenus, so I don\u2019t really mind the \u201cfix.\u201d I chose 10em because that allowed all of my submenu items to exist on one line, but you could choose whatever size works for you.<\/p>\n<p>Now all we need to do is style the list for its \u201chover\u201d state:<\/p>\n<pre lang=\"css\" escaped=\"true\" line=\"1\">#navbar li:hover ul {\n\tdisplay: block;\n\tposition: absolute;\n\tmargin: 0;\n\tpadding: 0; }\n#navbar li:hover li {\n\tfloat: none; }\n#navbar li:hover li a {\n\tbackground-color: #69f;\n\tborder-bottom: 1px solid #fff;\n\tcolor: #000; }\n#navbar li li a:hover {\n\tbackground-color: #8db3ff; }<\/pre>\n<p>Let\u2019s go through this bit by bit. The first rule causes the submenu to reappear when the user hovers over the containing list item (this is where the properly nested lists come in handy). We\u2019re using position: absolute on the menus to ensure they don\u2019t push any content below the navigation out of the way. The margin and padding are simply getting rid of the default spacing on the lists so we can style them ourselves.<\/p>\n<p>Next up comes the \u201cfloat: none\u201d rule on the list items. This is just preventing the items in the submenu from floating left: it\u2019s counteracting our previous \u201cfloat: left\u201d rule so that our submenu doesn\u2019t mimic our main navigation elements.<\/p>\n<p>The rules we\u2019re applying to \u201c#navbar li:hover li a\u201d are purely stylistic: I\u2019m applying a background color, bottom border, and changing the color of the anchor. You could set these to be anything you wanted whatsoever.<\/p>\n<p>And finally, I\u2019m applying a different background color to the anchor when it\u2019s being hovered over, just to help set it apart from the other items in the list. This is to improve usability: the user can easily see which item their cursor is over.<\/p>\n<p>That\u2019s all it takes! <a href=\"\/example\/css-dropdown-menu\/\">You can see a working example here.<\/a> I\u2019ve tested this and found it working in Firefox 2, IE7, Opera 8.5+, and Safari for Windows. Of course, you\u2019ll note that I\u2019m leaving out the usual party pooper: Internet Explorer 6. Because of IE6\u2019s limitations on :hover states (you can only hover over anchors in IE6, instead of any element like in all the other browsers), this fantastic little technique doesn\u2019t work. Unless, of course, you\u2019re willing to add in a couple of lines of JavaScript.<\/p>\n<p>The brilliant hive mind that is Patrick Griffiths and Dan Webb have come up with <a href=\"http:\/\/htmldog.com\/articles\/suckerfish\/dropdowns\/\">a fantastic JavaScript solution for Internet Explorer<\/a> that solves the :hover problem in just 12 lines of code. The version I\u2019m using looks like this:<\/p>\n<pre lang=\"javascript\" escaped=\"true\" line=\"1\">sfHover = function() {\n\tvar sfEls = document.getElementById(\"navbar\").getElementsByTagName(\"li\");\n\tfor (var i=0; i&lt;sfEls.length; i++) {\n\t\tsfEls[i].onmouseover=function() {\n\t\t\tthis.className+=\" hover\";\n\t\t}\n\t\tsfEls[i].onmouseout=function() {\n\t\t\tthis.className=this.className.replace(new RegExp(\" hover\\\\b\"), \"\");\n\t\t}\n\t}\n}\nif (window.attachEvent) window.attachEvent(\"onload\", sfHover);<\/pre>\n<p>The concept is pretty brilliantly simple (even if the code looks complex). The function goes through your document and finds every list item contained within the \u201cnavbar\u201d id (you could change this to be whatever you wanted). It then applies a \u201cmouseover\u201d and \u201cmouseout\u201d state on every item: it adds a class of \u201chover\u201d to the list item whenever it\u2019s being moused over, and removes it when the cursor wanders off. The result is you can then apply your CSS to the .hover class <em>as well as<\/em> the :hover pseudo-class and create identical results across the board. So all you need to do is modify your CSS like so:<\/p>\n<pre lang=\"css\" escaped=\"true\" line=\"1\">#navbar li:hover ul, #navbar li.hover ul {\n\tdisplay: block;\n\tposition: absolute;\n\tmargin: 0;\n\tpadding: 0; }\n#navbar li:hover li, #navbar li.hover li {\n\tfloat: none; }\n#navbar li:hover li a, #navbar li.hover li a {\n\tbackground-color: #69f;\n\tborder-bottom: 1px solid #fff;\n\tcolor: #000; }<\/pre>\n<p>And that\u2019s it! With just three tiny changes to your CSS and a dozen lines of JavaScript, you have <a href=\"\/example\/css-dropdown-menu\/\">a CSS dropdown solution<\/a> that works on <em>every single modern browser<\/em> \u2013 even the ones that aren\u2019t exactly standards-compliant.<\/p>\n<div class=\"wp-socializer wpsr-share-icons \" data-lg-action=\"show\" data-sm-action=\"show\" data-sm-width=\"768\" ><h3>Share and Enjoy !<\/h3><div class=\"wpsr-si-inner\"><div class=\"wpsr-counter wpsrc-sz-32px\" style=\"color:#000\"><span class=\"scount\"><span data-wpsrs=\"\" data-wpsrs-svcs=\"facebook,twitter,linkedin,pinterest,print,pdf\">0<\/span><\/span><small class=\"stext\">Shares<\/small><\/div><div class=\"socializer sr-popup sr-32px sr-circle sr-opacity sr-pad sr-count-1 sr-count-1\"><span class=\"sr-facebook\"><a rel=\"nofollow\" href=\"https:\/\/www.facebook.com\/share.php?u=\" target=\"_blank\"  title=\"Share this on Facebook\"  style=\"color: #ffffff\" ><i class=\"fab fa-facebook-f\"><\/i><span class=\"ctext\"><span data-wpsrs=\"\" data-wpsrs-svcs=\"facebook\">0<\/span><\/span><\/a><\/span>\n<span class=\"sr-twitter\"><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/intent\/tweet?text=%20-%20%20\" target=\"_blank\"  title=\"Tweet this !\"  style=\"color: #ffffff\" ><i class=\"fab fa-twitter\"><\/i><\/a><\/span>\n<span class=\"sr-linkedin\"><a rel=\"nofollow\" href=\"https:\/\/www.linkedin.com\/sharing\/share-offsite\/?url=\" target=\"_blank\"  title=\"Add this to LinkedIn\"  style=\"color: #ffffff\" ><i class=\"fab fa-linkedin-in\"><\/i><\/a><\/span>\n<span class=\"sr-pinterest\"><a rel=\"nofollow\" href=\"https:\/\/www.pinterest.com\/pin\/create\/button\/?url=&amp;media=&amp;description=\" target=\"_blank\"  title=\"Submit this to Pinterest\"  style=\"color: #ffffff\" data-pin-custom=\"true\"><i class=\"fab fa-pinterest\"><\/i><span class=\"ctext\"><span data-wpsrs=\"\" data-wpsrs-svcs=\"pinterest\">0<\/span><\/span><\/a><\/span>\n<span class=\"sr-print\"><a rel=\"nofollow\" href=\"https:\/\/www.printfriendly.com\/print?url=\" target=\"_blank\"  title=\"Print this article \"  style=\"color: #ffffff\" ><i class=\"fa fa-print\"><\/i><\/a><\/span>\n<span class=\"sr-pdf\"><a rel=\"nofollow\" href=\"https:\/\/www.printfriendly.com\/print?url=\" target=\"_blank\"  title=\"Convert to PDF\"  style=\"color: #ffffff\" ><i class=\"fa fa-file-pdf\"><\/i><\/a><\/span><\/div><\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>Attractive dropdown menus have long been the realm of Flash developers and advanced JavaScript gurus. But that needn\u2019t be the case. This tutorial will walk you through developing a clean, semantic dropdown menu using XHTML and CSS that works in all modern browsers! [&#8230;]<\/p>\n<p><a class=\"more-link article\" href=\"https:\/\/cssdeck.com\/blog\/easy-css-dropdown-menus\/\" title=\"Click to read 'Easy CSS Dropdown Menus'\">Read Article<\/a><\/p>\n","protected":false},"author":18,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[165,184,188],"tags":[251,89,103,88],"_links":{"self":[{"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/posts\/119"}],"collection":[{"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/users\/18"}],"replies":[{"embeddable":true,"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/comments?post=119"}],"version-history":[{"count":0,"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/posts\/119\/revisions"}],"wp:attachment":[{"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/media?parent=119"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/categories?post=119"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/tags?post=119"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}