答案:基于Web标准的UI组件 — 菜单(2)
UI Components Based on Web Standards - Menu (2)在本文的第一篇中,我们了解了一个“完美”的菜单应该具备的可用性和易用性特征,并且创建了基本的XHTML和CSS代码。接下来我们将深入到与菜单相关的一些高级特性的实现技术上,首先是——
指示当前活动菜单项当用户点击某菜单项进入网站相应的栏目,我们通常会希望这个菜单项表现出与其它菜单项不同的视觉特征,使用户明确地了解自己所处的“地点”而不至于在站点中迷路。我一直想不好应该是给这个菜单项一个什么样的名字,暂且称为“当前活动菜单项(Currently Active Menu Item)”吧,如果你有什么好想法请一定在右边留言告诉我,谢谢^_^。
当前活动菜单项对创建良好的用户体验具有非常重要的作用,一个负责任的UI设计师是绝对不会忽视它的。实现的方法至少有两种:“直接指示”与“自上而下的指示”。
“直接指示”的方法即直接给当前活动菜单项相对应的li元素一个适当的class属性,再在CSS中为这个class重载一般菜单项的视觉属性,使它表现出“独特”的视觉特征。说得挺悬忽,做起来很简单,我们还是用apache.org的菜单为例,并假设已经点击“DB”项进入了相应的栏目:
<li class="active"> <a href=>
XHTML只要做这么一点小小的改进就可以了,CSS的改动也不大,只要增加这么一段:
menu li.active a{ background-color:#E8F3FF; border:1px solid #05F; }
“自上而下的指示”并不直接在某个菜单项上指明它特殊的身份,而是先给每个菜单项命名,再在菜单项的“上级(比如body元素)”处指明哪个菜单项被选中了(颇有些类似皇帝翻牌选择当晚“临幸”的妃子^_^)。
我们拿上篇文章中使用”绝对定位”的那个菜单为例,假设“软件”项被选中:
<body class="chlSoftware">
<menu>
<li id="miMovie"><a href=><li id="miMusic"><a href=><li id="miSoftware"><a href=></menu>
</body>body元素的class设置了当前页面所处的频道(栏目),也就是此处chl前缀的意思——Channel。根据这个class就可以设置“临幸”的规矩了……-_-|||
body.chlMovie li#miMovie a, body.chlMusic li#Music a, body.chlSoftware li#miSoftware a{ background-color:#E8F3FF; border:1px solid #05F; }
可能的情况下我建议使用第二种方式,理由如下:
带图标的菜单项
- 写后台程序的时候比较方便,只需判断当前所处的栏目给body设置class即可(怎么判断?那可不是我的事儿....);
- 扩展性好,不仅可用于指示当前活动菜单项,也可以给页面上的其他元素提供当前状态的信息。比如你想让每个栏目有不一样的主色调,知道怎么办了吧^_^;
- 当皇帝比较爽……
做到现在我们的菜单还都是光秃秃的,某些朋友可能已经对Web标准技术在视觉效果上能走多远产生怀疑。下面我们就把图片引入到菜单的制作中,先从最简单的讲起——给菜单项加个图标“”。我们以例9的菜单为基础,对a元素的样式做些小修改:
menu a{
/*定义a为块级元素,方便用盒模型属性定义外观*/ display:block;
/*定义尺寸*/ width:100%; height:20px;
/*盒模型风格*/background-color:#F6F6F6;border:1px solid #DDD;
/*文字样式*/ font:11px arial; text-decoration:none;
/*垂直居中*/ line-height:20px;
/*水平居中*/text-align:center;
/*文字缩进*/ text-indent:20px;
/*图标*/ background:#F6F6F6 url(i/arrow.gif) 5% 50% no-repeat; }这里有三点需要说明一下:
背景图翻转技术
- 去除文字水平居中后菜单项的文字都紧贴左侧排列,我们需要给图标留出一定的空间。常用的方法(也是最容易想到的方法),就是使用padding-left。但这样会面临IE的盒模型Bug,虽然解决起来也很方便,但总不如用text-indent来得自然,更何况这样没有任何的Bug需要处理。
- 为什么不把图标直接用img标签插入到XHTML文档中?因为这些图标仅仅是装饰作用,它们并不是这个网页真正的“内容”,所以它们出现在XHTML代码中是不合适的。另外用背景图的方式处理也更方便更节约网络流量。反过来说,如果这个图标是一个logo,比如Apache HTTP Server那支著名的羽毛,建议你把它加入到XHTML代码中(别忘了alt属性),因为它是这个网页真正想要表达的“内容”。
- 关于如何正确设置背景图,我这里就不多说了,请参考小雨的《CSS2.0中文手册》中background部分。需要注意的是Opera对背景图定位有一些怪脾气,请参考我的另一篇文章。
这又是一个很实用的技术。当我们对简单的盒模型风格不满意的时候,自然会想到使用背景图来创建更有个性的菜单项,实现的方法也很简单,我们还是在例9的基础上做修改。
先看看两张背景图的效果:
普通状态(bk01.gif):
鼠标覆盖(bk02.gif):CSS的改动也不大,我就拣重要的讲(开始偷懒了……^_^):
menu a:link,menu a:visited{ background:transparent url(i/bk01.gif) 0 0 no-repeat; }
menu a:hover,menu a:active{ background:transparent url(i/bk02.gif) 0 0 no-repeat; }Yes,就这么简单,只要给a元素的四种状态设置相应的背景图就可以了。这种办法足以应付各种古里古怪的菜单,而且不光可以用在菜单上,任何需要模样古怪的链接的地方都可以用上它。不过这还不是最完美的方法,还有更棒的。
我们先把两张背景图合成一张(bk03.gif):
再修改CSS(这里只列出修改了的部分):
menu a{ ... background:transparent url(i/bk03.gif) 0 0 no-repeat; }
menu a:link,menu a:visited{ background:transparent url(i/bk01.gif) 0 0 no-repeat; }
menu a:hover,menu a:active{background:transparent url(i/bk02.gif) 0 0 no-repeat;background-position:0 -21px; }看明白了吗?事实上只用了一张图,当鼠标覆盖事件产生后把图的位置向上移动了一段距离,刚好露出下半张图的红色背景部分。这样做有什么好处吗?
- 方便管理背景图。一个大型网站很可能需要使用几十上百张背景图,把相关的背景图合在一起可以极大地方便管理和维护。
- 与桌面软件皮肤的制作方式更接近。制定中的CSS3已经引入桌面软件皮肤制作中最基本的“九宫格”技术,由此网页UI设计已经明显地呈现出向桌面软件UI设计靠拢的趋势。
- 节约网络流量。以上面这个例子为例,小的背景图0.47K,合并后的背景图0.94K。两张小图的体积之和也是0.94K,这有什么节约的?我们知道数据是以“IP包”的形式在网络上传输。大部分的IP包都在1K左右,比如我的网站服务器收发的每个IP包大小为1024字节。每张图至少需要一个IP包传输,这么一来两张小图就占用了2K的流量,而使用一张大图只需要1K的流量。对于中小型网站这点流量的出入并不算什么,但对于日访问量上千万的网站来说,“能省则省”并不仅仅是网络流量的问题,而是实实在在的经济
上一个:基于Web标准的UI组件 — 菜单(1)
下一个:CSS的优化&技巧