Posts Tagged: 性能


17
七 10

256色

神飞那里借了本《高性能网站建设进阶指南》,粗略读了一遍,最重要的收获是第10章图像优化纠正了我对256色的认识

Truecolor versus palette image formats

Using the RGB color model, how many distinct colors can you represent in a graphic? The answer is more than 16 million: 255 * 255 * 255 (or 224) gives you 16,777,216 combinations. Image formats that can represent this many colors are called truecolor image formats; examples are JPEG and the truecolor type of PNG.

To save space when storing the image information in a file, one technique is to create a list of all the unique colors found in the image. The list of colors is called a palette (also called an index). Having the list of colors, you can represent the image by keeping track of which palette entry corresponds to each pixel.

The palette can contain any RGB value, but the most common palette image formats GIF and PNG8—limit the number of palette entries to 256. This doesn’t mean you can pick from only 256 predefined colors. On the contrary, any of the 16+ million colors
are up for grabs, but you can only have up to 256 of them in a single image.

最后一段说GIF和PNG8最多只能包含256色,并不意味着只能从256种已定义好的颜色中选择,可以从224种颜色中挑选!

另外,本章还给出一些关于CSS Sprite的优化建议

Highly Optimized CSS Sprites

Sometimes optimizing sprites is more complex than optimizing images. Diverse resources combined in one sprite may be harder to compress well. Following these best practices will make your sprite as small as possible:

  • Combine like colors; for example, sprite icons with a similar color palette.
  • Avoid unnecessary whitespace, making images easier to process on mobile devices.
  • Arrange elements horizontally instead of vertically. The sprite will be slightly smaller.
  • Limit colors to stay within the 256-color limit of PNG8.
  • Optimize individual images, and then the sprite. Color reduction will be easier with a limited palette.
  • Reduce anti-aliased pixels via size and alignment. If an icon is slightly off-square, you can often reduce the anti-aliased pixels by aligning the image horizontally or vertically.
  • Avoid diagonal gradients, which cannot be tiled.
  • Avoid alpha transparency in Internet Explorer 6 or quarantine images that require true alpha transparency in a separate sprite.
  • Change the gradient color every two to three pixels, rather than every pixel.
  • Be careful with logos. They are very recognizable, so even small changes are likely to be noticed.

10
七 10

Building Performance Into the New Yahoo! Homepage

via Building Performance Into the New Yahoo! Homepage by Nicholas Zakas, Yahoo!


10
七 10

