jQuery 1.3.3新功能抢先预览

2009年5月29日 – 18:04

jQuery 1.3.3发布的日子日趋临近,各种新功能逐渐浮出水面(我咋像在写小说……)

改进了toggleClass()/hover()/live()/index()等方法,总之可以进一步简化代码了。

废话不多说了,直接上链接,有兴趣的同学直接去Cloudream那里看就可以了:
http://www.5iya.com/blog/post/jquery-1-3-3-new.asp

禁用脚本时显示元素——再从前端角度浅谈产品设计中的可用性和可访问性

2009年4月28日 – 01:44

三个月前,老鱼在其博客和支付宝UED博客中发表了浅谈产品设计中的可用性和可访问性
文中阐述了这样一种状况,页面上有元素需要暂时隐藏以避免过多的信息对用户产生干扰。而隐藏的信息需要通过脚本的交互显示出来,以增强可用性。那么对于不启用脚本的用户,如何保证可访问性的问题。
文中提到两种方案:

实现方案1:采用css样式设置企业注册信息的容器默认为隐藏,当用户点选企业后通过js脚本改变容器的隐藏属性为显示。
实现方案2:通过脚本控制企业注册信息的容器的初始状态为隐藏,当用户点选企业后通过脚本改变容器的隐藏属性为显示。

方案一的缺点在于无视可访问性
方案二的缺点在于“要在页面结构加载完成后,再去初始化要隐藏的容器,当客户端网速不佳的情况下,会先显示企业注册信息的内容,几秒后又不见了,体验上有所折扣。”

我又在文章的一楼评论中提出了两个方案:解决了第二个方案的缺点

实现方案3:把脚本直接紧跟着需要隐藏的元素后面
实现方案4:在页面头部最开始的地方写入脚本,这个脚本用于生成隐藏元素的css代码。

方案三的缺点在于结构行为和样式的高度耦合,非常不利于维护,且易被同行耻笑。
方案四比上面略好,但同样由于行为和样式的混杂,不利于维护。

还有这位兄弟提出的

实现方案5:用脚本给body加上个class,所有需要隐藏的元素的CSS都用这个class开头,比如 .js #id{display:none;}

今日又发现新思路,利用noscript标签。这个圡圡的标签。这本来应该是最先想到的,却似乎思维被僵化了,一味从JS和CSS角度去看了,忽略了HTML本身。

实现方案6:首先使用方案一,直接用CSS隐藏元素,然后再方案一的基础上,增加noscript标签,其中的再写入CSS用来覆盖先前的CSS。(演示代码代码在本文结尾)

是的,就这么简单、这么的圡,但很有效。对于 IE 6 和 Firefox 3测试通过。Chrome上我找不到关闭脚本的选项,故未经测试。

当一切看起来这么美好的时候,放到W3C的验证里边就有麻烦了,XHTML下他说noscript不能没有object?我很晕,然后放上object后他又说style不能放在这里,只能放在head里。我换用了link也一样报错。换了html 4也没有好转。
我在XHTML的描述中没有找到相关内容 http://www.w3.org/TR/xhtml1/
而在HTML 4.01中发现,http://www.w3.org/TR/html401/interact/scripts.html#h-18.3.1
然后我纳闷了一下,里边并没有提到noscript里不能放style和link。进一步考据,找到http://www.w3.org/TR/html401/struct/links.html#h-12.1.3
这里提到

The LINK element may only appear in the head of a document.

又找到 http://www.w3.org/TR/html401/present/styles.html#h-14.2.3

The STYLE element allows authors to put style sheet rules in the head of the document.

但无论如何,我head里放个noscript,里边再带个style或者link就不让我通过验证了!什么世道!

当然,这么2的事情,W3标准的制定小组早就想到啦! 在HTML 5中,这个问题将会被解决。可以参考这里: http://www.w3.org/TR/html5/semantics.html#the-noscript-element。同时代码页成功通过了验证。

