从模块化CSS到面向对象的CSS

最近做了一个项目,尝试了一些以前未曾上尝试过的方法——基于模块设计整个网站的内容。做到后期才发觉如果初期的时候设计的更好一些,能做到面向对象的CSS来设计,那整体开发效率以及代码复用方面会做比现在好。现在的代码还是有点不干净的地方,有些地方有点乱。这可能是这行当的“完美主义”情结吧 :) 希望下次可以做的更好。

1.模块化问题

首先,什么是模块化?我这里指的模块化并非仅仅指CSS模块化,还指的是HTML的模块化。那为什么要模块化?最主要特点是使各个部分相对独立,同时增加代码复用,最终目的是为了降低开发成本提升开发效率。

举个例子,当拿到一个项目的时候,扫一遍所有设计,就可以发现:
哦,一共有10种侧边栏设计,设计师就是把这10种侧边栏翻来覆去放在不同的页面中。那就很简单了,只要完成了这10种侧边栏,那么就算100个1000个页面也都是一样的,只要把HTML复制,粘贴就可以了。最大化的实现的代码复用。

鬼哥写过一篇文章来阐述这个问题:
http://www.cssforest.org/blog/index.php?id=134

2.面向对象的CSS

当进一步观察,很容易发现,有侧边栏都是有一个标题,再下面是是主面板,再有一类侧边栏是标签页的,下面展示的是新闻之类的内容。这个时候就完全可以抽象出两个类,一个是带标题的侧边栏(title_box),另一个是带标签的侧边栏(tab_box)。这样的好处是可以进一步抽象出代码,提高复用率。增加开发速度。
比如前者的HTML可以是这样的:

  1. <div class="title_box">
  2.     <span class="act"><a href="#">更多</a></span>
  3.     <h3>标题</h3>
  4.     <div class="panel">
  5.         <ul>
  6.             <li><a href="#">新闻</a></li>
  7.             <li><a href="#">新闻</a></li>
  8.         </ul>
  9.     </div>
  10. </div>

