迭代式开发流程

某周末在朋友家头脑风暴之后的产物。

流程化了许多开发中遇到的问题都可以解决。

角色安排上貌似还有揣摩的地方,有空再pk。

time_boxes

一个菜单的优化经历

最近的项目在多次修修改改之后遗留下了一个悲剧的一二级菜单,html结构混乱不说,还用了N多全局变量,N多脚本去制作切换的效果。所以决定着手重构之。

首先考虑是最激进的方法。只用CSS实现,具体的实现看这里

重构后的效果 -> 这里

除了hover的时候反应速度很快以外也没啥问题了。

后来收到一个feedback

menu_bug

用户从“Bug”按钮移动到“Search bug”的时候,会触发到“报表”的hover效果,以至于难以点到“Search bug”的按钮。

这里可以体验一下)

第一时间想到的是延迟hover的效果,查了一下相关资料未果,于是写下代码(用到了Jquery):

function navSwitcher(){
var topNav = $(“#navigation li.menu”);
topNav.hover(
function(){
var item = $(this);
setTimeout(function(){item.addClass(‘menu_hover’);},300);
},
function(){
var item = $(this);
setTimeout(function(){item.removeClass(‘menu_hover’)}, 300);
}
);
}

想法是用setTimeout延迟一下hover的效果,测试时候又发现了个问题,如果从一个按钮快速移动另外一个按钮再移回原来的二级菜单,会触发一个死循环。。

如果每次mousehover与mouseover的的时候clearTimeout一下应该可以解决问题了,于是修改了一下代码,顺便调整了timeout时间优化使用体验,完整的Demo可以到这里查看

代码如下:

function navSwitcher(){
var topNav = $(“#navigation li.menu”);
topNav.hover(
function(){
var item = $(this);
clearTimeout(item.data(‘timeout’));
var t = setTimeout(function(){
item.addClass(‘menu_hover’);
},100);
item.data(‘timeout’, t);
},
function(){
var item = $(this);
clearTimeout(item.data(‘timeout’));
var t = setTimeout(function(){
item.removeClass(‘menu_hover’)
}, 200);
item.data(‘timeout’, t);
}
);
}

嗯。。代码有点丑陋。。不过当我尝试把他封装一下时候发现会额外消耗5ms左右的时间。。于是还是这样好了,
在我的机器上FF3的测试结果:
script_time

尚在可以接受的范围:D

于是此次优化工作暂告一段落。

CSS实现多浏览器横向级联菜单

最近项目在优化前端代码的时候到了一个匪夷所思的地步,于是把动态菜单的js也喀嚓了,用CSS实现

主要是用a:hover的原理,Test了一下IE6 7 8 chrome FF 都兼容。
暂时只支持两级。

到这里可以查看这个小Demo

IE6下有个小bug,如果a:hover跟a的标签没有任何改变的话触发不了hover效果,所以把position:relative写在a:hover里边了

PS:临时测试,css代码胡乱写了….

<ul>
<li>
<!–[if IE 6]><a href=”#”><table><tr><td><![endif]–>
<a href=”#”>菜单1</a>
<p>
<a href=”#”>子菜单1</a>
<a href=”#”>子菜单2</a>
<a href=”#”>子菜单3</a>
</p>
<!–[if IE 6]></td></tr></table></a><![endif]–>
</li>
<li style=”background-color:#9FF;”>
<!–[if IE 6]><a href=”#” style=”background-color:#9FF;”><table><tr><td><![endif]–>
<a href=”#”>菜单2</a>
<p>
<a href=”#”>子菜单4</a>
<a href=”#”>子菜单5</a>
<a href=”#”>子菜单6</a>
</p>
<!–[if IE 6]></td></tr></table></a><![endif]–>
</li>

用CSS截断过长数据

总结了一下大概有以下几种:

1.定宽截断

.demobox{
  width:200px;
  overflow:hidden;
  height:2em;
  line-height:2em;
  word-break:break-all;
  text-overflow:ellipsis; /* IE中截断后加上... */
  white-space:nowrap;     /* 不换行 */
}

效果:
css-cut-01
如果不考虑长字符串的情况那么只需要 overflow:hidden和height属性就可以了,把换行的数据都hidden掉,间接实现截断效果,嘿嘿。

PS: FF中去掉white-space:nowrap属性就不会出现截断半个中文字的情况了

2.自适应宽度截断

如果内容有长字符串或者是加了white-space:nowrap的话,那么是会把外部容器撑破的,于是就不能自适应宽度截断了。

这里我利用了一下table的table-layout:fixed来间接实现。table在fixed模式中,td(或th)不会因为里面内容的大小而改变大小。[Gmail和QQmail的邮件列表都是采用这种方法 :D ]

先简单看一下效果:

css-cut-02
table用了fixed模式并且设置了width:100%,那么table以及td的宽度就只有200px了,溢出的内容用overflow:hidden隐藏掉,于是便实现了自适应宽度的截断效果。
当然这方法也是有弊端的,首先为了实现效果把html结构弄复杂了,其次是(看下图)
css-cut-03

截断的单元格与旁边的数据贴得太近了,并且padding-right是控制不了的。Gmail用了个十分懒的方法,在两个td中间塞多一个空白的td把两列数据分开,看起来会美观些。而QQmail是在次列td里面放置一个div元素,设置适当的margin把截断的数据撑开,让数据看起来不会连成一块。我决定塞个&nbsp进去好了,省事 :D

Tui css framework is available.

为了偷懒加快工作效率,早在半年前我就决定写一个CSS框架,到今天….它终于可以用了!

恰好公司正在折腾web栅格布局 ,所以也顺便一起整了。

说起CSS框架常见的有倡导栅格布局的 960grid 以及taobao的grid css(不知正名为何),还有特立独行的YUI(YUI中用em定宽以及负margin的使用方法十分令偶向往)。

于是综合了各框架的一些设计理念及实际情况,在YUI基础上修改开发了自用css框架tui….

主要是重写了YUI中的一些宽度数值,去掉一些不常用的css,添加一些ooxx。

目前TUI的功能有

  • 支持页面宽度:自适应、950px、974px、1190px
  • 左右侧边栏宽度:150px、190px、230px、270px、310px
  • 百分比布局:与YUI3.0相同(修改中)
  • 简单的css-reset

YUI中font-size是设置成13px的,印象中中文宋体在12px、14px中的显示效果会比较好。所以像素级测试了一下。

发现宋体在12px、13px的时候其实都是一样大的。唯一的区别是的13px的字宽比12px大1px,说白了就是字与字间多1px的间隔。并且相比13px,我觉得12px太挤了,看起来有点视觉疲劳。

于是Tui中沿用YUI的13px设定。(只在vista、win7中测试,不知未开启clearType的机子会咋样)

同学们到这里可以查看简单的Demo   <-[2010/6/16失效]

赌博问题研究

常有云“十赌九输”,某日针对这问题稍微研究了一下。

假设在丢筛子投大小的场景,赌徒投错了将失去该局的所有押金,中了不但能取回押金还能获得跟押金等额的金钱。

那么赌徒一直押小,第一次10元,如果输了次回押20元,以此类推40、80、160……那么只要押中一次,赌徒不但能拿回之前输的赌金,还能赢10元。只要押中一次便从10元从新押起。那么这样看来赌徒会一直赢下去。

针对次问题我们建立一个数学模型,最低押金X0,每场押金Xn,赔率Y(Y>1),每场胜利赌徒希望赢得的金钱Z,那么可以得知

Xn=(X0+Z)[y^(n-1)]/[(Y-1)^n]

那么回归到刚才的场景,假设连续开了9次大,押金就高达2560元了。显然赌徒一直赢钱的情况只会出现在赌徒有无限金钱的情况下。并且通过Xn的表达式不难看出,庄家可以通过提高最低押金X0,降低赔率Y、降低押金最大值的方法来获得更大的收入。

拉斯维加斯一家赌场的VIP房间设置了100$最低押金以及15000$的最高押金,如果采用上面的方法连续开出8次大的话将失去12800$赌金,而这个几率高达 0.5^8 = 1.56%  , 接近十赌九输了 :D

模块化CSS设计(一) – 图标

前言:

最近半年多的时间里我都在参与TAPD项目的设计与前端开发。之所以把设计和前端开发一起承担主要是考虑到一种较为理想的设计流程,在进行设觉设计 的同时把Html、CSS的实现都考虑进去,这样无论是设计还是代码都是统一的设计理念和风格,便于维护和后续开发。后来发现TAPD的规模远大于自己所 想,交互研究、视觉设计、代码设计每一部分都是一份庞大的工作,每个页面的设计与实现都没有太多的时间仔细琢磨…还好后期英明的Boss把设觉与交互 设计部分交给了其他同事,我才得以对前端代码仔细研究,用了一个月的时间把所有Html与CSS进行重构。

本系列文章将跟大家分享我在TAPD项目上关于CSS架构设计的一些心得,譬如命名、灵活性等,不会涉及太多CSS技巧。

由于是想到什么就写什么,各章节之间没有什么必然的联系,希望大家看后有能有所收获。m(_ _)m

-  by ceil  2009/5/11

模块化CSS设计(一) --- 图标

一般来说页面上的图标会用下边的两种形式撰写:

<a href=”#” title=”Edit”><img src=”[url]” alt=”Edit” /></a>

<a href=”#” class=”btn_edit” title=”Edit”>Edit</a>

前者:直接插入图标的图片,好处是该按钮是inline-block,可以很方便的插入到页面任何地方。譬如说放到一段文字的中间。

Example_01

Example_01

后者:用CSS背景定位的把图标显示出来,并且把Edit文字隐去,相比前者降低了表现与逻辑的耦合性,更好的Html语义化。不过为了让图标有高度和宽度,一般情况会 把<a>加上display:block,然后用background-image把图标放进去。那么弊端也是显而易见的,假设我需要把一个 图标插入到一句话的中间,那么由于display:block的存在会直接导致图标与其他文字换行显示。

Example_02

Example_02

综合两者的优点,我在TAPD中是这么定义一个图标的:

<a href=”#” class=”tag_bug”><i>Bug</i></a>

CSS

CSS

这样TAPD的图标的不但具有<img>形式的灵活性,同时减少耦合性、更好SEO、更好的HTML语义化…etc

(因为要兼顾IE6/7/8、Firefox、Safari、Chrome中display:inline-block的实现,所以迫不得已要额外加一个<i>标签用于将文字隐藏。)

按照yahoo的rules for high performance web sites的原则,应当减少Client与Server端间的HTTP请求次数。

我还用到CSS Sprite,将多张图标图片组装成单独的一张图片,用background-position显示不同的图标

CSS Sprite

CSS Sprite

也许有人会问:

<a class=”btn_edit”></a>

这么写不会更简单么?并且可以减少html和CSS代码?何必要写成<a class=”btn_edit”><i>Edit</i></a>

其实我坚持在标签里写文字一方面是基于SEO的考虑,另外还考虑到一种情况,假设突然有一天我们的客户觉得编辑按钮图标太糟糕了!要求直接直接用文字。那么我稍微修改一下CSS文件便可以巧妙的把原来的图标变成一个文字链接了。又或者是客户由于某些原因访问不了TAPD的CSS文件,标签里没有文字的会变得一片空白,无法使用。

Example_04

Example_04

另外由于IE6对透明背景的PNG图片支持不好,所以大部分不规则图标我都是用gif格式。但是有时候gif的256色不能满足设计师的设计要求(设计师A:俺的作品多姿多彩,256色怎么够用!!)。

所以在CSS sprite的时候我是合成了两张图片,一张对色彩要求不高并且需要透明背景的GIF图片和一张对色彩要求高的PNG图片。

前端开发是个体力活

debug
最近在调试某页面的style时发现,居然要开着6个浏览器。。 IE6,7,8, firefox ,safari ,google chrome…
每次改完代码就要刷新6个浏览器看看新的样式或js有没bug。然后就这么重复刷啊刷啊,F5啊 F5…折腾个几小时。
虽然有时候有信心写的代码在各个浏览器浏览都没问题,可能还是会很神经质的再去刷新一遍,然后看到意料之中的结果才安心的继续写代码… 囧

CSS expression在IE6的诡异问题

<body><div id=”page-wrapper”><div id=”header”>标题内容…</div></div></body>

以上是最近的项目里的html结构,其中page-wrapper是自适应页面大小的,header是存放页面的标题(height:60px;)。根据客户的需要,该页面是自适应浏览器大小,并且有一个最小的宽度。于是我这么对page-wrapper这么写到

#page-wrapper{
position:relative;
min-width:974px;
width:expression(((document.compatMode && document.compatMode==’CSS1Compat’) ? document.documentElement.clientWidth : document.body.clientWidth) < 974 ? “974px” : “auto”);
}

鉴于IE6中没有min-width,所以我尝试使用一下css expression这个只有IE支持的CSS属性。里面是一段JS,当page-wrapper的宽度小于974px的时候把宽度设置成974px,以实现Ie6下的min-width。为什么会有个position:relative ? =.= 这个是手误,很久以前需要实现一些效果忘记删掉了。

于是问题就出来。该页面在IE6下当浏览器窗口最大化时page-wrapper里面所有的内容会消失,再缩小到原本大小的时候内容又出出现。囧rz

最后诊断的结果是 ,当 header的height:60px;与page-wrapper的position:relative;和css expression同时出现并且页面是自适应大小的话在IE6下便会出现最大化的时候页面内容消失的诡异问题。

这问题出现的必要条件也太恶心了。。。估计也没多少人能遇上。。。。

于是决定面壁思过。。远离肥猪流。。

#page-wrapper{
min-width:974px;
_width:expression(documentElement.clientWidth< 974 ? “974px” : “auto”);
}

(_width仅为IE6识别) 虽然很不想用CSS hack,但我认为这不失为一个便捷的方法。我不希望添加非IE6浏览器解析css的负担。

IE6下width:100%的BUG

Mark一个今天遇到的问题:

<div class=”page_wrapper”>
<div style=”margin:30px;” class=”table_wrapper”>
<table width=”100%”>数据</table>
</div>
</div>

这样的结构的时候在Ie6中的table会错误的把page_wrapper当作100%的参考对象,于是会把table_wrapper撑破(比预想效果多60px宽度)。

解决方法就是给table_wrapper加上 width:100% 就ok了