标准这种东西我向来就把他当作迷信一样,不可不信也不可全信。对于这个问题,我宁可不遵守。因为无论从技术实现,还是语义化HTML,抑或者可用性角度来看,这都是个完美的解决方案,我不想被标准这个玩意所束缚。一方面现在主流的浏览器都支持,没有兼容性问题,另一方面将来的标准也支持这种做法,何乐而不为呢?

两种情况下不适合用方案六:
1,你是极端完美主义者。
2,你的老板或者客户只认W3C验证。

测试地址:
http://shawphy.com/demo/noscript-for-css.html
直接到W3C接受检验:
http://validator.w3.org/check?uri=http://shawphy.com/demo/noscript-for-css.html
附代码,我为了方便其间,用了HTML 5的doctype:

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5.     <title>用noscript在禁用脚本时显示元素</title>
  6.     <meta name="generator" content="editplus" />
  7.     <meta name="author" content="Shawphy(shawphy.com)" />
  8.     <style type="text/css">
  9.         div{display:none;}
  10.     </style>
  11.     <noscript>
  12.         <style type="text/css">
  13.             div{display:block;}
  14.         </style>
  15.     </noscript>
  16. </head>
  17. <body>
  18. <div>
  19.     你看不到
  20. </div>
  21. <a href="http://validator.w3.org/check?uri=http%3A%2F%2Fshawphy.com%2Fdemo%2Fnoscript-for-css.html">到W3C验证</a>
  22. </body>
  23. </html>

文字竖排

2009年4月13日 – 21:36

今日闲逛,走到了维基文库水调歌头 (明月几时有),恰巧发现他居然是文字竖排的,很有兴趣一看。

网上目前两种方法竖排,
一种是用 writing-mode:tb-rl;
另一种是用 layout-flow: vertical-ideographic;
但遗憾的是,这两种方法都基本是 IE Only 的……
那么维基文库是如何做到的呢?随便翻看一下代码,恍然大悟~

  1. <div style="font-size:xx-large;font-weight:bold;line-height:1em;width:1.5em; float:right;">水調歌頭</div> 
  2. <div style="width:1.5em; float:right;"> </div> 
  3. <div style="width:1.5em; float:right;">蘇軾 </div> 
  4. <div style="width:1.5em; float:right;"> </div> 
  5. <div style="width:1.5em; float:right;">明月幾時有 </div> 
  6. <div style="width:1.5em; float:right;">把酒問青天 </div> 
  7. <div style="width:1.5em; float:right;">不知天上宮闕 </div> 
  8. <div style="width:1.5em; float:right;">今夕是何年 </div> 
  9. <div style="width:1.5em; float:right;">我欲乘風歸去 </div> 
  10. <div style="width:1.5em; float:right;">又恐瓊樓玉宇 </div> 
  11. <div style="width:1.5em; float:right;">高處不勝寒 </div> 
  12. <div style="width:1.5em; float:right;">起舞弄清影 </div> 
  13. <div style="width:1.5em; float:right;">何似在人間 </div> 
  14. <div style="width:1.5em; float:right;"> </div> 
  15. <div style="width:1.5em; float:right;">轉朱閣 </div> 
  16. <div style="width:1.5em; float:right;">低綺戶 </div> 
  17. <div style="width:1.5em; float:right;">照無眠 </div> 
  18. <div style="width:1.5em; float:right;">不應有恨 </div> 
  19. <div style="width:1.5em; float:right;">何事長向別時圓 </div> 
  20. <div style="width:1.5em; float:right;">人有悲歡離合 </div> 
  21. <div style="width:1.5em; float:right;">月有陰晴圓缺 </div> 
  22. <div style="width:1.5em; float:right;">此事古難全 </div> 
  23. <div style="width:1.5em; float:right;">但願人長久 </div> 
  24. <div style="width:1.5em; float:right;">千里共嬋娟 </div>

虽然代码不是很优雅(自动生成的……)但大概意思也知道了。设置宽度为1.5倍的字宽,保证列距,然后让所有div右浮动。
很简单又很有用的技巧,兼容各个主流浏览器~

最后引用一句,对于IE“不應有恨……”,他有些私有属性还是挺有趣的……
(注:原文中“恨”是遗憾的意思。)

