图一
所以我们先将它如图哪样切成六片,然后将这六张图片合并在一起。为什么要这样呢?看看css sprites原理吧!
图二
上图中第一和第二个图片组成普通菜单样式(默认样式),第三、第四个图片组成翻滚样式,第五和第六个图片组成点击后的菜单项样式。
我们将阴影图片专门提取出来,作成一张很小的背景图片。
图三
该要的图形都准备好了,接下来,我们将这个图片加在菜单项上吧。一个按钮要用到两张图片才能表现出来。地球人都知道,一个标签只能装一张图片(如果你发现一个标签能装上两张图片,请及时告诉我,我请你吃饭!)。哦!我的菜单结构中每一项刚好有两个标签,一个是li,它里面有一个A标签,刚好可以用来装左右两张图片。Li用来装左侧的图片,A用来装右侧的图片。我真佩服我自己,这么好的点子都能想得出来,正在沾沾自喜的自我陶醉中
别忙,哦,天啦,如果这样来装图片,我的三种鼠标翻滚状态如何实现?我们都应该知道,目前除了该死的IE6,其它的浏览器都支持li:hover伪类。然而要兼容各主流浏览器(这是我们的第8项目标哟,别忘了!),这种方法是行不通的。IE6只能在A标签上应用伪类,其它的标签它可是一概不理!
既然IE6只能在A标签上应用hover伪类,那么我们要制作自适应的滑动门菜单,就需要在结构上动手脚了,看来只能在A标签中再加入一个标签,那么菜单的结构就会变成下面这个样子了。(注意:这儿就开始改变结构了,虽然我一直想极力避免这种情况的发生,但好像要达到要求,这个标签是非加不可了。)
lia href="#none" title="冰极峰"span冰极峰/span/a/li
我们在A标签中加入了一个span容器,它将文字内容包括起来了。现在有两个标签,可以装两张图片了。我们将右侧图片放在A标签的背景中并向右靠齐,将左侧图片放在SPAN标签中并向左靠齐。这样就能表现出一个完整的按钮形状。
还好,虽说多加了一个标签,但它还不是完全无语义。
好了,我们的准备工作都差不多了,该给菜单穿上新衣服了。
我们要做成自适应宽度的菜单,那么,我们就不能设置菜单的宽度值,所以我们不能像平时制作一个水平的有固定宽度的菜单的做法那样,设置宽度,然后向左浮动。如果这样的话,每个菜单项的宽度不同时,要分别定义每一项的宽度,那就必须给每个菜单项定义一个ID或CLASS,并且这种方式也不利后台程序的动态循环输出。
我们需要的是像内联元素一样从左到右自动在一行内排列每个菜单项,那么我们就需要菜单以内联的方式表现出来,OK,我们就用display:inline吧,这是一个非常有用的属性:它解析后的排列方式能达到我们的基本要求:在一行内从左到右自动排列标签元素,每一项宽度可以不同。
如果用上面这种属性真的能满足我们需要了,就没有下面这一段文字内容。
虽说这个属性能满足我们项目基本需要,可是它有一个非常致命的弱点:它不能设置宽度和高度值,不信你可以试试。它只表现为文字的默认高度和宽度,超出这个宽高值后就自动隐藏了。这样一来,我在这里面是有背景图片的,要表现出这个图片效果,我们需要给定一个宽度和高度。这就不能做出我们的效果了,郁闷!还好,还有一个属性:display:inline-block;它的表现就是我们需要的。
但是这个属性也有致命弱点,它只能被FF3等高级浏览器识别。其它的浏览器只能绕道而行了。啊哦!所以,统一浏览器是多么的重要啊!看来,HACK也是我们逼不得已的一种解脱方式了。
原理我们都了解了,我们可以根据上面两篇文章提供的技巧来做一个自适应的菜单了。
我们先写右侧图片的样式,它是应用在li元素的子节点A标签中的。
li a{display:inline-block; padding-right:30px; padding-top:10px; *padding-top:0; padding-bottom:13px; *padding-bottom:0; height:36px; background:url(images/button.gif) no-repeat right -36px; text-decoration:none; font-size:12px; color:#fff;}
我们先设置display:inline-block,然后我们再用padding来撑开它的边距,让它有一定的空间来装填图片。注意,这里的图片路径换成你自己的路径。然后设置其它的样式,如去掉下划线,字体颜色,字体大小等等。设置图片靠右对齐。
li a span{display:inline-block; padding-left:30px; padding-top:10px; *padding-top:0; padding-bottom:13px; padding-bottom:0; height:36px; line-height:36px; background:url(images/button.gif) no-repeat left top; font-weight:bold;}
按钮左侧的图片是放在SPAN元素中的,将它的图片向左对齐,也设置padding来撑开它的宽度和高度。
li a,li a span{display:inline;cursor:pointer;}
然后将它们的又设置回inline内联模式,触发IE的haslayout特性。
在上面的代码,我们还看到有一个HACK的应用,*padding-bottom:0;和*padding-top:0;这用来解决IE与FF等浏览器不同效果的。不信你删除后看看会有什么效果,在IE下高度伸展有问题。
好了下面该写鼠标移上时的效果了。
li a:hover{padding-right:30px;background:url(images/button.gif) no-repeat right -108px;}
li a:hover span{padding-left:30px;background:url(images/button.gif) no-repeat left -72px;font-weight:bold;}
再接下来是鼠标点击后的效果。
li a:active{padding-right:30px;background:url(images/button.gif) no-repeat right -180px;}
li a:active span{padding-left:30px;background:url(images/button.gif) no-repeat left -144px;font-weight:bold;}
ok,似乎大功告成,在不同浏览器下看看,似乎都能达到满意的效果。下面是截图:
图四
现在纯CSS版的滑动门菜单基本上就做好了。
行为篇
上面的效果似乎离我的理想状态的菜单又更进了一步。不过也有暇痴。
1.如我点击一个菜单后其焦点虚线框让人感到非常讨厌。
2.还有点击后不能高亮记录当前选中项。
一步一步来解决吧!
为了除去此虚线框,我们可以在A标签属性中加入onfocus="this.blur();"这句代码,这是非常立竿见影的方法。那么就需要在结构上添加一些内容,可能就会变成下面这种结构了:
lia href="#none" title="冰极峰" onfocus="this.blur();"span冰极峰博客/span/a/li
可是,我们别忘了,要尽量避免行为给结构造成干扰,这是我们在开始就提出的要求。因此,这种方法基本上可以否决了。
另外我们想记录当前选中项菜单,这种制作方法有很多种,纯CSS的做法可能会为每一个菜单项创建一个ID,然后用样式表来设置不同页面下调用高亮菜单的样式。但这种方法又会对结构添加一些字符。
上面两个解决方案都需要在结构中嵌入一些本来该用动作来表现的东西,这会造成结构冗余,可读性较差,并且给人感觉页面很乱。
我想该是JS粉墨登场的时候了...
我想在页面一载入时就遍历UL下的所有A标签,自动给它加上一个样式,这个样式就是li a的样式,我们可以将它改成一个class类,我们取名为normal吧,方便JS动态调用,并将li a:hover也换成一个class类,取名为over,作为JS动态调用鼠标移上时的效果,而li a:active就是当前选中状态了,取名为cur,将它们三个都在样式表中作出修改。
在页面载入后,用for循环给每个菜单A标签注入onclick,onmouseover,onmouseout事件,我们就可以摒弃用a:link,a:hover,a:active来摸拟三态效果了,因为这样更便于控制当前选中菜单的高亮效果。顺便在这个循环中去掉讨厌的虚线框(虽说在FF下只用一句样式就可以搞定,但在IE中显然是不行的!)。然后我们用cookie来记录选中的菜单项ID,并设置其为5分钟后过期。这样无论你如何恶意刷屏,高亮菜单还是能记住。(是否采用cookie方式来保持高亮,这可以根据不同的项目需求来定。这种方式也有不好的地方,有同好者可以交流一下!)
Js中创建了几个基本的函数,看起来就像下面这样(详细代码请参看源码):
var temp;/*菜单ID*/
function getObj(objName){return(document.getElementById(objName));}
window.onload =function() {
var obj=getObj("menu");/*ul的id*/
var obj_a=obj.getElementsByTagName("a");
number=obj_a.length;
for (var i=0,j=obj_a.length;ij;i++){
obj_a[i].index=i;
obj_a[i].className="normal";
obj_a[i].onclick=function(){click(this)};
obj_a[i].onmouseover=function(){overme(this)};
obj_a[i].onmouseout=function(){outme(this)};
obj_a[i].onfocus=function(){this.blur()};/*去掉IE下的虚线框,ff用样式解决*/
}
if (getCookie("show_a") != null) {
obj_a[getCookie("show_a")].className="cur";
temp=getCookie("show_a")
}
else{
var obj=getObj("menu");
var obj_a=obj.getElementsByTagName("a");
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/webkaifa/)obj_a[0].className="cur";
//鼠标滑过效果
function overme(o){/*代码略,请看DEMO* 猜你喜欢