这篇Blog将要讨论,在CSS的className中使用连字符“-”还是使用下划线“_”作为分隔符更适合?
在切入主题之前,先看看Google在Webmaster Tools中URL structure章节中所说的一段话:
Consider using punctuation in your URLs. The URL is much more useful to us than We recommend that you use hyphens (-) instead of underscores (_) in your URLs.
这段话的意思是,出于URL语义化的考虑,Google建议站点URL中使用连字符“-”来代替下划线“_”做分隔符。不知道是否是因为Google的这份文档,我们可以看到越来越多的国内外网站URL中开始使用“-”来作为分隔符,例如:
以及我正在使用WordPress编辑的这篇BLOG的编辑地址是:?post=338&action=edit
申请过域名的人都知道,一个英文域名中,合法的字符只有数字0-9、字母a-z、符号“-”和“.”两个。其中“.”号用作域名层级分隔符,“-”号作为单词分隔符。从牛津词典中可以看到对连字符hyphen的解释:
更多hyphen的应用场景,以及hyphen和dash以及minus符号的差异,感兴趣的同学可以去看wiki看看。
结论显而易见,在英语中分隔符号即是hyphen的语义。
这就不难理解,为什么当初在。同时也不难理解为什么CSS属性的写法是“background-color”而不是“background_color”或者“backgroundColor”了。
然而现实情况却并非如当初CSS1的规范制订的那样完美,很多开发者在写className中却因为某些原因,使用了“_”作为分隔符,并将此作为自己的代码规范。这使得W3C不得不在2001年CSS2的一次修订版本中将“_”定义为className中的合法字符,无须转义均可支持。这也是为什么在2001年前的浏览器如navigator 4.x、IE 5.x不支持className中的“_”未转义写法,而IE6及后来的firefox、chrome均能支持这种写法。
从某种程度上来说,W3C标准对现实的妥协,也是导致前端开发工程师面对浏览器差异化的杯具结局的原因之一。至于W3C支持className中的“_”作为分隔符的原因就不难想象了:正如这种写法的支持者所说,在JS中下划线“_”才是公认的分隔符。例如,DOM中有一个id为“kaiye”的节点,在IE6中你可以通过document.all.kaiye集合获取到这个节点的引用。但如果这个ID被命名为“kai-ye”,使用document.all.kai-ye显然会抛出一个异常,因为基本在所有的编程语言中“-”代表的是“减号运算符”,JS也不例外,正如这篇《Web开发中初学者容易混淆的9个命名约定》中所说。正是由于这点原因,导致在id属性命名时,开发者通常会避免使用“-”,为了保持代码风格统一,className中也使用“_”作为分隔符。事实上,W3C并没有规定class属性和id属性命名约定必须相同,className中的“-”分隔符更是和运算符减号“-”风马牛不相及,CSS不是编程语言又何来减号运算符的冲突问题?
同时这种命名约定却无形中挖了一个坑:通常在JS的命名约定中,你可以使用 _kaiye 来声明这是一个私有变量,但如果你在CSS中沿用这种命名习惯使用 _kaiye 来作为className将会导致这段声明在IE6中无效。不幸的是,我亲眼见到有人掉到这个坑里了,并且一定会有更多人因为这种命名约定掉到这个坑里,这也是我坚持不在className中使用“_”最重要的原因。
08年当我刚入职支付宝那会,我跟着小黑做了支付宝的第一个浏览器兼容性项目─“Firefox交易流程兼容性项目”。我们修改了上百个交易创建、修改、付款、完成的页面,修复了其中大量HTML、CSS、JS的兼容性写法,并同时将记录汇总成一张bugfix list。结果发现为了使支付宝兼容Firefox,我们对DOM做的最多的修改是,将标签P修改为DIV,对JS修改最多的是将 document.all 的写法换成 document.getElementById 。这意味着如果你的产品需要提供更好的用户体验,兼容更多的浏览器,你应该像许多JS框架那样使用W3C标准的写法来编写你的JS。getElementById就是获取DOM对象的最佳实践,而这个方法接受的唯一参数是一个字符串,这个字符串允许你包含任意字符,当然也包括连字符“-”。也就是说,document.all方法将不会出现在一个需要跨浏览器支持的产品中,你可以在ID属性中使用“-”作为分隔符。
Google、Yahoo、淘宝、豆瓣在他们的新CSS代码规范中推荐使用“-”作为className分隔符,这个自然就不难理解了。