水平导航条与下拉菜单(兼容ie6)
水平导航条
关键技术即是列表项(li)的浮动,即添加以下代码:
ul li { float: left;}
举一个例子,下面是html代码
<ul id="mainnav">
<li><a href="#">Home</a></li>
<li><a href="#">About Us</a></li>
<li><a href="#">Our Clients</a></li>
<li><a href="#">Support</a></li>
<li><a href="#">Contact Us</a></li>
</ul>
第一步,预格式化,消除列表项,列表外边距与内边距;(实际中通过reset.css)
#mainnav {
list-style: none;
margin: 0;
padding: 0;
}
第二步,浮动列表项;
#mainnav li {
float: left;
}
如图所示即为一个最简单也是最丑的水平导航/横向导航
第三步,简单美化导航显示效果,如设置字体,去掉下划线,给列表添加背景色,通过设置列表项边框添加分割线,等等。最终效果图与代码如下:
#mainnav {
list-style:none;
margin: 0;
padding: 0;
float: left; /* 使无序列表框包裹住浮动的列表项 */
background-color: #eee;
}
#mainnav li {
float: left;
}
#mainnav li a {
font: 20px/30px Arial, Verdana, sans-serif;
display: block;
text-decoration: none;
color: #404040;
padding: 5px 20px;
border-left: 1px solid #bbb;
}
#mainnav .firstChild a { /* 要给第一个列表项添加 class=”firstChild” */
border-left: none;
}
最后添加鼠标悬停效果,即:hover样式,代码如下:
#mainnav li a:hover,
#mainnav li a:focus { /* :focus伪类使键盘操作获得鼠标悬停效果 */
color: #fdfdfd;
background-color: #4cc;
}
最终DEMO:简单的水平导航条
下拉菜单
这种技术也叫Suckerfish dropdown,关键之处就是先通过设置二级列表的left属性为一个大的负值(如-999em),将其定位到窗口之外,然后鼠标悬停时再将left属性设置成0,从而显示出来。
注:虽然可以通过设置二级列表的display: none先隐藏,然后再鼠标悬停时设置diplay: block;
实现同样效果,但display: none会使屏幕阅读器无法读取其中的内容,从而造成可访问性问题。
html代码如下:
<ul id="mainnav">
<li class="firstChild"><a href="#">Home</a></li>
<li><a href="#">About Us</a></li>
<li><a href="#">Our Clients</a>
<ul>
<li><a href="#">Leadership</a></li>
<li><a href="#">Involvement</a></li>
<li class="subLastChild"><a href="#">Our Vision</a></li>
</ul>
</li>
<li><a href="#">Support</a>
<ul>
<li><a href="#">Blog</a></li>
<li><a href="#">Downloads</a></li>
<li class="subLastChild"><a href="#">FAQ</a></li>
</ul>
</li>
<li><a href="#">Contact Us</a></li>
</ul>
第一步,为了使二级列表绝对定位时的参考元素为包含其的一级列表项,先设置一级列表项为相对定位,添加 #mainnav li { position: relative;}。然后将二级列表定位到窗口之外:
#mainnav .subnav {
position: absolute;
left: -999em; /* 将二级列表定位到窗口之外 */
top: 40px;
}
top属性的数值 = 锚的行高 + 锚的上下内边距和
第二步,鼠标悬停时显示二级列表/下拉菜单,添加如下代码:
#mainnav li:hover .subnav {
left: 0;
}
#mainnav .subnav li {
float: none; /* 消除列表项对所包含子元素的包裹,扩展宽度 */
}
最后设置一些美化代码,最终DEMO:Suckerfish下拉菜单
另因为IE6不支持给除a元素之外的元素添加:hover伪类,需要通过JavaScript代码或修改.htc文件实现此效果,具体方法见下。
JavaScript方法
原理就是鼠标悬停时给列表项添加类,并在CSS文件设置该类的的left属性,鼠标移出时删除类。详情参考该文:http://htmldog.com/articles/suckerfish/dropdowns/
JS与CSS代码如下:
function sfHover() {
var sfEls = document.getElementById("mainnav").getElementsByTagName("li");
for (var i=0; i<sfEls.length; i++) {
sfEls[i].onmouseover = function() {
this.className += " sfhover";
}
sfEls[i].onmouseout = function() {
this.className = this.className.replace(new RegExp(" sfhover\\b"), "");
}
}
}
window.onload = sfHover;
#mainnav li:hover .subnav,
#mainnav li.sfhover .subnav {
left: auto;
}
DEMO:兼容ie6下拉菜单JS版
通过CSS的behavior属性添加特定的.htc文件
需要添加如下代码引用 ie6hover.htc 文件。
参考文章:http://www.cnblogs.com/czj33499173/archive/2011/12/30/2307674.html
body {
behavior: url(ie6hover.htc); /* 注意路径 */
}
ie6hover.htc文件代码如下:
<attach event="ondocumentready" handler="parseStylesheets" />
<script language="JScript">
/**
* Pseudos - V1.30.050121 - hover & active
* ---------------------------------------------
* Peterned - http://www.xs4all.nl/~peterned/
* (c) 2005 - Peter Nederlof
*
* Credits - Arnoud Berendsen
* - Martin Reurings
* - Robert Hanson
*
* howto: body { behavior:url("csshover.htc"); }
* ---------------------------------------------
*/
var currentSheet, doc = window.document, activators = {
onhover:{on:'onmouseover', off:'onmouseout'},
onactive:{on:'onmousedown', off:'onmouseup'}
}
function parseStylesheets() {
//window.alert("hi");
var sheets = doc.styleSheets, l = sheets.length;
for(var i=0; i<l; i++)
parseStylesheet(sheets[i]);
}
function parseStylesheet(sheet) {
if(sheet.imports) {
try {
var imports = sheet.imports, l = imports.length;
for(var i=0; i<l; i++) parseStylesheet(sheet.imports[i]);
} catch(securityException){}
}
try {
var rules = (currentSheet = sheet).rules, l = rules.length;
for(var j=0; j<l; j++) parseCSSRule(rules[j]);
} catch(securityException){}
}
function parseCSSRule(rule) {
var select = rule.selectorText, style = rule.style.cssText;
if(!(/(^|\s)(([^a]([^ ]+)?)|(a([^#.][^ ]+)+)):(hover|active)/i).test(select) || !style) return;
var pseudo = select.replace(/[^:]+:([a-z-]+).*/i, 'on$1');
var newSelect = select.replace(/(\.([a-z0-9_-]+):[a-z]+)|(:[a-z]+)/gi, '.$2' + pseudo);
var className = (/\.([a-z0-9_-]*on(hover|active))/i).exec(newSelect)[1];
var affected = select.replace(/:hover.*$/, '');
var elements = getElementsBySelect(affected);
currentSheet.addRule(newSelect, style);
for(var i=0; i<elements.length; i++)
new HoverElement(elements[i], className, activators[pseudo]);
}
function HoverElement(node, className, events) {
if(!node.hovers) node.hovers = {};
if(node.hovers[className]) return;
node.hovers[className] = true;
node.attachEvent(events.on, function() {
node.className += ' ' + className;
});
node.attachEvent(events.off, function() {
node.className = node.className.replace(new RegExp('\\s+'+className, 'g'),'');
});
}
function getElementsBySelect(rule) {
var parts, nodes = [doc];
parts = rule.split(' ');
for(var i=0; i<parts.length; i++) {
nodes = getSelectedNodes(parts[i], nodes);
}
return nodes;
}
function getSelectedNodes(select, elements) {
var result, node, nodes = [];
var classname = (/\.([a-z0-9_-]+)/i).exec(select);
var identify = (/\#([a-z0-9_-]+)/i).exec(select);
var tagName = select.replace(/(\.|\#|\:)[a-z0-9_-]+/i, '');
for(var i=0; i<elements.length; i++) {
result = tagName? elements[i].all.tags(tagName):elements[i].all;
for(var j=0; j<result.length; j++) {
node = result[j];
if((identify && node.id != identify[1]) || (classname && !(new RegExp('\\b' +
classname[1] + '\\b').exec(node.className)))) continue;
nodes[nodes.length] = node;
}
}
return nodes;
}