DHL用自己的check digits规范把我坑了一下

这几天一直在搞条形码生成。因为有一个和DHL的合作项目要自动生成条形码打印出来。
而DHL给的条形码要求是interleaved 2of5.

查了一圈资料得知interleaved 2of5是没有check digits的
但是生成出来的条码很明显不对

后来在wikipedia发现A checksum can be added as last digit, which is calculated in the same way as UPC checksums.
于是用标准的checksums来计算check digit即

In the UPC-A system, the check digit is calculated as follows:

Add the digits in the odd-numbered positions (first, third, fifth,
etc.) together and multiply by three. Add the digits in the
even-numbered positions (second, fourth, sixth, etc.) to the result.
Find the result modulo 10 (i.e. the remainder when divided by 10… 10
goes into 58 5 times with 8 leftover). If the result is not zero,
subtract the result from ten.

但是生成出来的条码依旧和DHL给的范例不一样。反馈给DHL他们也说他们的机器扫描不成功。
后来以为是条码宽度问题。根据DHL给的要求把每条宽度设置为0.5mm到0.33mm之间。总宽度42mm
再次提交,DHL反馈说扫描出来了但是数字不对。首位多了0,末尾多了8.
万能的wikipedia又告诉我

Before the actual pairs there is a start code consisting of nnnn
(narrow bar-narrow space- narrow bar-narrow space), and after all
symbols there is the stop code consisting of Wnn (Wide bar-narrow
space-narrow bar).

Because digits are encoded by pairs, only an even number of digits can
be encoded. Typically an odd number of digits is encoded by adding a
“0” as first digit, but sometimes an odd number of digits is encoded
by using five narrow spaces in the last digit.

瞬间想到最后以为是不是barcode生成器自动给我添加的校验位。去查看了生成类的源代码发现

static public function compute($code, $crc, $type){
        if (! $crc) {
            if (strlen($code) % 2) $code = '0' . $code;
        } else {
            if ( ($type == 'int25') && (strlen($code) % 2 == 0) ) $code = '0' . $code;
            $odd = true;
            $sum = 0;
            for($i=strlen($code)-1; $i>-1; $i--){
                $v = intval($code[$i]);
                $sum += $odd ? 3 * $v : $v;
                $odd = ! $odd;
            }
            $code .= (string) ((10 - $sum % 10) % 10);
        }
        return($code);
    }

然而不传递checkdigit进去生成出来的依旧不对。
这时候想到DHL一开始发的Check digit calculation , Factor 4 and 9 see Specification。
wikipedia了一下。终于发现了

Identcode and Leitcode are variants of interleaved 2 of 5 with check
digits used by Deutsche Post.

一开始还不知道Deutsche Post是什么。查了一下 ,不就是DHL么。。。。
好坑啊。DHL还用自己的checkdigit规范。

果断去把生成类里的代码改成

$sum += $odd ? 4 * $v : 9 * $v;

又生成了一张。发现和DHL给的范例终于一模一样了。。

大功告成。
然而不知道为啥DHL用自己的checkdigit规范不用国际通用标准。真是好坑好坑。
另外,wikipedia真是个好东西。然而国内百度一下并没有任何资料。全都是卖东西的。

写了个最简单的Redis访问统计和缓存命中统计

核心就这么一句。。。

$redis->incr('stat');

模版functions里面加一个

function statredis(){
global $redis_host;
global $redis_port;
global $redis;
try{
    $redis = new Credis_Client($redis_host . ':' . $redis_port);
    echo $redis->get('stat')." visits with ".$redis->get('hit')." hit & ".$redis->get('miss')." miss";
}
catch (Exception $e) {
    echo "no redis";
}
}

然后在footer里调用就好。效果见本页底部footer。

如果想做到每个页面单独统计。就在functions里写一个$redis->incr(‘stat:’.$md5($_SERVER[‘QUERY_STRING’]));

毁掉太阳系的十种方法

通过 果壳网 guokr.com

Jerrusalem/编译)人类正在把自己的母星搞得千疮百孔,天知道我们会不会把其他地方也搞砸?这里我们列出了未来学家眼中10种可能毁掉整个太阳系的方法——还是无意间毁的。排名不分先后,前方高能预警。

粒子加速器大灾变

粒子加速器运行时无意间释放出的奇异粒子也许会让我们面临使整个太阳系完蛋的风险。在欧洲核子研究中心的大型强子对撞机(LHC)建造前,一些科学家就担心这个高能加速器可能会撞出一些有害的东西,诸如真空气泡啦、磁单极子啦、微型黑洞啦,也许还有奇异夸克团(果壳译注:即strangelets,是一种假设的物质形态,类似于传统意义上的原子核,但里面包含着许多更重的奇夸克)。

科学界谴责了诸如上述的忧虑,认为它们是“科学素养不足又想寻求关注制造轰动的人”所传播的垃圾谣言。再者,大型强子对撞机安全性评估小组在2011年的报告中也得出了“对撞无危险”的结论。