控制函数队列

2009年4月5日 – 17:12

前一篇文章中探讨了关于jQuey中队列控制的两个函数 queue 和 dequeue,这两个极大方便了我们编写一些有时间差、并非立即执行完毕,却对次序要求很高的代码。

这里我再发布一个自己编写的处理队列的代码
注:这里的代码行为与jQuey的代码行为不完全一样!

测试页面: http://shawphy.com/lab/myqueue.html

  1. var myQueue=function(fnArr){
  2.     //将队列放入fnArr
  3.     this.fnArr=fnArr||[];
  4. };
  5. myQueue.prototype={
  6.     fnArr:[],
  7.     queue:function(fn) {
  8.         //如果是函数数组,则依次放入
  9.         if (fn[0]) {
  10.             for (var i=0; fn[i];this.fnArr.push(fn[i++])){}
  11.         } else {
  12.             this.fnArr.push(fn);
  13.         }
  14.     },
  15.     dequeue:function() {
  16.         //弹出剩余的第一个函数并执行
  17.         (this.fnArr.shift()||function(){})();
  18.     },
  19.     clear:function() {
  20.         this.fnArr=[];
  21.     }
  22. };

用法:
用new 创建一个实例:

  1. var foo=new myQueue()

或者带一个函数数组:

  1. var foo=new myQueue([
  2.     function() {
  3.         test.innerHTML+=1;
  4.         setTimeout("foo.dequeue()",1000);
  5.     },
  6.     function() {
  7.         test.innerHTML+=2;
  8.         setTimeout("foo.dequeue()",1000);
  9.     }
  10. ]);

还可以再添加一组或者一个函数

  1. foo.queue([
  2.     function() {
  3.         test.innerHTML+=3;
  4.         setTimeout("foo.dequeue()",1000);
  5.     },
  6.     function() {
  7.         test.innerHTML+=4;
  8.         setTimeout("foo.dequeue()",1000);
  9.     }
  10. ]);
  11.  
  12. foo.queue(function() {
  13.     test.innerHTML+=5;
  14.     setTimeout("foo.dequeue()",1000);
  15. });

开始执行当前队列中的第一个函数:

  1. foo.dequeue();

清空队列:

  1. foo.clear();

jQuery中queue和dequeue的用法

2009年4月5日 – 16:28

jQuery中的queue和dequeue是一组很有用的方法,他们对于一系列需要按次序运行的函数特别有用。特别animate动画,ajax,以及timeout等需要一定时间的函数

queue和dequeue的过程主要是:
1,用queue把函数加入队列(通常是函数数组)
2,用dequeue将函数数组中的第一个函数取出,并执行(用shift()方法取出并执行)

也就意味着当再次执行dequeue的时候,得到的是另一个函数了
同时也意味着,如果不执行dequeue,那么队列中的下一个函数永远不会执行

对于一个元素上执行animate方法加动画,jQuery内部也会将其加入名为 fx 的函数队列
而对于多个元素要依次执行动画,则必须我们手动设置队列进行了。

一个例子,要两个div依次向左移动,点击这里查看

  1. div {
  2.     background:#aaa;
  3.     width:18px;
  4.     height:18px;
  5.     position:absolute;
  6.     top:10px;
  7. }
  1. <div id="block1"></div>
  2. <div id="block2"></div>

如果只是轮流移动次数较少,可以使用animate的回调函数来做,一个动画放在另一个动画的回调里边
比如

  1. $("#block1").animate({left:"+=100"},function() {
  2.     $("#block2").animate({left:"+=100"},function() {
  3.         $("#block1").animate({left:"+=100"},function() {
  4.             $("#block2").animate({left:"+=100"},function() {
  5.                 $("#block1").animate({left:"+=100"},function(){
  6.                     alert("动画结束");
  7.                 });
  8.             });
  9.         });
  10.     });
  11. });

但这种方法当动画较多的时候简直是残忍。