background:url(#)的性能问题

很久之前写了使用 background:url(#) 解决 IE bug,原理是请求一张不存在的图片,不过写法有些问题。

写为

background:url(#)

会增加一个http请求,比如当前css的URL为

http://imgcache.qq.com/qzonestyle/project/css/xxx.css

则会多请求一次

http://imgcache.qq.com/qzonestyle/project/css/xxx.css#

和以下类似(详见解决IE6.0.2800压缩HTTP数据Bug之草记

http://imgcache.qq.com/qzonestyle/project/css/xxx.css?t=20100710.css

这样写可以避免这个问题

background: url(iesucks);

——————- 亡羊补牢的分隔线 2010-7-17 ——————-

上面的测试过程有些问题,经过用真实环境重新测试这样搞效果更差,若调用该css的页面地址是

http://www.99css.com/

则会先请求

http://www.99css.com/iesucks

之后301转向至

http://www.99css.com/iesucks/

改用透明图片不太甘心,不如变态一点,直接调用该css本身,因为css已经被下载并缓存了

background: url(http://imgcache.qq.com/qzonestyle/project/css/xxx.css);

16
五 10

Data URI&MHTML: 用还是不用?

YAHOO!的性能专家Stoyan Stefanov先后发布了

NCZ也有

引起了我们对data uri的关注,国内的也有一些不错的文章,比如:

工作太过饱和一直未深究,而前不久YDN的Performance on Yahoo! Search for Earth Day再次提到,更是撩起了我内心沉睡的欲望…

data URI的优缺点

data uri的主要优点是减少了http请求数,Best Practices for Speeding Up Your Web Site

Inline images use the data: URL scheme to embed the image data in the actual page. This can increase the size of your HTML document. Combining inline images into your (cached) stylesheets is a way to reduce HTTP requests and avoid increasing the size of your pages. Inline images are not yet supported across all major browsers.

还有就是调用起来比css sprite更加灵活,缺点是增加了客户端的资源消耗。

浏览器支持情况

Data URIs explained

Most modern browsers support data URIs:

  • Firefox 2+
  • Opera 7.2+ – data URIs must not be longer than 4100 characters
  • Chrome (all versions)
  • Safari (all versions)
  • Internet Explorer 8+ – data URIs must be smaller than 32k

不能太迷信权威,NET.2971 – The RFC 2397 data URL – Part 1这里说的比较靠谱:

2.3 – Maximum size

The size of data URIs is limited in some browsers. IE8 for example has a limit of 32,768 characters [4].

Filename Size[px] Size[kB] Size[chars]
Wallpaper_1600_1200.jpg 1600×1200 309 699052 – 9199 =

A test was done with IE 8 (8.0.6001.18702), Firefox 3.5.3 and Opera 10.0. A large wallpaper, 1600×1200 px, 309 kB was converted to Base64, resulting in almost 690k characters. This inline image was added to a HTML page and opened in the browser.

IE8 only displays the first part of the image (probably 32,768 characters), Firefox and Opera are showing the complete image.

When searching for information about maximum data size, Opera is often mentioned with a limit of 4100 characters, but this is apparently for older versions.

It is often said that inline images should be limited to small images, for example icons. In practice, however, often much larger images are used. Examples are the Google news pages with 80×80 px standard images (about 3000 characters), some pages contain more than 20 of them. We also see that all modern browsers support large data URLs which is a deviation from earlier policies.

MSDN上的data Protocol

Data URIs cannot be larger than 32,768 characters.

还有段视频Internet Explorer 8 Data URI(不想装淫光的下面有下载链接)

可以简单理解为我们只要把data URI的字符数控制在32768字符内就可以照顾到所有A级浏览器了。

IE6&7使用MHTML并注意MHTML在ie7/vista bug 解决方案就好了,JavaScript组件打包模式里说的比较明确:

MHTML在ie7+/vista缺少结束分割符无法显示,win03sp2缺少Content-Type会有安全提示,原因都MIME不标准,不是所有的东西都可以省。

下面要开始测试了,demo在此,是在WIN7 IE8的IE7模式进行的测试,结合httpwatchfiddler,虽然不是测试所有浏览器但可以反映出一些共同的问题。

PS:demo是在tommyfan的基础上改的,节省了我不少时间,感谢囯+先;99css所在的服务器大猫给开了gzip,有兴趣的朋友可以到 http://miao.in去看看:)

下载速度对比

正常网速

可见,base64稍慢

fiddler模拟低速


base64慢了不少

渲染时间对比

几毫秒可以忽略,不过还是base64偏慢,data:URI + mhtml troubles and solutions中有云:

data:URI takes much more time to be processed (in comparison to CSS Sprites or raw images) – about 10x more (for Firefox, for IE – 2x, for Opera/WebKit almost the same time). So in case of large images’ square (starting from 400×400, or 100k square dots), so you must be careful ibefore you completely convert all graphics to base64.

感官体验

并不是下载速度越快越好,还要考虑访问者的主观感受,比如逐步呈现(Progressiv Rencering),将css放顶部的原因就在于此,测试demo,虽然放底部速度更快,但放顶部可以逐步呈现,详见《High Performance Web Sites: Essential Knowledge for Front-End Engineers》(中译名:《高性能网站建设指南》)第五章的分析。

sprite的demo中页面是逐步呈现的,而base64在css下载完成前一直处于“白屏”状态

Data URIs for CSS Images: More Tests, More Questions走了点弯路,想把data uri的css放底部,可能他没看过《High Performance Web Sites》吧:) (Rob, this is only a joke~)

文件尺寸对比

原始的31个icon加起来16.5KB

sprite的css 1.4KB + 图片4.54KB = 5.94KB

data URI的css 51.2KB, gzip后16.5KB

对于大型站点来说流量 = ¥,这点sprite领先

CPU&内存对比

通过观察Windows任务管理器,base64比sprite多1%左右的CPU,多1M左右的内存

data URI使用建议

  • 能使用sprite的地方尽量使用sprite
  • 不方便使用sprite的时候才使用data uri,比如
    • 宽高不固定且又又要求background-position:center bottom
    • repeat/repeat-x/repeat-y的图片
    • png-24图片,IE6用α滤镜时图片请求不到会导致浏览器一直处于卡死状态,详见Image Optimization, Part 5: AlphaImageLoader,用mhtml代替则可避免此问题(先下载css,再从缓存调用自身)

以上结果跟demo本身的特点有很大关系,希望能看到各位的更多测试结果

除了文中提到的文章,下面的也不错:

另外,我写了个生成器,改天详细介绍:)


9
五 10

Balance is The Key to Life

via Please Don’t Touch the Slow Parts


19
三 10

css换行符对gzip的影响

之前做过一个css压缩工具CssOptimizer,其中一点是把换行符都去了,有同事反映这个做法过于极端,加上服务器端会进行gzip,这个换行符到底要不要去掉呢?于是拿了个项目中的文件简单测试了一下(css中的注释已去除):

去除换行符 保留换行符
gzip前 46.4KB 48.0KB
gzip后 8.40KB 8.58KB

可见,去除换行符对性能来说还是有好处的,不过前提是注意这些网站优化原则


20
一 10

[转载/翻译]优化浏览器渲染

ISD Webteam的大布同学(twitter:@tc_bryanzhang)牺牲了自己大量的xx时间翻译了Page Speed系列中的Optimize browser rendering,因其blog还在重新打造当中,所以偶这里先转载了,以下是翻译全文:

优化浏览器渲染

资源被下载到客户端后,浏览器仍需加载,解释,并渲染HTML、CSS和Javascript代码。只需利用现有浏览器的特性简单地编排你的代码和页面,就可以提升客户端的性能。

  1. 使用高效率的CSS选择器
  2. 避免CSS expressions
  3. 将样式表放在页面顶部
  4. 指定图像尺寸

使用高效率的CSS选择器

概述

避免低效率的匹配大量元素的键选择器【key selectors】可以加快页面渲染。

详细信息

当浏览器解析HTML时首先构造一个内部文件树来代表所有显示的元素。然后浏览器根据标准的CSS级联、继承和排序规则,为元素指定匹配的各种样式。在Mozilla里的执行情况(可能在其他浏览器也是这样),CSS搜索引擎通过样式规则为每个元素找到匹配的样式。该引擎由右至左评估每个规则,从最右边的选择器开始(称为“键”【Key】),并通过移动每个选择器,直到找到一个匹配或丢弃的规则。(“选择器”是应用规则的文档元素。)

基于此原则,引擎要评估的规则越少越好。所以提高渲染性能的重要一步就是删除未使用的CSS。在此之后,对包含大量的元素和/或CSS规则的页面来说,优化规则本身的定义就能够提高性能。优化规则的关键在于尽可能具体定义规则,并避免不必要的重复,让样式引擎快速找到匹配的规则,而不用花费时间查找不适用的规则。

下列各类规则被认为是低效的:

后代选择器的规则

例如:

通配选择器作为键的规则

body * {...}
.hide-scrollbars * {...}

标签选择器作为键的规则

ul li a {...}
#footer h3 {...}
* html #atticPromo ul li a {...}

后代选择器是低效的,因为对于每个与键相匹配的元素,浏览器必须遍历DOM树,评估每一个祖先元素,直到找到一个匹配或到达根元素。键越不具体,需要进行评估的节点数量就越大。

子代选择器和相邻选择器的规则

例如:

通配选择器作为键的规则

body > * {...}
.hide-scrollbars > * {...}

标签选择器作为键的规则

ul > li > a {...}
#footer > h3 {...}

子代选择器和相邻选择器是低效的,因为对每个匹配的元素,浏览器必须评估另一个节点。这样导致规则中的每个子选择器加倍消耗。同样,键越不具体,需要进行评估的节点数量就越大。尽管如此,虽然同样效率低下,在性能方面相对后代选择器而言,它们仍然是可取的。

有多余修饰的规则

例如:

ul#top_blue_nav {...}
form#UserLogin {...}

ID选择是唯一的定义。加上标签或类的限制只增加了多余的、引起不必要评估的信息。

对非链接元素应用:hover伪选择器的规则

例如:

h3:hover {...}
.foo:hover {...}
#foo:hover {...}
div.faa:hover {...}

非链接元素上的:hover伪选择器在某些情况下*会使IE 7 和IE 8 变慢。当页面没有一个严格的doctype时,IE 7 和IE 8 将忽略除了链接外的任何元素的:hover。当页面有严格的doctype,在非链接元素上的:hover将导致性能下降。

*查看bug报告http://connect.microsoft.com/IE/feedback/ViewFeedback.aspx?FeedbackID=391387

建议

避免通配选择器。

允许元素继承祖先的样式,或者使用一个类来给多个元素应用样式。

使您的规则尽可能具体。

尽量使用class和ID选择器而非标签选择器。

删除多余的修饰语。

这些修饰语是多余的:

ID选择器被class选择器和/或者标签选择器限制。

class选择器被标签选择器限制(当一个类只是用于一个标签,无论如何这都是一个很好的设计实践)。

避免使用后代选择器,特别是那些指定多余祖先的。

例如,这一个规则 body ul li a {...} 指定了一个多余的body选择器, 因为所有的元素都是body标签的后代。

使用class选择器代替后代选择器。

例如,如果您需要有序列表项和无序列表项有不同的两个样式,而不是使用两个规则:

ul li {color: blue;}
ol li {color: red;}

你可以将样式编码成两个类名并在规则中使用,例如:

.unordered-list-item {color: blue;}
.ordered-list-item {color: red;}

如果您必须使用后代选择器,尽量使用子代选择器,这最少只需评估一个额外的节点,而非中间直至祖先的所有节点。

在IE中避免对非链接元素应用:hover。

如果您对非链接元素应用:hover,请在IE7和IE8中测试并确保页面可用。如果您发现:hover导致性能问题,可以考虑条件性的为IE使用JavaScript onmouseover事件(只对IE写mouseover事件)。

附加资源

更多关于Mozilla里的高效CSS规则的细节,请看https://developer.mozilla.org/en/Writing_Efficient_CSS

有关CSS的完整信息,请看Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification。有关CSS选择器的资料,请看Chapter 5

Back to top

避免CSS expressions

概述

CSS表达式会降低浏览器的渲染性能;用其他方案替换它们将会改善IE浏览器的渲染性能。

注意:本节最佳实践只适用于Internet Explorer 5到7,它们支持CSS表达式。Internet Explorer 8放弃使用CSS表达式,而其他浏览器是不支持的。

详细信息

作为一种动态改变文档属性来响应各种事件的的手段,Internet Explorer 5引入了CSS表达式或 “动态属性”。它们由在CSS声明中的CSS属性值里嵌入JavaScript表达式构成。在大多数情况下,它们用于以下目的:

模拟其他浏览器支持但IE浏览器尚未支持的标准CSS属性。

使用比编写全面JavaScript注入式样式更小巧,更便捷的方法,来提供动态样式和高级的事件处理。

不幸的是,CSS表达式对于性能的不良影响是相当大的,因为每当有事件触发,浏览器都要重新计算每个表达式,如一个窗口改变大小,鼠标移动等。CSS表达式的低性能表现是IE 8弃用它们的原因之一。如果你在网页里使用CSS表达式,应该尽一切努力来消除它们并且使用其他方法来达到同样的功能。

建议

尽可能使用标准的CSS属性。

IE 8已高度兼容标准CSS;IE 8只有在“兼容”模式才支持运行CSS表达式,而在“标准”模式下则不支持。如果你不需要向后兼容旧版本的IE,你应该转换成标准的CSS属性来替换所有对应的CSS表达式。如需CSS属性和支持它们的IE版本的完整列表,请参见MSDN的CSS属性索引。如果你确实需要支持所需CSS属性不可用的旧版本IE浏览器,请使用JavaScript来实现等效的功能。

使用JavaScript脚本样式。

如果你正在使用CSS表达式来实现动态样式,用纯JavaScript重写它们是很有意义的,因为这样既能提高IE性能,同时在其他浏览器获得相同效果的支持。在这个由MSDN动态属性页提供的例子里,下面的CSS表达式用于在浏览器里居中一个HTML块元素,并且该元素的尺寸可以在运行时改变,每次调整窗口大小都能重新定位在浏览器中心:

<div id="oDiv" style="background-color: #CFCFCF; position: absolute;
left:expression(document.body.clientWidth/2-oDiv.offsetWidth/2);
top:expression(document.body.clientHeight/2-oDiv.offsetHeight/2)">Example DIV</div>

下面是一个使用JavaScript和标准CSS的等价例子:

<style>
  #oDiv { position: absolute; background-color: #CFCFCF;}
</style>

<script type="text/javascript">
 // Check for browser support of event handling capability
  if (window.addEventListener) {
  window.addEventListener("load", centerDiv, false);
 window.addEventListener("resize", centerDiv, false);
  } else if (window.attachEvent) {
  window.attachEvent("onload", centerDiv);
  window.attachEvent("onresize", centerDiv);
  } else {
  window.onload = centerDiv;
  window.resize = centerDiv;
  }

  function centerDiv() {
  var myDiv = document.getElementById("oDiv");
  var myBody = document.body;
  var bodyWidth = myBody.offsetWidth;

  //Needed for Firefox, which doesn't support offsetHeight
  var bodyHeight;
 if (myBody.scrollHeight)
 bodyHeight = myBody.scrollHeight;
 else bodyHeight = myBody.offsetHeight;

  var divWidth = myDiv.offsetWidth;

  if (myDiv.scrollHeight)
   var divHeight = myDiv.scrollHeight;
   else var divHeight = myDiv.offsetHeight;

 myDiv.style.top = (bodyHeight - divHeight) / 2;
  myDiv.style.left = (bodyWidth - divWidth) / 2;
  }

</script>

如果您使用CSS表达式来模拟早期IE版本中不可用的CSS属性,你应该提供版本测试的javascript代码,为支持CSS的浏览器禁止CSS表达式。举例来说,max-width属性,这个属性在一定数量的像素范围内强制文本换行,在IE 7前是不支持的。下面的CSS表达式作为一种解决方法,为IE 5和6提供了这个功能:

p { width: expression( document.body.clientWidth > 600 ? "600px" : "auto" ); }

为不支持此属性的IE浏览器版本使用等价的JavaScript替换CSS表达式,可以使用类似于下面的内容:

<style>
  p { max-width: 300px; }
</style>

<script type="text/javascript">

  if ((navigator.appName == "Microsoft Internet Explorer") && (parseInt(navigator.appVersion) < 7))
  window.attachEvent("onresize", setMaxWidth);

  function setMaxWidth() {
  var paragraphs = document.getElementsByTagName("p");
  for ( var i = 0; i < paragraphs.length; i++ )
  paragraphs[i].style.width = ( document.body.clientWidth > 300 ? "300px" : "auto" );

</script>

Back to top

将样式放在页面头部

概述

将内联样式块和<link>元素从页面<body>移动到页面<head>中,这样能提高渲染性能。

详细信息

在HTML文件<body>中指定外部样式表和内联样式块可能对浏览器的渲染性能产生不利影响。浏览器阻塞渲染网页直到所有外部的样式表都已被下载。(用<style>标记指定的)内联样式块可能会导致reflows和页面跳动。因此,把外部样式表和内联样式块放在页面的<head>中是很重要的。通过确保样式表先被下载和解析,可以让浏览器逐步渲染页面

建议

HTML 4.01规范(第12.3节)规定,始终把使用<link>标签的外部样式表放在<head>部分里。不要使用@import。还要确保您指定的样式有正确的顺序

<style>区块放在<head>部分里。

Back to top

指定图片尺寸

概述

为页面中所有图片指定宽度和高度可以消除不必要的reflows和重新绘制页面【repaints】,使页面渲染速度更快。

详细信息

当浏览器勾画页面时,它需要能够流动的,如图片这样的可替换的元素。提供了图片尺寸,浏览器知道去环绕附近的不可替换元素,甚至可以在图片下载之前开始渲染页面。如果没有指定的图片尺寸,或者如果指定的尺寸不符合图片的实际尺寸,一旦图片下载,浏览器将需要reflows和重新绘制页面。为了防止reflows,在HTML的<img>标签中或在CSS中为所有图片指定宽度和高度。

建议

指定与图片本身相一致的尺寸

不要使用非图片原始尺寸来缩放图片。如果一个图片文件实际上的大小是60×60像素,不要在HTML或CSS里设置尺寸为30×30像素。如果图片需要较小的尺寸,在图像编辑软件中,设置成相一致的尺寸(详见优化图像。)

一定要指定图片或它的块级父元素的尺寸

一定要设置<img>元素本身,或它的块级父元素的尺寸。如果父元素不是块级元素,尺寸将被忽略。不要在一个非最近父元素的祖先元素上设置尺寸。

Back to top

注:浏览器为了重新渲染部分或整个页面,重新计算页面元素位置和几何结构的进程叫做reflow


1
十二 09

The Life of Page 2.0


via The performance roadmap


29
十一 09

Websites On Speed


via Websites On Speed


25
十 09

[翻译]OOCSS FAQ

在OOCSS中怎么定义“对象”?

对象类似JAVA中的类,保持着OO的特征。

一个CSS对象由4部分组成:

  1. 可能是一个或多个DOM节点的HTML
  2. 由wrapper节点的class名开始的CSS样式声明
  3. 类似于背景图片和显示用的sprites组件以及
  4. JavaScript行为,监听或者与对象关联的方法

这可能令人费解,因为每个CSS class不是其自身必要的对象,但可以是一个wrapper class的一个部件。比如:

<div class="mod">
        <div class="inner">
                <div class="hd">Block Head</div>
                <div class="bd">Block Body</div>
                <div class="ft">Block Foot</div>
        </div>
</div>

对象是一个class为mod的模块。包括4个部件节点(不能独立于模块外,包括2个区块,inner和body,和两个可选择的区块,head和foot)

OOCSS如何提升性能?

OOCSS具有双倍的性能优势:

  1. 高度重用的CSS代码,只需要很少的CSS代码,意味着:
    • 更小的文件,从而更快的传输
    • CSS代码在站点页面中调用的比重增大则有希望被复用或被浏览器缓存
  2. 就浏览器而言更少的重绘和布局计算
    • 单个页面,CSS规则复用的越多,渲染引擎花在“computed values”的计算时间越少
    • 手动增加的”extending”类,重写更少的规则,这再一次意味着引擎做很少去应用规则

要用ID来对内容写样式吗?

当你在同一页面(或者同一站点同时缓存良好)复用一个对象时,这是性能的“免费赠品”。用ID来写样式在同一页面中只能使用一次。@cgriego (twitter)拿它与singletons比较过,我认为非常精确。可能有些情况下你要用ID定义样式,比如非常特殊的header menus,此时你可以在用ID来沙箱(译注:动名词)特殊元素并确保此处的代码不会影响站点的其它地方。选择ID而非class前要三思,随着站点的发展,真的很难预料其他人会怎么处理依据你的CSS所构建的HTML。如有选择的余地,尽可能的考虑扩展性。

我正在考虑移除模板head, body, foot中的ID。某些人或许有多个主区域。站点的多个header 和 footer更难以猜测,但我敢打赌肯定有设计师会这样想,所以ID很可能会消失(不太顺,看原文:Someone could have multiple main content areas. Multiple site headers and footers are more difficult to imagine, but I bet there is a designer who can dream up something like that, so the IDs are very likely to disappear.)。

另一方面,ID hooks 对链接非常有用(译注:做锚点使用)。放在HTML中,不过别用它们来写样式。

设计师可以写OOCSS吗?

是的,设计师出于本能理解对象,比多数人当前书写CSS的方式要形象 — layers of exceptions (想一下,一个老太太吞了一只苍蝇)。事实上,他们爱上OOCSS的原因有两个:

  1. 这使他们能快速创建复杂高点击量的站点。他们不需纠结于不理解的结构除非有足够的能力并充足的了解语法
  2. 学CSS时,他们不需创建丑陋的 “hello world!” 站点。设计师在非常在意的是他们的工作看起来很漂亮。如果必需做一些丑陋的东东,即便是学习之由,他们很快就会有挫败感并灰常的郁闷。OO-CSS使得他们的工作在每个学习阶段都看起来很漂亮

设计师是聪明D。我们要给他们信任。他们会讲一种不同的,非工程师的语言,但是极客的语言经常以一种丑陋的方式来拒绝人。我们能做的更好。

我是个前端架构师,如何向团队传授OOCSS?

作为架构师,你应该写结构对象;圆角如何创建,为角或其他特性放置表象元素,并处理浏览器差异。新手为这些模块写皮肤(borders, colors, background images, 等等)。

我用OO-CSS方式创建了大批站点(千级的页面,百万级的访问者)。正确的完成后,很好扩展,这意味着新手将处理的个别元件可预见性很强。代码审阅很容易,因为有可接受的方法明确的规则来扩展对象。这种回馈使新开发者快速生产。

我在FullSIX(一个法国的网络营销机构)管理一个前端开发团队,是我工作过的最有才能的。某些时候我们的成功意味着我们将会有更多难以把控的工作。雇佣前端专家非常困难(没有这种学校!),所以我开始对一些对写代码有兴趣的设计师(很少或没有经验)推行一个内部实习项目,一个月就可以作为团队的初级成员工作。

  • 第一周:学习语义并根据现有的CSS创建HTML。学习创建网页:不需要更多的CSS,HTML语法,多个class,验证,语义,介绍代码审阅等
  • 第二周:创建简单的内容对象(标题,列表等),持续一周。学习CSS语法,怎么扩展对象,颜色,字体百分比,等等
  • 第三周:创建区块的皮肤。边框,颜色,背景图片,基本的布局,sprites。让他们同一个回答过n个问题的资深开发者一起工作,使他们少走弯路,他也应是很好的代码审阅者。
  • 第四周:他们已经是团队的皮肤制作成员了。

他们的代码在一个客户的网站上,同资深开发者写的一样好,或许更好因为他们还未学到一些坏习惯:)

入门:如何使用这些文件?

3个文件,libraries.css (reset 及 fonts 取自 yui), grids.css 及 template.css 已完成,其它的还非常不稳定。

  1. 打开template.html并存为新文件
  2. 通过扩展相应的对象来改写列的数量及宽度。站点中只需一个模板,即使你有不同列的页面,因为列也是对象。可以把它们当作任意的区域,可能会有0 ~ n个左列。查阅模板文档可了解更多
  3. 用栅格来分割内容区域为小的区块。查阅栅格文档了解更多
  4. 添加内容。提示:这也应OO

如何部署在站点上?

注意CSS文件在不断改进中,我会依据接到的反馈进行改变。

我把CSS文件分为了模块,比如栅格和模板。在使用时移除不必要的注释并减少HTTP请求,否则站点会超级慢。这意味着要合并CSS文件为一个稍大的文件。我通过嵌套的注释来组织CSS。最后,作为上线/部署的一部分,用CSS压缩器来移除注释.

可以修改文件,或者用我自己的样式重写吗?

我不会修改grids, template, 或者 libraries。大量测试表明这些已恰到好处。如果要自定义,考虑下面的扩展基本对象

粉红不是我要的颜色!怎么处理content.css?

获取你会想要修改content.css。去吧,改颜色,字体大小,大小写。只需注意这个文件在快速发展,同时我还没有任何文档来说明如何正确的处理。我会这么做,我保证。

我需要不只6种标题(h1~h6),如何增加?

如果需要不只6中标题样式,通过添加一个新class来扩展标题对象。

.category{font-size:108%; font-weight:normal; font-style: normal; text-transform:uppercase; color: #333;}

不要这样做:

#mySaleModule h2, #mySaleModule .h2{font-size:108%; font-weight:normal; font-style: normal; text-transform:uppercase; color: #333;}

如何扩展对象?

如果要扩展对象,比如一个160px的左列,而非默认值,你可以再列上增加额外的class。

<div class="leftCol gMail"> ... </div>

如果默认值和扩展的列宽或者页面不适合你的站点,你可以扩展列来实现自定义的宽度。

myColumn 扩展列对象来实现自定义列宽。

.myColumn{width:400px;}

HTML

<div class="leftCol myColumn"> ... </div>

不要通过重写我的class来实现,而应扩展此框架提供的对象。我提供了列,标题及其他对象。你可以通过增加另外的class(只指定与我的基本对象的不同点)来扩展这些对象。相对而言此处混合比较好。

不要这样做(因为更新我的框架时会有些麻烦):

.leftCol{… 此处自定义CSS …}

没有用到的样式。我的站点没有160px的gmail式的列,可以移除吗?

当然。移除对象或扩展对象非常合理。只需注意在站点发展时,很难预料到其他人用你的CSS创建的什么样的HTML。过早优化很危险。

为什么有一个单独的模板?

在OOCSS中,一个重要的目标是所有的页面创建自一个模板。这简化了CMS开发,因为有一个单独的起始点所有页面可以制作为其他的页面。CMS的用户不会落入已创建的页面不能变种为不同的页面类型的陷阱。OO模板的另一个目标是每一个section(列,header等)控制自己。实际上,这意味着如果要在模板上增加一个左列,只需在HTML中增加此列。你从来不想这样写CSS吧,为了使子元素满足表现而DOM树需要很多改变。对CMS开发来说DOM循环相当的昂贵。

这有语义吗?我要终止像 .formYellow 或 tinyBlueH2 的class命名吗?

OOCSS可以写得有语义也可无语义,取决于你创建模块时用 errorMod 而非 bigRedModule。我选择class名优一些原则(排名不分先后):

  • 短 – 每一字节计算起来,所以尽可能保持class短
  • 清晰 – 可预料的行为/样式要显而易见
  • 语义化 – 对象什么高过看起来像什么。如何用在站点中?
  • 通用 – 名称应该适用于多数站点。过于特殊的名称减少了适用场合或导致语义化的class以非语义化的方式使用
  • 屏幕 – 移动阅读器或打印样式或许有不同的视图,会重写默认的屏幕视图,所以当有冲突时class为屏幕而特殊定义(Different views might be provided by mobile or print stylesheets, however they override the
    default screen view, so the classes chosen are screen specific when there was a conflict)。这简化了开发。

其它的框架如何?这只能同YUI一起使用吗?

在大量框架的生态系统中,YUI是专业性及可扩展性的一例。我同他们进行了对比,因为我不断受到他们代码和文档的影响。OOCSS不是一个真正意义上的框架,尽管我创建了很多例子,而是一种书写可扩展,健壮,可维护性强的CSS的一种方式。也许最好的比喻是一个新的语言。最终,它是未知的JavaScript库(it is JavaScript library agnostic),我希望贡献代码回YUI及其他框架。

CSS框架太超过!我需要从头开始编写所有代码吗?

每需要一个随机数字都要写一个数字class吗?

CSS is hard,not because it is broken , but because it is a legitimate technology requiring expertise to architect correctly. 为每个站点重复发明轮子非常的愚蠢。

源文件中右列在主列之前,会影响可访问性,SEO吗?

我早期工作过的站点有更标准的模板结构,body上有一个极好的class,依靠这个模板显示或隐藏左右列。自定义CMS的用户要创建一个3列布局的页面时非常沮丧,发现需要两列,找到它们不得不一个个从头开始,因为有多个模板/起始点。你或许注意到主列是个流体列,在左右两列渲染后自适应剩余的空间。

我更喜欢标签排序胜过视觉排序(因为如果标签顺序改变会变得非常怪异),但是我也只想要一个模板。在web开发中经常遇到的是,两个重要的目标发生了冲突,我做判断如何解决。这种情况下标签排序满足视觉顺序除了右列。在当前的代码中,只需在HTML增加一个左或右列,没有别处昂贵的DOM变化。

屏幕阅读器用户有两个选择:

  1. 跳过链接
  2. 导航链接经常为一个链接列表或嵌套的链接列表形式。这非常有趣,因为这允许屏幕阅读者通过屏幕阅读器的特殊操作设置跳过整个列表。

我的意见是对于跳过菜单这两种方式足够了。

每个人似乎都有一个回复观点:SEO,它们都不同,甚至相反。:)基于这个思潮,我倾向于:尤其对含有一定合理数量链接的导航菜单,不用太过在意。曾几何时,我看到过导航链接被索引在搜索结果的内容部分,不过是在几年前了。搜索爬虫非常智能,我已经准备好想当然的认为如果我以语义化,干净的方式标记内容,并非填充一坨垃圾链接,爬虫能区分的出来。

把导航菜单标记为列表,允许屏幕阅读器用户跳过,并提供“跳至内容”链接,对可访问性提供了双倍的备用措施。

为什么用了_ hack?我能把这些代码放在单独的文件中吗?或者添加IE专有的class?

很显然,首先考虑的是尽可能少和长远。

  1. 添加一个单独的样式表奖增加一个额外的HTTP请求,增加整体文件的大小,这早已是浏览器性能的对立点
  2. 我喜欢把一个对象的代码放在一个地方。我认为这有助于减少hack的数量,尤其是当项目随时间而发展
  3. IE6-的开发工具非常原始,这使得hack和普通代码放在一起更加重要。我想能尽快找到一个可以使用属性的IE bug。同样,我认为这有助于减少hack
  4. 规则表明浏览器理解不了的属性会被忽略。对IE6-使用_早已众所周知,可以合理的预料好的浏览器将会忽略这个属性
  5. 使用条件注释意味着每个HTML页面必须包含一个IE专用样式。某一天(我不能等了!)当IE6的市场份额下降至像IE5那样低时,我将去除这些代码,但最后我要做的是触及百级或千级的HTML页面。我宁愿只有依赖CSS hack的CSS,而不是把它放在HTML中。不幸的是,恕我直言,IE6兼容性的末日比我们期望的要更加长远,因为IE中的quirksmode会回落到IE5.5的模式

我认为我的选择有助于减少hack的总体数量,提升性能,并只有忽略不计的风险。话说回来,如果觉得代码中的_令你作呕,你完全可以移至单独的文件。

为了添加表象效果比如边框而使用空 <b> 标签容器对象,会给屏幕阅读器用户带来问题吗?

不会,幸运的是屏幕阅读器会忽略空的b标签。使用这个表象标签(b是加粗)来实现表象具有优势。这个标签可以通过服务器端脚本包含,以至于有一天所有的CSS圆角和阴影都支持了,可以关闭脚本并拥有漂亮,干净,语义化的HTML。

OOCSS声称避免位置依赖的样式。是否意味着我不能使用类似 .myModule .title 的派生选择器?

不使用派生选择器没什么阻碍,只是把它们放在更高的DOM树而已。避免在body或页面中最外层的div放置wide-net class或id,然后对对象产生的变量写大量的样式。这不能复用,同时会使页面渲染变慢。相反,通过直接在对象上添加一个class来增加一个多余的“local”变量(并对其子元素写派生样式)。

一个好的经验是一个容器主体(body of a container)内的任意元素显然是一个单独的对象。

这无可厚非,因为UL显然是一个单独的对象:

#sidebar ul { ... }

因此,carousel显然不是body对象的一部分:

body.browseProducts .carousel

这是适当的层叠应用,因为子节点真正的是较大的父对象的一部分。b(角)和inner显然隶属于moudle,它们不能独立存在:

.myModule { ... }
.myModule b { ... }
.myModule .inner { ... }

如何贡献?

最好的方法是涉足其中,开始使用代码(libraries, grids, fonts)并提交bug 报告及功能需求。 我建了一个OOCSS google group 来进行超过140个twitter字符的讨论。

译注:

OOCSS的官方站点为 http://oocss.org,有一些例子及下载等。