Koubei UED

Just another WordPress weblog

一个导航的前端实现 By 大米

%e4%b8%80%e4%b8%aa%e5%af%bc%e8%88%aa%e7%9a%84%e5%89%8d%e7%ab%af%e5%ae%9e%e7%8e%b0

前端代码要做到简洁易读、高效,还要考虑后端嵌套的方便性。
前段时间做了一个导航,把整个制作过程重现,希望对大家有帮助。

看到这样的导航,你会怎么设计代码结构和切图?

第一步
代码结构按照逻辑来分析初步构想可以这样:

<ul>
	<li class="first-current">1 填写店铺信息</li>
	<li class="middle">2 填写联系人信息</li>
	<li class="middle">3 确认创建信息</li>
	<li class="last">4 提交成功</li>
</ul>

分三种表现,头、中间、尾,同时,用current标出当前停在第几步。可以用第二个class,就是中间用空格,当然如上中间加-,新用一个class也无妨。

第二步
切图,这是最关键的。
这个导航虽然不是很花哨,但是图形结构也是有一定复杂度。如果直接按1234每个步骤的图直接截下来,左右两头都有图形特殊性,就都需要做滑动门或相似的技术,增加代码的复杂度。
然而,我们这里如果把图切成透明gif图,并且左右覆盖,就会减小步骤之前的耦合性。
于是,自然而然,想到了这样的切图方式:

看上去三种步骤,和对应的current状态,应该可以实现了。
实际写CSS的时候,问题出来了,因为这样的切图,需要前面的步骤的图片去覆盖住后面的步骤,即使定义z-index来控制z轴优先级,也不能完全解决问题。具体来说,可以让步骤1覆盖住步骤2,但要让步骤2覆盖住步骤3,就不可行,因为我们期望兼容中间步骤可以无限多,应用了相同的class,也就表明会有相同的z-index,这样必然的结果是,后面的步骤覆盖前面的步骤。

所以脑子拐个弯,逆向切图。

这样,只要设置负的margin-left,让后面的覆盖住前面,就达到了预期的效果。
考虑到最后一个步骤是两头都有不同表现的,需要用到滑动门或者hook,这里我用了hook。于是HTML代码改造如下:

<ul>
	<li class="first-current">1 填写店铺信息</li>
	<li class="middle">2 填写联系人信息</li>
	<li class="middle">3 确认创建信息</li>
	<li class="last">4 提交成功<span class="hook"></span></li>
</ul>

第三步
CSS,写起来就一气呵成了