此时利用queue和dequeue则显得简单很多:

  1. var FUNC=[
  2.     function() {$("#block1").animate({left:"+=100"},aniCB);},
  3.     function() {$("#block2").animate({left:"+=100"},aniCB);},
  4.     function() {$("#block1").animate({left:"+=100"},aniCB);},
  5.     function() {$("#block2").animate({left:"+=100"},aniCB);},
  6.     function() {$("#block1").animate({left:"+=100"},aniCB);},
  7.     function(){alert("动画结束")}
  8. ];
  9. var aniCB=function() {
  10.     $(document).dequeue("myAnimation");
  11. }
  12. $(document).queue("myAnimation",FUNC);
  13. aniCB();

1,我首先建议了一个函数数组,里边是一些列需要依次执行的动画
2,然后我定义了一个回调函数,用dequeue方法用来执行队列中的下一个函数
3,接着把这个函数数组放到document上的myAnimation的队列中(可以选择任何元素,我只是为了方便而把这个队列放在document上)
4,最后我开始执行队列中的第一个函数

这样做的好处在于函数数组是线性展开,增减起来非常方便。
而且,当不要要继续进行接下来动画的时候(比如用户点了某个按钮),只需要清空那个队列即可。而要增加更多则只需要加入队列即可

  1. //清空队列
  2. $(document).queue("myAnimation",[]);
  3. //加一个新的函数放在最后
  4. $(document).queue("myAnimation",function(){alert("动画真的结束了!")});

以前发过一个wait插件,用于让动画之间可以暂停一段时间
http://shawphy.com/2008/07/enabling-settimout-within-chained-functions-in-jquery.html
可以看一下,他也就是利用了这个原理,默认在fx中插入一个timeout,放到队列中,直到timeout结束后才执行dequeue继续执行队列中的下一个函数。

这当然也可以用于ajax之类的方法,如果需要一系列ajax交互,每个ajax都希望在前一个结束之后开始,之前最原始的方法就是用回调函数,但这样太麻烦了。同样利用queue添加队列,每次ajax之后的回调中执行一次dequeue即可。

如果没有使用jQuey库,也可以自己写段简易代码来解决这个问题。见控制队列函数

Learning jQuery 1.3 英文版样章试读

2009年3月21日 – 12:51

这是目录:
http://www.packtpub.com/article/learning-jquery-1.3-table-of-contents
第四章 效果 试读
http://www.packtpub.com/files/learning-jquery-1-3-sample-chapter-4-effects.pdf
在线购买地址:
https://www.packtpub.com/learning-jquery-1.3/book
有印刷版和电子版出售,售价不同。
我惊奇的发现原来中国大陆也是免运费的。

当心多余的逗号

2009年3月13日 – 23:01

今天看到jQuery Blog更新了 THIS WEEK IN JQUERY, VOL. 1 。里边提到一个tip ,说道经常有人问为啥写的代码在IE中运行错误,在其他浏览器下都能跑,原因是因为:

  1. var foo = {
  2.   bar: 'ice cream',
  3.   baz: 'luhrmann', // <-- get rid of that comma!
  4. }

对,就是多了个逗号。
我哑然一笑~
我昨天也正巧碰到了同样的情况,我firefox下运行一切正常,跑到同事的ie下就报错。回来查了半天才知道原来是多了个逗号。
有时候删除几个属性的时候就会忘了删除最后一个逗号了~~

BTW:我修复并保证在IE下正常运行后,同事的遨游下依然惊爆3个错误……我无视他了……罪过罪过……(遨游难道不是IE的马甲了么?)

打造自己的reset.css

2009年3月1日 – 04:14

0,引言
每每有新项目,第一步就是应当使用一个reset.css来重置样式。滥用不如不用,直接拿个现成的reset.css过来将导致后期各种离奇bug的发生。所以最好还是自己写一个reset.css,并且要明白每一条reset都是用来做什么的。reset.css本意就是重置样式,我始终建议把.clearfix放入layout.css,而把h1、h2之类的定义放进typography.css。 具体如何规划网站CSS结构,不在文本讨论之列,可以参考Smashing Magazine上的文章,国内有差强人意的中文译版。注意,本文把reset分成了两个部分,一个是纯reset.css,可以用于任何项目。另一个是用于特定项目的“reset”,自定义修改的内容,这些内容可以放在layout.css、typography.css之类的文件中,他们共同导入到一个base.css形成一个项目的基础样式。本文就是来介绍如何写一个合适所有项目的通用的reset.css,以及介绍在设置玩reset.css之后需要针对不同项目要首先要设置的内容。