可能的CSS是:

  1. .title_box {margin-bottom:10px;border:1px solid #aaa;}
  2. .title_box h3{border-bottom:1px solid #aaa;}
  3. .title_box .act{float:right}
  4. .title_box .panel{margin:0 10px;}

为了保证代码的简洁易读,一些小的padding或者背景修饰我就不写了。
其中act是action的意思,这里偷学来的XD

是的,以上的HTML以及CSS代码就共同构建了一个基本的侧边栏类
他所具有的特诊是有边框,下面空开10px,右上角还有个“更多”

有同学可能会问,我为何要把act类放在那个span上而不是a上?为何要把panel放在一个div上?放在ul上不是可以减少代码么?这里我之所以这样写,是为了最少代码与开发成本之间平衡的考虑。所有成本中,人力成本是最高的,服务器有钱都可以加,但是代码得更快速的写出来才是要紧的。这么写的话可以最大保证通用性。同时,另一个理论用于支持这种写法的是:只有无语义的div和span适合拿来做布局,而有语义的元素不应当参与到布局中。当然,我这里只是一种权衡。

这么写是很灵活的一种写法。如果不需要“更多”,直接删除即可,如果不需要标题,直接删除即可。进一步来看,这段HTML可以应用到整个网站各个地方而不仅限于侧边栏。只要是形式相同的地方都可以用。

3.进一步实现继承和扩展

这里带来的一个问题是如何控制宽度。侧边栏和正文部分宽度不同,有些地方需求又各异,如何保证宽度?跳出思维局限来看,是不是所有某一宽度的div都同属一类?是的,他们是同一类的,所以只要定好了宽度,继承就可以了!

如果应用了栅格化布局,就能很容易理解这一点,那么上面的代码就应该是这样的

  1. <div class="g5 title_box"></div>

前面的g5就代表了其占了5个栅格!这个模块首先是占了5个格子的宽度,然后他是一个带标题的模块。进一步看,如果这个格子在不同的地方背景色不同,那可以继承了前面两个类的基础上,再加上一个 bg_blue于是这就成了:

  1. <div class="g5 title_box bg_blue"></div>

没错,他就是一个占5个格子的带标题的模块,背景色是蓝色的。
好,可能他在某个地方是左浮动的,需要加上float:left,但不是所有的title_box都需要做浮动,那自然加上一个left类即可:

  1. <div class="g5 left title_box bg_blue"></div>

所以,挑选一个合适的基于栅格的框架很有意义,如YUI,BluePrint,或者OOCSS。
可以参考一下OOCSS,我很欣赏其中的思想
前端观察对其的介绍:http://www.qianduan.net/object-oriented-css.html

针对面向对象CSS的一个很好的PPT
http://www.slideshare.net/stubbornella/object-oriented-css

面向对象的CSS框架(OOCSS)的项目地址
http://wiki.github.com/stubbornella/oocss

我除了不喜欢其中到处都是为了圆角而设计的CSS之外,其他都很喜欢。

另外,写的时候,我搜索了一下,才发现这种思想08年初嗷嗷就已经有啦,我Out啦:
http://www.aoao.org.cn/blog/2008/01/oo-style/

4.这不是银弹

要坚信,在解决一个问题的同时必然会带来其他问题。

优先级问题
其中一个问题是优先级问题,由于模块细分,优先级很容易弄得焦头烂额。我的经验是每个类都负责一个部分——布局归布局,色彩背景归色彩背景。只有把各个类细分出来,才能避免样式的冲突。最后,id也是必不可少的。也需要important。比如上面,我就会定义一个noborder类,表示这个容器一定没有边框。用于个别地方是一个title_box但没有边框的情况。这个类里我就设置了

  1. .noborder{border:0 !important;}

这样就能保证在任何时候,都不会有边框了。

同时,我对于文件规划,通常是一个页面只引入这个页面的css,比如首页的index.css
在这个css里再用import依次导入用于
重置的reset.css(重置标签类,其实一个标签本身不就是一个类么?div类,span类,本身就具有block或者inline属性,我们只是在其上面在扩展而已)
global.css(用于设置header和footer以及中间主体部分的布局,因为这两个部分一般整站是不会变的)
layout.css(用于设置栅格,构建内容以及侧边栏的宽度等。)
module.css(用于建立如title_box这种中等模块)
submod.css(这里放一些细节的模块,比如某一个新闻列表的完整细节样式设定)
如果模块较多,还可能分成若干的子块,侧边栏放侧边栏,中间的放中间。因为我相信绝大多数情况下侧边栏将永远是侧边栏,而不会跑到中间去。
如果有必要,也会建立form.css,专门设置表单元素,定义表单元素的外观。我会在里边设置一些 blue_btn,red_btn之类的class来定义不同颜色的button.
而后,在这个首页的index.css里写特定的样式。
这种规划的方法在很多文章中都能见到影子,如今再回头看,又有了更深一层的体会。

另外,import有潜在的性能问题。见这里
只是我实在抵御不住import带来的便利性,在html里加入一堆的link是多么痛苦的事情。而且大多数时候对性能的要求没那么高,为此我宁可节约一点人力成本。这是种取舍,因网站需求而异。但总体顺序还是不变的。
而解决这个性能问题的方法是用 条件CSS,可以参考这里
这里
id与class
命名的时候到底是以id为主,还是class为主,想必各位同学看到这里也该明白在下的观点了——以class为主,id为辅。因为同一段HTML可能用到页面的任何地方,而id在同页面里是不能重复的。而且,为了体现继承扩展的关系,应当使用class了。
那么id还用不用?当然要用,且不论id在写JS时候的速度,实际在写页面的时候,肯定会某一个模块做“个性化”定义,这就需要使用id了。个性化的东西写在id里,这样就不用担心干扰其他模块了,最大避免触一发动全身的窘境。通用与独立同在。

聪明的同学一定想到了什么,对,是不是记得曾经看到过启蒙读物上,一再强调,千万不要把一个类明明为left,因为指不准哪天他就不在左边了。不要定义为blue,因为哪天就改成红色了?是的,那个说没错,但我这里也没错。我们说的是两个东西。

修改CSS还是修改HTML

曾经看到的那些,都是建立在一旦HTML写完,需求变的时候不许改HTML,只许改CSS的基础上的。但实际上,又多少机会能让你只改CSS而不改动HTML的呢?另外,既然有一套完善的CSS了,为何不直接简单修改一下HTML呢?如果背景变变成了红色,我只需要修改一下class,从bg_blue改成bg_red就可以了,何乐而不为?由此看来,class取名成left和right并非很糟糕的决定,只要合理利用,完全可以应付多样的需求。

开发成本VS维护成本
这样做之后带来的问题就是开发成本与维护成本的矛盾。这样开发确实很快速。但问题是以前小改动起来是不需要动HTML的,而现在改一次就得改HTML,而这方面一旦页面做好后就可能归其他部门那边管了,修改测试上传都得惊动其他部门,这方面如何协调是一个问题。
换句话说:面向对象CSS保持CSS框架不变而修改HTML,而原先那种是保持HTML不变而修改CSS
这方面我没有太多经验,欢迎大家探讨。
Twinsen有过类似的探讨( http://www.twinsenliang.net/skill/20081129.html ) 他就很反对这么来。
其中的大部分观点都赞同,只是最近我也在反思:
到底多大机会能让我碰上“left_box”和“right_box”的互换。全站的blue_button换成红色呢?
如果只是一两个页面的话,修改CSS的成本更低,还是保持CSS不动修改HTML的成本更低?

增加学习成本
当公司招募新人的时候,不得不对其进行培训,以使其学会使用这套自建的框架体系。但带来的好处是使整个网站风格统一,给进一步维护带来方便。所以我认为增加的这点学习成本是值得的。
同时,如果你都已经跳槽到别处了,没留下好的文档,人家学不会也没关系。直接抛开这套体系也能过日子。因为本身这套体系是从reset开始对各个标签初始化对象的,而后逐渐增加class以扩展对应属性。
也就是说,新人也可以抛开这套东西,直接用自己的写法来写。当然,这好不好已经不在今天的讨论范围了。这里只是为了说:这个框架也可以让新手不管这些约束直接写自己的。

class过长导致文件过大
这可以通过压缩来解决。用正则找出css和html中所有的class,以出现频率排序,然后分别从abcdeft…开始,先单字母,后双字母 a一直到zz应该有26*27种组合,足够一般网站应用了。google应该也是这样做的。抱歉这段时间比较慢,代码就没写了。

副作用:js必须用id而不是class了,否则压缩后会找不到对应的class
解决思路:约定JS中保存class的字符串变量为 foo_cls=”bar”,那么只要用正则找到对应_cls结尾的变量进行对应替换即可。
这本身是面向对象的CSS,而进一步压缩这里仅提供一种思路。

总结

结构和样式分离是好事,我这里提出的观点反而有点逆潮流,试图通过HTML中的class属性来控制表现。我认为这是一种理性回归,至少我们不用一个ID下面写一堆的针对他的样式,冗余,容易出错,效率还高。同时这种方式与直接在元素上写style也是有本质区别的,模块化,面向对象的思想体现在其中,合理控制每一个类的颗粒度,或者说控制范围。
我这种介于结构—样式的完全分离与结构—样式完全整合之间的一种状态,试图寻找一种平衡,提升开发效率并降低维护成本。

谨以此文做以探讨。

扩展阅读

重构之美-跨越Web标准,触碰语义网[分离:通用也许是个美丽陷阱] ——另一个反对的声音
面向对象的CSS--OOCSS 国人写的通过JS增加CSS面向对象功能

圆角?抱歉,你的浏览器不支持。请升级以获得更好体验。

之前写过一篇博客,问是否敢对IE6说不。实际上,我虽然自己没有公然抗议,暗自的还是有一些的。

最常见的就是:hover伪类了。除了二级菜单这类关键部位之外,其他地方一律用此处应当使用的标签,而不滥用a。其:hover伪类IE6无法支持,大不了少了点效果而已,不会有功能损失。想获得更好体验?请升级。为此写脚本做兼容?抱歉,我没时间。实际上,很多时候需求方并不在意这些细节交互地方。他们都不在意,你在意什么?

圆角?对不起,我可不高兴用一堆标签弄出圆角来。九宫格之类的办法不是不会,只是嫌麻烦。一堆标签自己看得心烦。直接用border-radius,浏览器要支持你就圆角,不支持就方的好了,没什么了不起的。除非需求方强烈要求,那在说

阴影?呵呵,同样对不起,阴影如果方便直接背景就背景,不方便实在抱歉……我给一个box-shadow已经很不错了,兼容Chrome Firefox 3.5呢。没了阴影功能又不会缺失,可有可无。

文字阴影?text-shadow伺候,如果需求方执意要求,那只能做背景图了……只是Chrome下文字阴影效果真是颗碜。。。

其实CSS3有很多很美妙的特性,利用这些特性可以非常轻易制作很出众的效果,何苦为了一些效果而花费大量时间呢?
适当跟需求方说明这些。告诉他们实现这些所要消耗的人力成本有多高。让他们自己决定哪些一定要,哪些可以放弃一部分低级浏览器用户。
在完善的沟通下,才能说服老板,说服需求方逐步抛开低级的浏览器,才能促进整个大环境的改变。

适当转型——写点生活

之前一直是纯技术博客,现在打算逐渐转一点,逐渐加入些生活元素。
当然,我也有另外的博客,太过私人化的不会放在这里了。大家放心。(就算我想放你们也管不着,这是我的博客,灭哈哈哈哈~~)
虽然有了twitter,但有些时候还是博客可以积淀一些东西。
架设Dabr和twitter的api很容易,我也有架设,能猜到的话,欢迎一起用,但别声张~
你也可以自己架设自己用。很容易搜索到教程

另外,收到 likeren 邀请(他的博客很人文,搞技术测宅男们建议吸取一些人文素养),尝试了一下国外的基于软件同好的SNS Wakoopa有兴趣可以上面来一起玩。

再另外,最近接了个项目后,有了点感悟,想写博客,结果发现想要写的太多,纠结很久。在此次牢骚一下……

给账族写的快速入账命令行GM脚本

最近要开始记账,寻遍国内外各种在线记账的也未能找到完全诚心如意的。最终觉得账族整体界面、操作上都比较符合我要求。
源于在Todoist上任务管理的录入方式,通过一系列命令可以快速输入。所以希望这里入账也有命令行。
而这个网站又恰巧用了jQuery,就写起来更顺手了。
此外,这个网站貌似目前主要开发任务是论坛……我不说啥了……不指望他们近期能开发这个功能。
所以,为了进一步加速入账效率,则开发了这个脚本。

比如我输入:
工资 +5000
回车,早就自动往我工资帐户加上了5000元(其实我工资远不到5K。。。不过做的蛮开心,暂无跳槽之意。)

又比如输入:
3 旅游 1000 信用卡
就自动设置为3天前,旅游用信用卡花了1000,花费分类是旅游

就类似这种功能。

地址是:

http://userscripts.org/scripts/show/55688

我用着还挺爽。

json2select的全国城市数据

去年写过一个小插件,json2select 一直想要转换出配套的数据,但总有这样那样的问题之后,终于拖到了现在。
好在一切悲剧的日子已经过去了,新时代已经来临。猛击这里
三级联动,直辖市精确到城镇街道,一般城市到达区。强烈推荐。

这一切都要感谢 Asfman ,辛勤的工作,当然也少不了感谢搜狐白社会,是他们提供了这么好的数据,也要感谢我们伟大祖国,我们中华民族地大物博,省市也很多……

这套数据有100K多一点,但可以想办法压缩
把其中重复字符串替换掉,把街道替换成j,市替换成s,区替换成q,都可以减少文件体积。要用的时候先用正则替换后,再eval执行字符串就能得到数据了,可以达到68K左右
另外,保存成gb2312的话也可以减小体积。目前我手头的是52K左右大小了。但可能导致乱码,慎用。

进一步,如果通过词频分析,找出重复最多的前20个,替换的话,相信可以把体积维持在30K以下了。但手头没工具,最近也很忙,所以大家自己发挥吧。
我粗略压缩后的东西我就不单独发布了。

update:
在热心网友 Noker (虽然截止到目前位置似乎博客里还空着)的帮助下,已经把这套数据压缩到只有30K左右了。太棒了!
大家可以到 移步到这里下载 对应的数据,以及查看demo

update:
网友fantasy提出一个潜在的bug,由于这套数据中只有 标题 子元素 而没有对应的value值,所以后台无法获取到。为此需要修改一下源文件创建option的那一行

  1. <option value='"+sd.v+"'

改成

  1. <option value='"+(sd.v||sd.t)+"'

即可
或者重新下载1.0.1版即可

能支持IE6的前端更牛,还是敢对IE6说不的更牛?

前几天群里探讨一个问题,作为一个前端,是能够支持更多的浏览器比较牛,还是勇于对IE6说不,更牛一些呢?IE6在其特定历史时期内起到了举足轻重的作用。而如今,是时候让他寿终正寝,离开历史舞台的时候了,他却欲罢还休不离不弃。面对这种态势我们能做些什么吗?

1.臭名昭著的IE6

IE6已经成为现代前端工作者的痛。是的,IE6有无数的毛病,无数的bug。尤其是在现今以CSS作为控制HTML表现得今天,IE6所具有的无数CSS毛病更是让现今的前端工作者痛不欲生。随便就能举出几个问题:双倍边距,3px,重影等问题。IE6也不能彻底支持:hover这种伪类。这些使开发者不得不为IE6制定特定的规则,不论是使用hack、条件注释、条件CSS或者使用JS来弥补,都不同程度上增加了工作量,降低了产值。而如今,大量在线应用的出现,丰富的JavaScript内容的存在,IE6底下的JS执行效率严重阻碍了体验。此外,还有png不透明度的问题。

实际上,这也不能怪IE6,他出现的时候,全世界还都是在表格布局的控制下呢。自然他对标准的支持比不上其他后起之秀。尤其是最近动作很多的以webkit核心的浏览器。

但IE6罪恶之处在于:当他完成历史使命后,依然霸占着互联网的舞台。

2.IE6为何还不退散

首先,微软不主动更新IE6,而是直接推出IE7,并且不强制推送。IE7和IE6界面使用习惯的区别,导致了IE6在很长一段时期内霸占着市场。我就曾经给辅导员升级到IE7,结果又被勒令退回IE6。所幸,这个现象从去年开始已经有所改观了,去年年初起,微软已经开始推送IE7了,而现在IE8也已经在推送了。强制推送的好处是,很大一部分低端用户不会卸载,只能默认接受。虽不人道,也迫于无奈。

另一个导致IE6无法推出历史舞台的原因,也恰恰是微软的Vista的失败。实际上,IE6进入市场取代IE5.5也正是从XP普及开始的。而Vista迟迟无法普及,就导致了其捆绑的IE7无法普及。

还有一个原因,也是由于IE6拖了太长时间,反而导致很多公司内部系统只能在IE6下正常运行,进一步导致这些公司无法部署更高级版本的IE。

实际上,虽然我主要浏览器是chrome和firefox,我本人系统也装的是IE6,一方面是开发需要,另一方面是,IE6速度确实比IE7和IE8快很多。开个网银也更令人惬意。

在这些多重原因的驱使下,IE6成了阴魂不散的恶鬼。

另外,月光博客也有过分析过 IE6在中国依旧占据了庞大市场的原因,可以移步看看。

3.前端工作者的现状

IE6对于标准的践踏的同时,超高的占有率给了所有前段开发者不能抛弃IE6的理由。痛苦,但却无可奈何。

前端工作者为啥不能无视IE6?老板用IE6,老板的朋友用IE6,这是普遍的原因之一。当然,也有拿出数据说,我们网站40%的人还在用IE6访问。

于是,为了那些IE6的用户(包括自己的老板和老板的朋友),前端们不得不为了IE6单独写hack。就我目前经验来说,我现在唯独专门写hack的就是IE6了,其他各种浏览器下几乎没有出入。

是的,为IE6多付出的工作量还是可以换来对应的回报的,也为此,在国内前端们无奈的“纵容”下,IE6用户升级速度进一步放缓。

4.国内外如何推动IE6的灭亡

前几天,国外著名科技网站 Mashable 一篇名为: IE6 Must Die for the Web to Move On 报道,希望IE6能尽快滚蛋中文翻译版。另外,Twitter上也有对应的头像加工的网站,在自己的头像上加上一个小图标: http://twibbon.com/Join/IE6-Must-Die

国外几大网站纷纷针对IE6用户设置了升级的提示。

twitter:
twitter-ie6

youtube:
youtube-ie6

facebook:
facebook-ie6

5.我们可以做些什么

是的,面对这个浪潮,我们可以做什么?一味得妥协?主动行动起来吧!
要相信只要每个人的共同努力,就一定可以让IE6离开这个舞台。
至少,我的老爸就会使用Chrome上网,而不是IE。

1,买新电脑吧!
是的,新的电脑通常配有vista系统,小白们不会跑去装xp的。而vista自带IE7。从此让小白跟IE6说拜拜吧!而更好的情况是,Win7马上就要上市了。到时候更加肆无忌惮忽悠小白买电脑吧!

2,这就是互联网!
没错,中国很多网民,认为那个蓝色的e就是互联网,认为百度或者谷歌就是互联网。那么很简单,直接换一个浏览器,把那个e删除,然后告诉他们,那个狐狸,或者那个球球就是互联网,打开这个,你就上网了!我就是这样告诉我老爸的。现在,他很自如得使用Chrome上网,看视频,看新闻。乐在其中,又很安全,我也放心。

3,你的电脑存在安全漏洞!
看到喜欢使用傲游、TT等IE马甲的用户,直接告诉他们,电脑有安全漏洞,需要升级!是的,他们会相信你的!同时,他们根本不在乎IE的内核是6还是7,但,你在乎,不是么?

4,推荐你一个很棒的浏览器
诚然,存在不少用户,只用IE6,给他们升级后,会说,这个浏览器用不惯。这个时候怎么办?应该向他们推荐用其他浏览器,比如傲游,然后,参考第上面一条。
实际上,直接推荐Chrome也是很容易成功的,我推荐给不少人用Chrome,无不为其急速所震撼。而我之所以推荐傲游,因为傲游3将默认使用webkit引擎,而在遇到网银时自动切换回IE的内核。实在是好。注意,不要随意推荐Firefox,因为Firefox启动速度过慢,以及配置扩展的复杂性,往往让小白们望而生畏。

此外,国内我也看到不少人为了推进IE6的灭亡而所作出的努力。比如 http://www.webrebuild.org/就有类似的计划。只需要把下面代码放到自己的博客上,就可以了。更有甚者,麦鸡的博客已经完全屏蔽IE系列了……

6.到底谁更牛?

能支持5、6个浏览器的前端与敢对IE6说不的前端谁更牛,这不重要。重要的是,能为推动IE6的离去做些什么。
如果什么都不做,安于现状,那么,只会让IE6推迟消亡,自己受到的苦难更多一点,更长一点。
从自己身边的事情做起,相信自己,不论是积极推动还是消极被动,你都在用自己的方式改变这个世界。知道这点,就可以了。

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

三个月前,老鱼在其博客和支付宝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>

文字竖排

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

网上目前两种方法竖排,
一种是用 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“不應有恨……”,他有些私有属性还是挺有趣的……
(注:原文中“恨”是遗憾的意思。)