div.form-nav {border-bottom:3px solid #E77302;margin-bottom:10px;background:#F2F2F2}
div.form-nav ul li {height:29px;float:left;background-image:url(/images/eshop/form/step_arrow.gif);background-repeat:no-repeat;color:white;font-size:14px;font-weight:bold;line-height:29px}
div.form-nav ul li.first {background-position:0 0;padding-right:30px;padding-left:8px}
div.form-nav ul li.first-current {background-position:0 -150px;padding-right:30px;font-size:16px;padding-left:8px}
div.form-nav ul li.middle {background-position:0 -50px;margin-left:-20px;padding-right:30px;padding-left:22px}
div.form-nav ul li.middle-current {background-position:0 -200px;margin-left:-20px;padding-right:30px;padding-left:22px;font-size:16px;}
div.form-nav ul li.last {background-position:0 -100px;margin-left:-20px;padding-left:22px;position:relative;}
div.form-nav ul li.last span.hook {position:absolute;top:0;right:-20px;width:20px;height:29px;display:block;background:url(/images/eshop/form/step_arrow.gif) no-repeat right -100px;}
div.form-nav ul li.last-current {background-position:0 -250px;margin-left:-20px;padding-left:22px;position:relative;font-size:16px;}
div.form-nav ul li.last-current span.hook {position:absolute;top:0;right:-20px;width:20px;height:29px;display:block;background:url(/images/eshop/form/step_arrow.gif) no-repeat right -250px;}

这儿提供完整的demo

30 Responses to “一个导航的前端实现”

  1. gvtbs 说:

    不太好我给你我的结构:

    1 填写店铺信
    2 填写联系人信息
    3 确认创建信息
    4 提交成功

    样式我不写了

  2. 明城 说:

    也可以参考淘宝 B2C 的步骤条,不过我个人觉得结构上用 OL 合适些,因为是前后有序的

  3. sknol 说:

    学习了,谢谢分享:)

  4. M 说:

    如果把交叉区域以及两端的切出来,其他用1px平铺岂不是更省资源?

  5. 一瞬 说:

    嗯,和淘宝商城手机充值导航一个方法。

  6. 大米 说:

    to明城,淘宝那个购买的进度条我之前也注意到并firebug过。html结构ok,css比较糟糕,针对每个step写class,如果100个step,css就疯了。

    to M,从节约带宽的角度来考虑这个问题,你的方法最优。同时从代码结构和切图角度看,都不够优雅,css没细想。如果后端开发套页面,容易套错。伟大的web标准指引我们要用最简单的html来表现业务逻辑,把表现逻辑让给css来处理。

  7. bulin 说:

    我是路过给大米负荆请罪的
    这个BT的步骤条激发了大米同学无限的创造力@_@

  8. 不再等待 说:

    直接 在ul 下 加背景不是OK?

  9. suntear 说:

    我也做过跟这个差不多的,其实没必要想这么复杂。

  10. suntear 说:

    就是用margin-left:-xxx的方法

  11. Alex.o0 说:

    偶来踢馆的
    我弄了个更精简的方案
    http://www.wishtree.org/nav/

    这个导航比较bt的地方就是两边的圆角
    所以要么给两头的li加个不同的样式要么用额外的html标签来区分
    考虑到后端开发套页面的便利 这里给两头的li加了额外的html标签(虽然html“不够优雅”,不过大米同志也是这么弄的)
    背景图用了两张(也可以合成一张,不过体积会大那么一点点)

  12. Alex.o0 说:


    留言咋没显示?

  13. 大米 说:

    给整个ul加背景是个不错的方案,谢谢各位的热情回复。

    to Alex,我们回复需要后台审核才出来,下次改版在提交回复的地方说明一下,不然会误解。

  14. 大仙 说:

    很好的东东,收下了,得空研究研究。

  15. hax 说:

    问个无关的事情。右侧有一帮阿里巴巴系的ued团队blog,能不能搞个聚合站点啊?我一个一个看过来,累啊。

  16. baljeans 说:

    楼上的好想法。。。

  17. 熊猫 说:

    既然是有明显先后顺序的,为什么不用ol呢?

  18. Bourne 说:

    可以搞个聚合的,然后每个团队的文章子类启用不同的二级域名

  19. 小当 说:

    Alex.o0的精简方案非常棒,思路很精巧,赞一个!

  20. 蚂蚁线 说:

    是一个很不错的思路,以后肯定有很多地方用的上!谢谢LZ

  21. shiny 说:

    f-dev.com域名在停靠?
    域名被卖了?

  22. yeyi 说:

    完全对网络资源的浪费,写一堆CSS,用一堆的图片

  23. Jackie 说:

    实用,就是有些浪费资源。

  24. 则名 说:

    其实一张图做四种状态就ok

  25. zhixiao 说:

    果然跟TAOBAO,ALIPAY的前端有很大差距,快点招人吧.

  26. diego.wu 说:

    为什么IE6没有效果?FF,TT都没有问题.

  27. noname 说:

    这种效果也需要这么复杂?4种状态不就ok了?

  28. 大米 说:

    不少提到一个图4个状态的做法,开发简单了,维护移植复杂了。举个例子,啥时候需求说要去掉一步,变成三步。不同做法的成本收益比可以根据项目本身特点自行考量。

  29. [...] 原文:http://ued.koubei.com/?p=435 [...]

  30. aksoft 说:

    这是不是太复杂了?

Leave a Reply