1,基础
牛顿是站在巨人伽利略的肩膀上的,我们也可以这么做。首先我们要选定一个前进的基础。
请永远不要使用

  1. * { margin: 0; padding: 0; }

这问题太多了,在此不多加表述。

目前比较流行的有Eric Meyer的重置样式和YUI的重置样式。另有Condensed Meyer Reset简化Eric Meyer的样式。有趣的是,Eric的重置样式也是源于YUI的。而那份简化版又把Eric的样式简化回YUI的样式了 。但同时,糟糕的是,网上流传的比较广的(尤其是国内)都不是最新的版本。上面两个页面里直接看到的都不是最新的,Eric专门为有一个reset.css页面。而YUI当前版本(2.7.0)的reset.css实际地址里,比上面的页面中还多一些东西。此外,我们还可以基于一些常见的框架,比较著名的比如Blueprint或者Elements CSS Framework(这个的reset也是源自于Eric Meyer的)。OK,准备工作就差不多了。以上这些都可以作为参考资料来组织我们自己的reset。我这里主要采用YUI,兼带Eric的reset。

2,默认色彩
对于页面是不是有默认背景色和前景色,YUI和Eric有着不同的看法。
YUI重置背景色为白色而文字颜色为黑色。

  1. html {
  2.     color: #000;
  3.     background: #FFF;
  4. }

而Eric在当前最新版中让所有颜色为透明,他认为透明才是最原始的颜色。虽然他曾一度认为也应当设置白色背景色、黑色文字颜色。至于最后为什么改了,Eric并没有给出具体理由。

这个问题我基本认为是用户自定义的更重要还是你的设计更重要的问题。我个人的观点是,如果你的设计本身就是白色背景,那么不要设置背景。一小部分中高水平的用户,他们会自定义网页默认背景色。设置成他们喜欢的背景色,比如浅蓝色。基本常见的浏览器都提供了这个简单的功能。而我们的背景色重置则会破坏用户的选择——尽管这样能保证你的设计原汁原味的呈现给所有用户。当然我知道,更高端的用户会用Stylish之类的Firefox扩展来自定义页面。但不得不说,只会用“选项”来调背景色的用户更多,不是么?而同时,如果设计本身就有其他背景色,比如黑色、蓝色、绿色之类的,OK,这些设计当然可以设置背景色。但请不要放进reset.css里。这里是重置样式的地方,不是你设计的地方。请把你的设计放在更广袤的土地上。
所以,简单说来,NO,不要在reset中设置背景色。