牛津大学未来人类学院的研究人员安德斯·桑德伯格(Anders Sandberg)同意加速器不怎么可能酿成灾难,但警告称如果奇异夸克团被泄露了出来,“那结果可能很坏。”他说。即便只是将火星这样的行星转换成奇异夸克团,假设转换时间是1小时,而只有0.1%的行星质量被转换为辐射,我们得到的平均光度将是太阳光度的大约4200万倍,辐射的大部分还将是硬伽马射线(“硬”辐射是指在能谱高能一端的辐射)。

哎呀。当然了,LHC不可能制造奇异夸克团,但将来地球上或宇宙空间里的设备也许有能力制造出这种东西。有假说称,这些奇异物质也许存在于中子星内部的高压之中。如果将来哪天我们一个不小心人为地制造出那样的条件,我们很快就没戏唱了。

美剧《闪电侠》中的粒子加速器爆炸。图片来源:arrow.wikia.com

悲剧的恒星工程

如果人们在某个恒星工程中严重破坏了太阳、改变了它的状态,又或者在期间搞砸了行星的动态,那太阳系就可能被玩脱了。

未来学家们推测,未来的人类也许会开展相当数量的恒星工程项目,包括“星球畜牧业”。休斯顿大学的大卫·克里斯威尔(David Criswell)在1985年出版的《星际移民与人类经验》(Interstellar Migration and the Human Experience)中将这种畜牧业诠释为人类控制恒星的演变与性质的尝试——包括延长恒星寿命,提取恒星物质乃至人工制造新的恒星。为了让太阳烧得慢些以延长恒星寿命,未来的恒星工程师移除恒星多余的质量(恒星越大,消耗核聚变的原料就越快)。

但恒星工程也会带来潜在危险。就像在地球上开展的地质工程一样,恒星工程可能带来各样不可预见的后果。比如旨在减轻太阳质量的工作可能导致危险的燃烧,或使太阳光度减少到危及生命的程度。这些工程也可能对行星的轨道产生显著的影响。

太阳出了岔子,太阳系也要悲剧了。图片来源:ilovemyscience.com

失败的木星恒星化

一直有人认为是时候设想将木星转变成某种人造恒星了。不过这个做法也许会摧毁木星,然后团灭地球上的生命。

天体物理学家马丁·福格(Martyn Fogg)在《英国星际学会志》里建议,将木星恒星化是到木星的伽利略卫星(果壳译注:伽利略卫星是指由伽利略率先发现的木星四大卫星)上殖民的第一步。为了实现这个计划,未来人类可以在木星里种下一个微型的原始黑洞。这只黑洞的各项参数需要被设计得分毫不差,以防它达到爱丁顿光度(果壳译注:黑洞不断吸引周围介质,同时向外发出辐射。当其质量增加到一定程度,星体向外的辐射压与向内的引力压会达到一个平衡点,这时天体的光度被称为爱丁顿光度)。福格认为这最终将“为欧罗巴(木卫二)和盖尼米得(木卫三)提供足够的能量使它们的温度一次接近于地球和火星”。

听起来不错把,但如果出了差错,后果可不堪设想。桑德伯格表示,最初这个系统也许运行良好,不过黑洞可能会增长到最终吞噬整个掉木星,然后发出横扫整个太阳系的辐射。生命大灭绝、木星被吞到黑洞里,我们的星系也就一团糟了。

要将木星变成下一个的“太阳”?如果出了差错也许一不小心就葬送了太阳系的前程。图片来源:io9.com

破坏行星轨道

当我们开始有能力改变行星或者其它星体的位置和质量的时候,打破太阳系微妙天体轨道平衡的风险也随之而来了。

太阳系的轨道动态是十分脆弱的。据估计,一个轻微的扰动,都可能产生混乱乃至有潜在危险的轨道变动。原因在于行星之间存在轨道共振。这种共振由行星公转周期的比例来表示。其结果是,即使相距十分遥远,在两个轨道上运行的天体仍然能够相互影响。这些星体有时靠近,有时又相互远离,而这种周期性的接近也许会是比较小的那个星体变得越来越不稳定,最终有可能离开它原有的轨道,甚至飞出太阳系!

在未来,混乱的轨道动力学可能会自然产生,也可能由于我们对太阳和行星的一些行动而被触发,比如之前说的恒星工程。将火星移动到适居带的尝试也可能破坏轨道平衡。

另外,如果我们用水星和金星的物质制造戴森球(果壳译注:弗里曼·戴森假想出的巨大球形结构,它将恒星包裹起来,从而获得恒星大部分能量),也会极大地影响太阳系的行星动态。也许水星(剩下的部分)会被甩出太阳系,也许地球会被大天体(比如火星)撞上,谁知道呢。

用太阳附近行星的物质来建造戴森球,会改变行星原本的轨道状态。图片来源:Adam Burn

曲率引擎操作失误

装配着曲率引擎的太空船当然相当酷,不过同时它也会带来危险。飞船跃迁目的地的任何东西,比如一颗行星,都有可能被转化为极大规模的能量。曲率引擎可能依靠在飞船周围制造负能量空泡来工作。曲率驱动会翘曲时空——在飞船身后时空将被“拉长”,而在它之前则会被“压缩”——飞船的速度有可能超越光速的限制。

