欢迎光临

木子屋

标题: IE对CSS样式表的限制和解决方案

作者: dnawo

日期: 2009-09-15 01:02 AM

分类: HTML/CSS

内容: HTML文档与CSS的关联常见有4种方式：
1.使用link标记
复制内容到剪贴板 程序代码<link rel="stylesheet" type="text/css" href="sheet.css" />
2.使用style元素
复制内容到剪贴板 程序代码<style type="text/css">
body{background:#fff;}
h1{font-size:2em;}
</style>
3.使用@import指令
复制内容到剪贴板 程序代码<style type="text/css">
@import url(sheet1.css);
@import "sheet2.css";
</style>
4.使用style属性的内联样式(inline style)
复制内容到剪贴板 程序代码<p style="color:#f00;">这是红色的字</p>
在实际应用中，使用style属性的内联样式是不推荐使用的，XHTML1.1已经将其标准为不建议使用，原因很简单这种方式不比font标记强多少，削弱了CSS集中控制整个文档外观的优点。前3种方式利用了link标记和style标记，在IE(包括IE6、IE7和IE8 beta1)中有如下限制：
1.文档中只有前31个link或style标记关联的CSS能够应用。
从第32个开始，其标记关联的CSS都将失效。IE的官方文档All style tags after the first 30 style tags on an HTML page are not applied in Internet Explorer也提及这个限制，包括在使用.xsl的.xml文件也有这个限制。但是似乎写错了数量。
2.一个style标记只有前31次@import指令有效应用。
从第32个@import指令开始忽略。
3.一个css文件只有前31次@import指令有效应用。
从第31个@import指令开始忽略。
4.IE中每个style标签或css文件的选择符个数不能超过4095。
5.@import指令下层叠限制不能超过4层
在IE下通过@import指令引入css文件时，第5层会失效。这个限制来自Cascade limit via @import rule。实际上，由于浏览器对多层嵌套的支持不完善，所以即使不得已使用了@import指令引入CSS文件，也不要超过2层。
IE对CSS的限制在绝大部分情况下是不会遇到的，即使遇到最佳的解决方案也应该是手动或者通过后端程序对CSS文件和响应的标记进行合并，最小化的http请求数是优化页面呈现的第一原则。
在IE中，可以通过document.styleSheets对象（Firefox、Opera9和Safari3.1都支持）修改内联和嵌入样式的值。该对象仅在文档包含style或link元素时可用，其实用document.styleSheets.length就可以看出IE下这个值最大是31。下面是利用Javascript来合并link和style标记来解决IE下的限制：
复制内容到剪贴板 程序代码var fnMergeStyleSheet = function(){
if(!document.styleSheets){
return;
}
var aSheet = document.styleSheets,
aStyle = document.getElementsByTagName('style'),
aLink = document.getElementsByTagName('link');
if(aStyle.length + aLink.length < 32 || !aSheet[0].cssText){
//document.styleSheets.cssText 只有IE支持
return;
}
var aCssText = [],aCloneLink = [];
//把style标签中的样式存入，然后删掉该标签，但保留第一个
//因为由getElementsByTagName方法返回值是nodeList，所以删除时循环用倒序
for(var i=aStyle.length-1;i>-1;--i){
var o = aStyle[i];
aCssText.push(o.innerHTML);
if(i>0){
o.parentNode.removeChild(o);
}
}
//在IE中只有在31之内的link标签才能通过其styleSheet.cssText获取样式
//无法的获取复制到一个数组aCloneLink中
for(var i=aLink.length-1;i>-1;--i){
var o = aLink[i];
if(o.getAttribute && o.getAttribute('rel')==='stylesheet'){
if(o.styleSheet){
aCssText.push(o.styleSheet.cssText);
}else{
aCloneLink.push(o.cloneNode(true));
}
if(i>0){
o.parentNode.removeChild(o);
}
}
}
var oHead = document.getElementsByTagName('head')[0];
//通过前面的删除，前31个link或者style标记最多只剩下2个
//通过重新增加link节点的方法激活其styleSheet属性，从而获取样式
for(var i = aCloneLink.length-1;i>-1;--i){
var o = aCloneLink[i];
oHead.appendChild(o);
aCssText.push(o.styleSheet.cssText);
oHead.removeChild(o);
}
//把所有的样式都复制给第一个标签
aSheet[0].cssText += aCssText.join('');
}
上面仅仅是一个简单的粗糙的解决方案，可以改进的地方还有：
1.没有考虑media这个属性，如果有多个media应该分别合并，当然更没有考虑link标记的rel="alternate stylesheet"带来的影响。但我更建议通过@media指令把相应的样式写在同一个文件中，至少可以减少HTTP连接数。
2.没有解决@import指令31次限制的问题，其实可以提取其href值然后进行激活处理。但是实际应用在建议用link标记来替代@import指令，因为在IE中@import指令相当与把link标记写在文档的底部，会导致在IE5/6页面加载时瞬间无样式问题，学名叫“Flash of Unstyled Content”（简称为FOUC）的bug，当然可以通过在文档头中放一个link或script元素可以避免这个bug。
3.一般来讲页面之所有出现大量的link或者style标签很可能有很多是相同的，可以在aCssText合并前除掉相同的项，减少代码量。
如果不用DOM中已存在的样式元素直接通过cssText属性添加样式代码，而是创建一个新的样式元素来添加，一定要注意先把新建的样式元素先添加到DOM中，然后再通过cssText属性添加样式代码。反之，其添加的样式代码似乎先被IE6的样式解析器解析后才添加，这样!imporant和hack都将失效。请看例7。不建议通过添加新的样式元素的方式来添加新的样式，这样很容易达到IE的限制条件。

+ 查看当前日志评论 (0)

登录

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 1.162 ms

返回

标题: IE对CSS样式表的限制和解决方案

你没有权限发表评论

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 1.162 ms

返回

暂无评论

返回

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 1.176 ms

返回