那么,文字颜色呢?原则上来说,也是不应该设置文字颜色的。但是IE中的表单元素中legend这个对象比较特别,跟主题结合的比较紧密。legend会默认有自己的颜色(跟当前的主题有关)而不会继承父元素的颜色(即便设了color:inherit;)。
从某些角度来说,可以想当然地认为设置字体颜色人数远小于设置背景色的人数;以及认为就算设置了背景色,人们看到legend元素是黑色的也不会觉得奇怪。因此,YUI在其reset中设置了legend {color: #000;}是无可厚非的。
但反过来说,把这个放到typography.css或者form.css里岂不是更好?不同的页面设计,其对legend的色彩要求很可能是不同的,放在reset.css里重复定义是没有必要的。因此这条CSS规则可以作为在reset.css之后首先应当设置的规则。

3,padding和margin
曾经一度流行的* { margin: 0; padding: 0; }也就是出于这个目的。让各个元素的padding和margin都归零,尤其是那些h1和p以及ul/ol/li之类的元素,还有,body本身也是有margin的。清除元素的padding和margin是很有用的。
YUI这样做:

  1. body, div, dl, dt, dd, ul, ol, li,
  2. h1, h2, h3, h4, h5, h6, pre, code,
  3. form, fieldset, legend, input, button,
  4. textarea, p, blockquote, th, td {
  5.     margin: 0;
  6.     padding: 0;
  7. }

而Eric这样做:

  1. html, body, div, span, applet, object, iframe,
  2. h1, h2, h3, h4, h5, h6, p, blockquote, pre,
  3. a, abbr, acronym, address, big, cite, code,
  4. del, dfn, em, font, img, ins, kbd, q, s, samp,
  5. small, strike, strong, sub, sup, tt, var,
  6. b, u, i, center,
  7. dl, dt, dd, ol, ul, li,
  8. fieldset, form, label, legend,
  9. table, caption, tbody, tfoot, thead, tr, th, td {
  10.     margin: 0;
  11.     padding: 0;
  12.     border: 0;
  13.     outline: 0;
  14.     font-size: 100%;
  15.     vertical-align: baseline;
  16.     background: transparent;
  17. }

可以看到,Eric把几乎所有的元素都写上了规则。而YUI只把有padding和margin的元素清空样式,而其他元素则不动。我个人比较偏好YUI的做法,因为他这样可以避免给一些无关元素带上不必要的样式。导致元素过多时的性能下降。但Eric的也有可取之处,他这样写,整个reset.css可以小上不少字节,对服务器的压力会小一些。但进一步想,这种做法跟用 * 来选择所有元素还有什么区别呢?这已经几乎囊括了所有元素了!你怎么用呢?看你自己喜好了。

4,边框
YUI里:

  1. fieldset, img {
  2.     border: 0;
  3. }
  4. abbr, acronym {
  5.     border: 0;
  6.     font-variant: normal;
  7. }

Eric已经在上一条中把所有的边框都清掉了,还是推荐用YUI的,理由同上。

5,外边框(outline)
这个就是元素获取焦点时的虚线框,在ie之外的浏览器上可以像下面Eric做的那样,通过设置outline来消除。

  1. /* remember to define focus styles! */
  2. :focus {
  3.     outline: 0;
  4. }

而YUI则没有设置这一条。而在Eric的样式中,可以看到Eric的提醒:务必重新定义获取焦点后的样式!
这点其实很重要,出于可访问性的角度出发,那些不便于使用鼠标的人基本上都是用tab导航来浏览网页的。获取焦点的元素有特定样式的话可以极大帮助这类群体的用户,通常建议设置成跟:hover一样。经常设计上会因为这个虚线框而大打折扣。因此这条保留在reset中,并且作为reset.css之后及早定义的规则。

另外,对于在Firefox之类的支持outline的浏览其中,除了获取焦点的元素外,浏览器本身并没有给元素设置outline属性,所以,像Eric那样把所有元素的outline设成0,我就觉得没有太大必要了。

6,字体样式(font style/weight/size/variant)
YUI里,分成了多条:

  1. address, caption, cite, code, dfn,
  2. em, strong, th, var, optgroup {
  3.     font-style: inherit;
  4.     font-weight: inherit;
  5. }
  6.  
  7. h1, h2, h3, h4, h5, h6 {
  8.     font-size: 100%;
  9.     font-weight: normal;
  10. }
  11. abbr, acronym {
  12.     border: 0;
  13.     font-variant: normal;
  14. }
  15.  
  16. input, button, textarea,
  17. select, optgroup, option {
  18.     font-family: inherit;
  19.     font-size: inherit;
  20.     font-style: inherit;
  21.     font-weight: inherit;
  22. }
  23.  
  24. /*@purpose To enable resizing for IE */
  25. /*@branch For IE6-Win, IE7-Win */
  26. input, button, textarea, select {
  27.     *font-size: 100%;
  28. }

Eric则在他最终版的reset中去掉了关于这些的样式重置,只保留了 font-size: 100%; 同样他没有给出具体理由。
但通常情况下,我认为还是重置一下这些样式好,比如strong元素,很多时候只是语义而已,并非希望他真的加粗。可能会有背景色或者其他方式来强调。而之所以这里都用了inherit这个继承属性而不是定义 font-weight: normal; 可以在 Eric 先前的reset文章中看到。这是为了防止——父元素字体加粗了,而没有一个子元素继承加粗属性(因为设置了normal)——这种情况的发生。所以把YUI中设置h1-h6的样式以及abbr和acronym的两句样式都改成inherit会比较好。

此外,对于h1-h6的字体大小定义,建议放到专门的typography.css里,不建议放在reset.css里。所以这里我同样倾向于用YUI的策略,全部重置。

但是很不幸,在ie6/ie7当中,不论是strong还是h1-h6,亦或是em等元素,设置了inherit均无法继承父元素属性,依然保持自己的特色。这就带来了浏览器差异,样式重置本身是为了避免浏览器差异的,但现在带来了浏览器差异,是万万不可取的。对于这个问题我考虑了很久,到底是为了统一所有浏览器都重置成normal(YUI的想法),还是放弃重置这些元素,让他们顺其自然,来保证在所有浏览器中样式一样(Eric的想法)。我最后决定采用YUI的做法。因为,无论重置成normal还是不重置,这些元素都无法继承父元素属性。既然如此,那么退而求其次,保证这些元素都恢复到普通外观,避免在设计的时候还要重置样式。
不得不说,这种妥协是仅仅针对IE6和IE7的,也许在5年后,老板和客户都不要求支持IE7的时候,我们可以放心大胆得使用inherit了。

此外,YUI并没有给code kbd samp tt 这几个元素重置字体大小。但实际上在IE中,他们都会被缩小显示。所以此处应当给予重置font-size: 100%;

7,行高(line-height)
对于行高,YUI并没有给出重置定义,而Eric则给出了重置:

  1. body {
  2.     line-height: 1;
  3. }

行高默认所有元素都会继承的,所以给body设置行高为1就足够了。通常行高设为1时候,英文照常阅读,但中文就无法阅读了,行间距过于紧密导致容易看错行。通常在中文环境下得设置1.4到1.5才能是用户正常阅读。我建议是1.5,这样算出来的值也是整数。比如字体大小12px的时候行高是18px,字体大小16px时行高24px。看起来也会比较舒服。此外,还有一个不设置成1的重要原因是:IE下,行高为1时,中文字顶部会被削掉几像素,字体加粗时尤为明显。所以,重置的原则是好的,但切不可重置为1。

8,列表样式
YUI用了:

  1. li {
  2.     list-style: none;
  3. }

Eric用了:

  1. ol, ul {
  2.     list-style: none;
  3. }

尽管我没有测试出YUI的有什么问题,但我始终觉得设置ol和ul会比较稳妥。而且,波及的元素更少,性能应该更高一点。虽然下载量会多3字节。

9,表格元素
在表格方面,都比较统一。均是:

  1. /* tables still need 'cellspacing="0"' in the markup */
  2. table {
  3.     border-collapse: collapse;
  4.     border-spacing: 0;
  5. }

Eric还提醒到,需要在html中设置cellspacing=”0″ 来达到完美重置效果。
但此外YUI还设置了

  1. caption, th {
  2.     text-align: left;
  3. }

让caption和th元素不要居中。作为重置,是可取的。建议添加此规则。

10,上下标以及baseline
YUI写成

  1. sup {
  2.     vertical-align: baseline;
  3. }
  4.  
  5. sub {
  6.     vertical-align: baseline;
  7. }

似乎没有优化,不知道为何没有写到一起去。而Eric则在最开始那条中就已经定义。而其中的问题是,YUI这样定义了,但没有重置字体大小,这点是有所遗憾的。既然是重置样式,就彻底一些,所以建议改成这样的:

  1. sup, sub {
  2.     font-size: 100%;
  3.     vertical-align: baseline;
  4. }

同样对于Eric把所有元素都放到了Baseline上,包括上标下标。Eric的解释是,强制让设计师精确定位这些元素的垂直偏移。

11,插入和删除(ins/del)
对于这个问题,YUI直接清除了ins的下划线和del的删除线这两个文本装饰:

  1. del, ins {
  2.     text-decoration: none;
  3. }

而Eric保留了删除线:

  1. /* remember to highlight inserts somehow! */
  2. ins {
  3.     text-decoration: none;
  4. }
  5. del {
  6.     text-decoration: line-through;
  7. }

如何取舍?我选择Eric的,为什么我这里不追求完美的样式重置了呢?很简单,我这个reset的目标是为了让我们写页面的时候尽量避免浏览器默认样式,以及不同浏览器之间默认样式差异带来的问题。而del元素删除线的文本装饰,我相信没有人会反对的。有人会加上其他样式,比如字体变淡之类的,但对于del如此强语义的元素来说,没有什么比用删除线更能表达含义的了。而不像上面那个focus样式,未必人人喜欢虚线框。但似乎又没有什么浏览器默认不给del元素加删除线,故这条可以省略。
所以,这里我只重置ins样式,别忘了给ins元素在等下也添加一些样式。

12,引用元素的引号
某些浏览器中,q或者blockquote前后会出现引号。这个并不是谁都喜欢的。所以需要重置他。
YUI的比较简单,只重置了q:

  1. q:before,
  2. q:after {
  3.     content: '';
  4. }

而Eric则比较周到,把q和blockquote都重置了。

  1. blockquote, q {
  2.     quotes: none;
  3. }
  4. blockquote:before, blockquote:after,
  5. q:before, q:after {
  6.     content: '';
  7.     content: none;
  8. }

OK,就决定用Eric的了,对于样式重置,细致一点周到一点总没有错。

13,链接
对于链接,YUI和Eric都没有采取样式重置,但从我思考许久后还是决定把链接样式重置放进来。究其原因,还是因为样式重置一来要彻底,二来对于链接样式并非所有设计师都喜欢用下划线装饰。因此,我还是建议把链接的下划线重置掉。

  1. a {
  2.     text-decoration: none;
  3. }

但这样做有点粗糙。真正有下划线样式的其实只有 :link和:visited所以改成下面这样比较好:

  1. :link, :visited {
  2.     text-decoration: none;
  3. }

此外,对于链接颜色,可以作为reset后急需设置的规则来处理。直接放入reset.css中不是很合适。

14,我的重置样式
总结上面种种规则,这里给出一下我的CSS重置规则,BSD协议发布,请随意使用。测试样本(这个是从YUI那里复制过来的,感谢YUI为此做出的贡献。)
下载:reset.css reset-min.css

  1. /*
  2. Copyright (c) 2009, Shawphy(shawphy.com). All rights reserved.
  3. http://shawphy.com/2009/03/my-own-reset-css.html
  4. Based on YUI http://developer.yahoo.com/yui/reset/
  5. and Eric Meyer http://meyerweb.com/eric/tools/css/reset/index.html 
  6. Licensed under the BSD License:
  7. http://creativecommons.org/licenses/BSD/
  8. version: 1.1 | 20090303
  9. */
  10.  
  11. body, div, dl, dt, dd, ul, ol, li,
  12. h1, h2, h3, h4, h5, h6, pre, code,
  13. form, fieldset, legend, input, button,
  14. textarea, p, blockquote, th, td {
  15.     margin: 0;
  16.     padding: 0;
  17. }
  18. fieldset, img {
  19.     border: 0;
  20. }
  21. /* remember to define focus styles! */
  22. :focus {
  23.     outline: 0;
  24. }
  25. address, caption, cite, code, dfn,
  26. em, strong, th, var, optgroup {
  27.     font-style: normal;
  28.     font-weight: normal;
  29. }
  30.  
  31. h1, h2, h3, h4, h5, h6 {
  32.     font-size: 100%;
  33.     font-weight: normal;
  34. }
  35. abbr, acronym {
  36.     border: 0;
  37.     font-variant: normal;
  38. }
  39.  
  40. input, button, textarea,
  41. select, optgroup, option {
  42.     font-family: inherit;
  43.     font-size: inherit;
  44.     font-style: inherit;
  45.     font-weight: inherit;
  46. }
  47. code, kbd, samp, tt {
  48.     font-size: 100%;
  49. }
  50. /*