曲速场的示意图。图片来源:wikipedia

不过,这种“能量空泡”有可能产生巨大的灾害。2012年的时候,一个研究小组计算了下曲率驱动引擎可能产生的伤害。杰森·梅洁尔(Jason Major)在“今日宇宙网”(Universe Today)上解释道:空间并非只A点与B点之间那些“虚空”,它充满了有质量的粒子(有些则没有质量)。这些粒子可能会被“扫”到跃迁泡上,集中在飞船的前面和后面。

当曲率驱动飞船从超光速飞行中退出并减速时,能量空泡所积累的粒子会爆发出巨大的能量。结果是,飞船前方、目的地上的任何东西都会被这股能量摧毁。研究论文总结道,由于飞船前方粒子的极端蓝移,目的地的任何人都会被强烈的伽马射线和高能粒子轰成渣。

他们补充说,短途旅行释放出的能量之大也“足以消灭你面前的任何东西”。这个“任何东西”,指的可以是整个行星。而且,由于能量大小取决于旅途的距离,理论上来说,释放的能量可能非常非常高。

人工虫洞事故

理论上,用人工虫洞来绕开星际旅行的限制真是美如画。但在连续时空里扯出一个洞时,我们要格外小心。2005年的时候,伊朗核物理学家穆罕默德·曼苏里(Mohammad Mansouryar)提出了一个穿越虫洞的计划大纲。他假设如果我们能制造足够多的“奇异物质”,理论上我们就能制造出能够穿越宇宙时空的虫洞,从而缩短太空航行时间。

穆罕默德的理论还停留在纸上,不过桑德伯格表示这样做也许会产生严重的负面影响。首先,虫洞喉部需要的质能规模和一个相同大小的黑洞差不多。其次,时间旅行也许会让虚粒子变为实粒子,并由于能量跃迁而破坏虫洞。除此之外,如果把虫洞的一端建在太阳附近,也许会让太阳的能量流失到那一端,或者给太阳系带来大量的辐射。我们都知道,干掉太阳没什么好结果,被辐射也好不到哪里去。

虫洞能在星际旅行中派上大用场,也可能惹出大麻烦。图片来源:Interstella

什卡多夫推进器导航错误

1987年,前苏联物理学家列昂尼德·什卡多夫(Leonid Shkadov)构思了一种被称为什卡多夫推进器的超大结构。这个装置能将整个太阳系移动到另一个相邻的恒星系统那边去。在将来,我们也许能用它从一个衰老的恒星附近移居到另一个更年轻的恒星那里去。

亚当·哈德兹(Adam Hadhazy)在《大众机械》里解释了这玩意的工作原理:什卡多夫推进器的设置很简单——它不过是一个巨大的、圆弧状的镜子,凹的一侧对准太阳。建设者们将把它放在太阳引力与辐射压的平衡点上。然后这面镜子就变成了太阳的一个稳定静止的“卫星”,在引力与辐射推力之间保持平衡。

推太阳噜!朝哪推,算好了吗?图片来源:centauri-dreams.org

由于凹面对着太阳,太阳的辐射在镜子处反射回太阳,这能有效地用太阳的辐射能量推动它自己移动——反射的能量会产生一个微小的净推力。这能有啥问题?实际上,问题还真的挺多的:如果我们计算出错,可能会把把太阳系带到宇宙,或者干脆直接撞上其他恒星。

然后我们就讨论到一个有意思的问题:如果我们已经发展出了这种在恒星间旅行的科技,那我们也能知道如何操纵或影响太阳系外缘的小天体。而那时我们一定得小心。桑德伯格警告道:“啊,要是让柯伊伯带和奥尔特云(果壳译注:柯伊伯带是海王星轨道外的小行星密集带,奥尔特云则更加遥远,是一个假设中包裹着太阳系的球体云团。)变得不稳定,你就等着无数彗星砸过来吧。”

吸引到邪恶的外星人

这一条十分简单且容易理解。

如果地球人的“搜寻地外文明”(SETI,the Search for Extraterrestrial Intelligence)计划成功了的话,我们可能很快就能带着希望把友好的信息发给其他外星文明了。不过,这也将提醒外星人“我们在这里!”嗯,最后遇上的外星人肯定是很友好的,吧……是吗?

如果来的是《火星人玩转地球》里的火星人……就一点都不好玩了。图片来源:collider.com

冯·诺依曼探针与星际“灰蛊”灾难

我们也许会送出能够自我复制的“冯·诺依曼探针”(von Neumann probes,一种设想中的能够通过提取星际物质来自我复制的太空飞船)去征服银河系。如果我们没给它们编好程序,或者某些人故意编入了进化算法——那么随着时间的变化,它们也许会突变成某种十分邪恶的东西。最终,我们这些聪明的航天小玩意也许会杀回太阳系,用光太阳系所有资源进行自我复制,或者把太阳系撕成碎片并顺便把我们也都干掉。

与冯·诺依曼探针相似的东西,还有某种由更微小的、自我复制的结构组成的太空飞船:能指数级复制的纳米机器人——“灰蛊”(果壳译注:英文为Grey Goo。今年一月新发布的RTS游戏《Grey Goo》使用了“分子纳米技术”这个概念,其中Goo族就是一种由纳米机器人组成的智慧种族。)它们有可能十分危险。灰蛊末日描述了这样的场景:纳米机器人的不可控自我复制消耗了整个行星的能源,目的是为了制造更多自己的分身。由于单个体积很小,它们的集合将是一种看起来像液态的状态。如果几个小机器人踏上了从地球逃亡的飞船,那么这种泛滥将蔓延整个太阳系,甚至包括太空站等大型结构。当灰色的洪流席卷太阳系,一切都将变成糊状。

可自我复制的太空船会不会组团大闹银河系?图片来源:pcgamesn.com

这可能是“费米悖论”的一种答案:外星文明不存在。弗兰克·提贝尔(Frank Tipler)1981年就根据冯·诺依曼探针提出过这个观点。如果外星文明存在的话,我们应该早就见过这种机器人了——或者早就被它们吞掉了。不过卡尔·萨根和威廉·纽曼回应称,由于冯·诺依曼探针自我复制十分迅速,(如果它们存在的话,与它们接触的)银河系里的智能很可能绞尽脑汁想清除它们,而非创造它们。这也是为什么我们至今没见过冯·诺依曼探针之类的外星机器人的缘故。

超级人工智能

创造一个超级人工智能的潜在危险是,它有可能干的事比“灭绝地球人类”要多得多——它的威力可能蔓延到太阳系,或许还会更远。

“回形针末日”描述了一个超级人工智能是如何把整个地球变成一大堆回形针的。这实际上是一个思想实验,主要目的是让一个程序计算“如何拥有最多的回形针”。而最终的结果是程序将认为这需要把整个地球全变成回形针。这个问题很紧迫。一个超级人工智能显然不会做造一大堆回形针这种无聊的事,而可能无节制地给处理器提供源源不断的能源,又或者将所有可用物质“电脑化”。一个超级人工智能甚至可能产生一种急切的本能冲动,驱使它将程序的范围扩大到整个银河系。

超级人工智能奥创。图片来源:marvel.wikia.com

文末附送最后的,也是最可能的方法——让太阳系对我们失去意义——通过“人类灭绝”达成。

(编辑:Calo)

文章题图:comicvine.com

图解无垠宇宙

图解无垠宇宙

1. 太阳到底有多大

图解无垠宇宙

我们都知道太阳好大好大好大…但是大到什么程度呢?这张图告诉我们太阳的巨大使我们人类的小脑袋无法理解滴。我们觉得地球已经很大了,一架波音747全速绕赤道飞一圈需要42小时,而以相同速度绕太阳一周需要6个月。

2. 离我们最近的月亮也非常遥远

图解无垠宇宙

与无垠的宇宙相比,月球离我们真的很近了,只有大约238900英里远呢。但与我们日常生活相比,宇宙中的星体都离我们远的不像话。我们地球和月亮之间距离可以塞下其它另外七大行星,还有多余的地方。其中包括土星和木星,分别是地球的9倍和11倍。

3. 从火星上看,地球就是颗小小的点

图解无垠宇宙

如果你来一趟火星之旅的话,你在火星上看到天空的地球就是图上这样的。这张照片是美国NASA的好奇号在地球与火星距离非常近的时候拍下的,当时只有9900万英里,在其他时候,它们之间的距离有上面距离的5倍远。

4. 北美在木星上只有这么大

图解无垠宇宙

木星以它的体积而著名,1655年发现的木星大红斑正在萎缩,但它仍然是北美洲的好多倍。木星和其他气态巨行星体积如此之大,是因为他们的低气温可以保持从离太阳近的行星散发的较轻气体,如氢和氦。

5. 如果用土星代替月亮

图解无垠宇宙

另一种方式理解气态巨行星到底有多大的方法是在照片中将月亮换成土星。插画家罗恩·米勒将在死亡谷拍摄的满月照片换成了其他行星。在这个位置,土星占据了天空大部分空间,日食会持续好几个小时。 (当然,由于土星的引力影响,它要是接近地球结果会是毁灭性的。)

6. 一颗彗星也是庞然大物

图解无垠宇宙

图中彗星是2014年11月菲莱探测器着陆的67 p / C-G,将它罩在洛杉矶上大概就是这样子的。在宇宙中,这颗彗星绝对是小号中的小号,只有3.5英里宽,但是这张图显示了宇宙中的东西要比你能想象的要大得多。

7. 美国历史只是冥王星公转一圈的时间

图解无垠宇宙

不仅仅是宇宙物体的大小让人匪夷所思——浩瀚宇宙的时间尺度也是巨大的。冥王星沿轨道绕太阳一周需要248个地球年。换句话说,美国的整个历史不过是冥王星绕太阳转了一周而已。上次冥王星处在它现在位置上的时候,我们还没有发明飞机,更别提宇宙飞船了。的轨道。当冥王星是去年在其当前位置,我们没有发明了航空,更不用说航天了。这张地图美国宇航局公布了新视野号团队的预期调查在7月成为第一个宇宙飞船去冥王星。

8.冥王星不只是在太阳系边缘

图解无垠宇宙

我们许多人认为又冷又小的冥王星是太阳系外缘的,事实远非如此,冥王星的轨道在这张地图的蓝色小框中心。外层是柯伊伯带,接着是奥尔特星云——其延伸范围比海王星远一千倍,是距我们第二近的恒星距离的一半远。

9.个头一个赛一个

图解无垠宇宙

一旦你离开太阳系,遇到其他星球,和它们比起来太阳就是小不点儿了就像地球之于太阳一样。还有其他更大的星球,(如心大星和参宿四)直接秒了其它星球。一遍又一遍,宇宙中有无数的星球,完全超出了人的基本思考范畴。

10.你能看到的星星都在黄色圈内

图解无垠宇宙

当然,星球是巨大的。但是银河系,又一遍,简直是令人难以置信的大。这张图完整显示了银河系。其中黄色的圆圈可能包含了不借助望远镜你肉眼你能看到的每颗星星。基于这样一个事实,在理想条件下,南半球的人们可以看到特别明亮的恒星系统船底座海山二星,但在大多数地方,黄色圆圈的范围将缩小很多。

11.银河系只是十亿分之一

图解无垠宇宙

浩瀚宇宙中,银河系只是数以十亿计星系中的一个。最近,科学家绘制了银河系附近的大约100000个星系,发现这是一个更广泛的超星系团的一部分称为Laniakea。这个超星系团由几个叉状体系组成,银河系躺在一个遥远的边缘。更重要的是,它的另一个超星系团(称为Perseus-Pisces)朝着相反的方向运动,似乎有合并成一个更广泛网络的趋势,在相对空的空间形成密集的超星系团。

HTML编码规范

HTML编码规范

1 前言

HTML作为描述网页结构的超文本标记语言。本文档的目标是使HTML代码风格保持一致,容易被理解和被维护。主要依照百度前端团队和腾讯alloyteam的标准修改而来,具体使用请结合CatUI

2 代码风格

2.1 缩进与换行

[强制] 使用 4 个空格做为一个缩进层级,不允许使用 2 个空格 或 tab 字符。

[强制] 嵌套的节点应该缩进( 4 个空格)。

示例:

1
2
3
4
<ul>
<li>first</li>
<li>second</li>
</ul>

[建议] 每行不得超过 120 个字符。

解释:

过长的代码不容易阅读与维护。但是考虑到 HTML 的特殊性,不做硬性要求。

2.2 命名

[强制] class 必须单词全字母小写,单词间以 - 分隔。

[强制] class 必须代表相应模块或部件的内容或功能,不得以样式信息进行命名。

示例:

1
2
3
4
5
<!-- good -->
<div class="sidebar"></div>

<!-- bad -->
<div class="left"></div>

[强制] 元素 id 必须保证页面唯一。

解释:

同一个页面中,不同的元素包含相同的 id,不符合 id 的属性含义。并且使用 document.getElementById 时可能导致难以追查的问题。

[建议] id 建议单词全字母小写,单词间以 - 分隔。同项目必须保持风格一致。

[建议] idclass 命名,在避免冲突并描述清楚的前提下尽可能短。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- good -->
<div id="nav"></div>
<!-- bad -->
<div id="navigation"></div>

<!-- good -->
<p class="comment"></p>
<!-- bad -->
<p class="com"></p>

<!-- good -->
<span class="author"></span>
<!-- bad -->
<span class="red"></span>

[强制] 禁止为了 hook 脚本,创建无样式信息的 class

解释:

不允许 class 只用于让 JavaScript 选择某些元素,class 应该具有明确的语义和样式。否则容易导致 css class 泛滥。

使用 id、属性选择作为 hook 是更好的方式。

[强制] 同一页面,应避免使用相同的 nameid

解释:

IE 浏览器会混淆元素的 id 和 name 属性, document.getElementById 可能获得不期望的元素。所以在对元素的 id 与 name 属性的命名需要非常小心。

一个比较好的实践是,为 id 和 name 使用不同的命名法。

示例:

1
2
3
4
5
6
<input name="foo">
<div id="foo"></div>
<script>
// IE6 将显示 INPUT
alert(document.getElementById('foo').tagName);
</script>

2.3 标签

[强制] 标签名必须使用小写字母。

示例:

1
2
3
4
5
<!-- good -->
<p>Hello StyleGuide!</p>

<!-- bad -->
<P>Hello StyleGuide!</P>

[强制] 对于无需自闭合的标签,不允许自闭合。

解释:

常见无需自闭合标签有input、br、img、hr等。

示例:

1
2
3
4
5
<!-- good -->
<input type="text" name="title">

<!-- bad -->
<input type="text" name="title" />

[强制] 对 HTML5 中规定允许省略的闭合标签,不允许省略闭合标签。

解释:

对代码体积要求非常严苛的场景,可以例外。比如:第三方页面使用的投放系统。

示例:

1
2
3
4
5
6
7
8
9
10
11
<!-- good -->
<ul>
<li>first</li>
<li>second</li>
</ul>

<!-- bad -->
<ul>
<li>first
<li>second
</ul>

[强制] 标签使用必须符合标签嵌套规则。

解释:

比如 div 不得置于 p 中,tbody 必须置于 table 中。

详细的标签嵌套规则参见HTML DTD中的 Elements 定义部分。

[建议] HTML 标签的使用应该遵循标签的语义。

解释:

下面是常见标签语义

  • p - 段落
  • h1,h2,h3,h4,h5,h6 - 层级标题
  • strong,em - 强调
  • ins - 插入
  • del - 删除
  • abbr - 缩写
  • code - 代码标识
  • cite - 引述来源作品的标题
  • q - 引用
  • blockquote - 一段或长篇引用
  • ul - 无序列表
  • ol - 有序列表
  • dl,dt,dd - 定义列表

示例:

1
2
3
4
5
<!-- good -->
<p>Esprima serves as an important <strong>building block</strong> for some JavaScript language tools.</p>

<!-- bad -->
<div>Esprima serves as an important <span class="strong">building block</span> for some JavaScript language tools.</div>

[建议] 在 CSS 可以实现相同需求的情况下不得使用表格进行布局。

解释:

在兼容性允许的情况下应尽量保持语义正确性。对网格对齐和拉伸性有严格要求的场景允许例外,如多列复杂表单。

[建议] 标签的使用应尽量简洁,减少不必要的标签。

示例:

1
2
3
4
5
6
7
<!-- good -->
<img class="avatar" src="image.png">

<!-- bad -->
<span class="avatar">
<img src="image.png">
</span>

[强制] 减少标签数量

解释:
在编写 HTML 代码时,需要尽量避免多余的父节点。很多时候,需要通过迭代和重构来使 HTML 变得更少。

示例:

1
2
3
4
5
6
7
8
<!-- good -->
<img class="avatar" src="...">


<!-- bad -->
<span class="avatar">
<img src="...">
</span>

[建议] 避免JavaScript 生成标签

解释:
在 JavaScript 文件中生成标签让内容变得更难查找,更难编辑,性能更差。应该尽量避免这种情况的出现。

2.4 属性

[强制] 属性名必须使用小写字母。

示例:

1
2
3
4
5
<!-- good -->
<table cellspacing="0">...</table>

<!-- bad -->
<table cellSpacing="0">...</table>

[强制] 属性值必须用双引号包围。

解释:

不允许使用单引号,不允许不使用引号。

示例:

1
2
3
4
5
6
<!-- good -->
<script src="esl.js"></script>

<!-- bad -->
<script src='esl.js'></script>
<script src=esl.js></script>

[建议] 布尔类型的属性,建议不添加属性值。

解释:

XHTML 需要每个属性声明取值,但是 HTML5并不需要。

如果你必须为属性添加并不需要的取值,参照 WhatWG 的指引:

如果属性存在,他的取值必须是空字符串或者 [...] 属性的规范名称,不要在首尾包含空白字符。

示例:

1
2
<input type="text" disabled>
<input type="checkbox" value="1" checked>

[建议] 自定义属性建议以 xxx- 为前缀,推荐使用 data-

解释:

使用前缀有助于区分自定义属性和标准定义的属性。

示例:

1
<ol data-ui-type="Select"></ol>

[建议] HTML 属性应该按照特定的顺序出现以保证易读性。

  • id
  • class
  • name
  • data-*
  • src, for, type, href
  • title, alt
  • aria-*, role

解释:

Classes 是为高可复用组件设计的,理论上他们应处在第一位。Ids 更加具体而且应该尽量少使用(例如, 页内书签),所以他们处在第二位。但为了突出id的重要性, 把id放到了第一位。

示例:

1
2
3
4
5
6
7
<a id="..." class="..." data-modal="toggle" href="#">
Example link
</a>

<input class="form-control" type="text">

<img src="..." alt="...">

3 通用

3.1 DOCTYPE

[强制] 使用 HTML5doctype 来启用标准模式,虽然doctype不区分大小写,但建议使用大写的 DOCTYPE。见is-there-any-benefits-to-use-uppercase-or-lowercase-letters-with-html5-tagname

示例:

1
<!DOCTYPE html>

[建议] 启用 IE Edge 模式。

解释:

Internet Explorer 支持使用一个文档属性标签 <meta> 来指出这个页面应当支持的IE的版本。除非另有规定,最好用最新的支持的模式。
更多信息, 阅读Stack Overflow 文章.
不同doctype在不同浏览器下的不同渲染模式,诡异模式总结的很到位.

示例:

1
<meta http-equiv="X-UA-Compatible" content="IE=Edge">

[建议] 在 html 标签上设置正确的 lang 属性。

解释:

有助于提高页面的可访问性,如:让语音合成工具确定其所应该采用的发音,令翻译工具确定其翻译语言等。
通过Sitepoint 得到一个语言代码列表.由于其只是给出了语言代码的大类,比如说中文就只给出了ZH,但是没有区分香港,台湾,大陆等。而微软给出的一份细分了zh-cn,zh-hk,zh-twHead to Microsoft for a detail list of language codes

示例:

1
<html lang="zh-CN">

3.2 编码

[强制] 页面必须使用精简形式,明确指定字符编码。指定字符编码的 meta 必须是 head 的第一个直接子元素。

解释:

HTML5 Charset能用吗 一文。

示例:

1
2
3
4
5
6
7
8
9
<html>
<head>
<meta charset="UTF-8">
......
</head>
<body>
......
</body>
</html>

[建议] HTML 文件使用无 BOMUTF-8 编码。

解释:

UTF-8 编码具有更广泛的适应性。BOM 在使用程序或工具处理文件时可能造成不必要的干扰。

3.3 CSS和JavaScript引入

[强制] 引入 CSS 时必须指明 rel="stylesheet"

示例:

1
<link rel="stylesheet" src="page.css">

[建议] 引入 CSSJavaScript 时无须指明 type 属性。

解释:

text/csstext/javascript 是 type 的默认值。

[建议] 展现定义放置于外部 CSS 中,行为定义放置于外部 JavaScript 中。

解释:

结构-样式-行为的代码分离,对于提高代码的可阅读性和维护性都有好处。

[建议] 在 head 中引入页面需要的所有 CSS 资源。

解释:

在页面渲染的过程中,新的CSS可能导致元素的样式重新计算和绘制,页面闪烁。

[建议] JavaScript 应当放在页面末尾,或采用异步加载。

解释:

将 script 放在页面中间将阻断页面的渲染。出于性能方面的考虑,如非必要,请遵守此条建议。

示例:

1
2
3
4
<body>
<!-- a lot of elements -->
<script src="init-behavior.js"></script>
</body>

[建议] 移动环境或只针对现代浏览器设计的 Web 应用,如果引用外部资源的 URL 协议部分与页面相同,建议省略协议前缀。

解释:

使用 protocol-relative URL 引入 CSS,在 IE7/8 下,会发两次请求。是否使用 protocol-relative URL 应充分考虑页面针对的环境。

示例:

1
<script src="//s1.bdstatic.com/cache/static/jquery-1.10.2.min_f2fb5194.js"></script>

4 head

4.1 title

[强制] 页面必须包含 title 标签声明标题。

[强制] title 必须作为 head 的直接子元素,并紧随 charset 声明之后。

解释:

title 中如果包含 ascii 之外的字符,浏览器需要知道字符编码类型才能进行解码,否则可能导致乱码。

示例:

1
2
3
4
<head>
<meta charset="UTF-8">
<title>页面标题</title>
</head>

4.2 favicon

[强制] 保证 favicon 可访问。

解释:

在未指定 favicon 时,大多数浏览器会请求 Web Server 根目录下的 favicon.ico 。为了保证favicon可访问,避免404,必须遵循以下两种方法之一:

  1. 在 Web Server 根目录放置 favicon.ico 文件。
  2. 使用 link 指定 favicon。

示例:

1
<link rel="shortcut icon" href="path/to/favicon.ico">

4.3 viewport

[建议] 若页面欲对移动设备友好,需指定页面的 viewport

解释:

viewport meta tag可以设置可视区域的宽度和初始缩放大小,避免在移动设备上出现页面展示不正常。

比如,在页面宽度小于 980px 时,若需 iOS 设备友好,应当设置 viewport 的 width 值来适应你的页面宽度。同时因为不同移动设备分辨率不同,在设置时,应当使用 device-width 和 device-height 变量。

另外,为了使 viewport 正常工作,在页面内容样式布局设计上也要做相应调整,如避免绝对定位等。关于 viewport 的更多介绍,可以参见 Safari Web Content Guide的介绍

5 图片

[强制] 禁止 imgsrc 取值为空。延迟加载的图片也要增加默认的 src

解释:

src 取值为空,会导致部分浏览器重新加载一次当前页面,参考:https://developer.yahoo.com/performance/rules.html#emptysrc

[建议] 避免为 img 添加不必要的 title 属性。

解释:

多余的 title 影响看图体验,并且增加了页面尺寸。

[建议] 为重要图片添加 alt 属性。

解释:

可以提高图片加载失败时的用户体验。

[建议] 添加 widthheight 属性,以避免页面抖动。

[建议] 有下载需求的图片采用 img 标签实现,无下载需求的图片采用 CSS 背景图实现。

解释:

  1. 产品 logo、用户头像、用户产生的图片等有潜在下载需求的图片,以 img 形式实现,能方便用户下载。
  2. 无下载需求的图片,比如:icon、背景、代码使用的图片等,尽可能采用 css 背景图实现。

6 表单

6.1 控件标题

[强制] 有文本标题的控件必须使用 label 标签将其与其标题相关联。

解释:

有两种方式:

  1. 将控件置于 label 内。
  2. label 的 for 属性指向控件的 id。

推荐使用第一种,减少不必要的 id。如果 DOM 结构不允许直接嵌套,则应使用第二种。

示例:

1
2
3
<label><input type="checkbox" name="confirm" value="on"> 我已确认上述条款</label>

<label for="username">用户名:</label> <input type="textbox" name="username" id="username">

6.2 按钮

[强制] 使用 button 元素时必须指明 type 属性值。

解释:

button 元素的默认 type 为 submit,如果被置于 form 元素中,点击后将导致表单提交。为显示区分其作用方便理解,必须给出 type 属性。

示例:

1
2
<button type="submit">提交</button>
<button type="button">取消</button>

[建议] 尽量不要使用按钮类元素的 name 属性。

解释:

由于浏览器兼容性问题,使用按钮的 name 属性会带来许多难以发现的问题。具体情况可参考此文

6.3 可访问性 (A11Y)

[建议] 负责主要功能的按钮在 DOM 中的顺序应靠前。

解释:

负责主要功能的按钮应相对靠前,以提高可访问性。如果在 CSS 中指定了 float: right 则可能导致视觉上主按钮在前,而 DOM 中主按钮靠后的情况。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!-- good -->
<style>
.buttons .button-group {
float: right;
}
</style>

<div class="buttons">
<div class="button-group">
<button type="submit">提交</button>
<button type="button">取消</button>
</div>
</div>

<!-- bad -->
<style>
.buttons button {
float: right;
}
</style>

<div class="buttons">
<button type="button">取消</button>
<button type="submit">提交</button>
</div>

[建议] 当使用 JavaScript 进行表单提交时,如果条件允许,应使原生提交功能正常工作。

解释:

当浏览器 JS 运行错误或关闭 JS 时,提交功能将无法工作。如果正确指定了 form 元素的 action 属性和表单控件的 name 属性时,提交仍可继续进行。

示例:

1
2
3
4
<form action="/login" method="post">
<p><input name="username" type="text" placeholder="用户名"></p>
<p><input name="password" type="password" placeholder="密码"></p>
</form>

[建议] 在针对移动设备开发的页面时,根据内容类型指定输入框的 type 属性。

解释:

根据内容类型指定输入框类型,能获得能友好的输入体验。

示例:

1
<input type="date">

7 多媒体

[建议] 当在现代浏览器中使用 audio 以及 video 标签来播放音频、视频时,应当注意格式。

解释:

音频应尽可能覆盖到如下格式:

  • MP3
  • WAV
  • Ogg

视频应尽可能覆盖到如下格式:

  • MP4
  • WebM
  • Ogg

[建议] 在支持 HTML5 的浏览器中优先使用 audiovideo 标签来定义音视频元素。

[建议] 使用退化到插件的方式来对多浏览器进行支持。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<audio controls>
<source src="audio.mp3" type="audio/mpeg">
<source src="audio.ogg" type="audio/ogg">
<object width="100" height="50" data="audio.mp3">
<embed width="100" height="50" src="audio.swf">
</object>
</audio>

<video width="100" height="50" controls>
<source src="video.mp4" type="video/mp4">
<source src="video.ogg" type="video/ogg">
<object width="100" height="50" data="video.mp4">
<embed width="100" height="50" src="video.swf">
</object>
</video>

[建议] 只在必要的时候开启音视频的自动播放。

[建议] 在 object 标签内部提供指示浏览器不支持该标签的说明。

示例:

1
<object width="100" height="50" data="something.swf">DO NOT SUPPORT THIS TAG</object>

8 模板中的 HTML

[建议] 模板代码的缩进优先保证 HTML 代码的缩进规则。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- good -->
{if $display == true}
<div>
<ul>
{foreach $item_list as $item}
<li>{$item.name}<li>
{/foreach}
</ul>
</div>
{/if}

<!-- bad -->
{if $display == true}
<div>
<ul>
{foreach $item_list as $item}
<li>{$item.name}<li>
{/foreach}
</ul>
</div>
{/if}

[建议] 模板代码应以保证 HTML 单个标签语法的正确性为基本原则。

示例:

1
2
3
4
5
<!-- good -->
<li class="{if $item.type_id == $current_type}focus{/if}">{ $item.type_name }</li>

<!-- bad -->
<li {if $item.type_id == $current_type} class="focus"{/if}>{ $item.type_name }</li>

[建议] 在循环处理模板数据构造表格时,若要求每行输出固定的个数,建议先将数据分组,之后再循环输出。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- good -->
<table>
{foreach $item_list as $item_group}
<tr>
{foreach $item_group as $item}
<td>{ $item.name }</td>
{/foreach}
<tr>
{/foreach}
</table>

<!-- bad -->
<table>
<tr>
{foreach $item_list as $item}
<td>{ $item.name }</td>
{if $item@iteration is div by 5}
</tr>
<tr>
{/if}
{/foreach}
</tr>
</table>