IE对CSS样式表的限制分析与解决方案
程序员文章站
2022-06-14 16:04:02
html文档与css的关联常见有4种方式: 使用link标记
html文档与css的关联常见有4种方式:
使用link标记
<link rel="stylesheet" type="text/css" href="sheet.css" />
使用style元素
<style type="text/css">
body{background:#fff;}
h1{font-size:2em;}
</style>
使用@import指令
<style type="text/css">
@import url(sheet1.css);
@import "sheet2.css";
</style>
使用style属性的内联样式(inline style)
<p style="color:#f00;">这是红色的字</p>
在实际应用中,使用style属性的内联样式是不推荐使用的,xhtml1.1已经将其标准为不建议使用,原因很简单这种方式不比font标记强多少,削弱了css集中控制整个文档外观的优点。前3种方式利用了link标记和style标记,在ie(包括ie6、ie7和ie8 beta1)中有如下限制:
文档中只有前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文件也有这个限制。但是似乎写错了数量。请在ie看:
例1:34个style标记同时应用
例2:1个style标记和34个link标记同时应用
一个style标记只有前31次@import指令有效应用。
从第32个@import指令开始忽略。请看:
例3:在一个style标记中使用34次@import指令。
一个css文件只有前31次@import指令有效应用。
从第31个@import指令开始忽略。请看:
例4:用link标记引入一个使用34次@import指令的css文件
例5:用style标记引入一个使用34次@import指令的css文件
例6:用link和style标记分别引入一个使用31次@import指令以上的css文件
一个css文件的不能超过288kb?
这个消息来自internet explorer css file size limit。
@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和例2,可以改进的地方还有:
没有考虑media这个属性,如果有多个media应该分别合并,当然更没有考虑link标记的rel="alternate stylesheet"带来的影响。但我更建议通过@media指令把相应的样式写在同一个文件中,至少可以减少http连接数。
没有解决@import指令31次限制的问题,其实可以提取其href值然后进行激活处理。但是实际应用在建议用link标记来替代@import指令,应为在ie中@import指令相当与把link标记写在文档的底部,会导致在ie5/6页面加载时瞬间无样式问题,学名叫“flash of unstyled content”(简称为fouc)的bug,当然可以通过在文档头中放一个link或script元素可以避免这个bug。
一般来讲页面之所有出现大量的link或者style标签很可能有很多是相同的,可以在acsstext合并前除掉相同的项,减少代码量。
如果不用dom中已存在的样式元素直接通过csstext属性添加样式代码,而是创建一个新的样式元素来添加,一定要注意先把新建的样式元素先添加到dom中,然后再通过csstext属性添加样式代码。反之,其添加的样式代码似乎先被ie6的样式解析器解析后才添加,这样!imporant和hack都将失效。请看例7。不建议通过添加新的样式元素的方式来添加新的样式,这样很容易达到ie的限制条件。
使用link标记
<link rel="stylesheet" type="text/css" href="sheet.css" />
使用style元素
<style type="text/css">
body{background:#fff;}
h1{font-size:2em;}
</style>
使用@import指令
<style type="text/css">
@import url(sheet1.css);
@import "sheet2.css";
</style>
使用style属性的内联样式(inline style)
<p style="color:#f00;">这是红色的字</p>
在实际应用中,使用style属性的内联样式是不推荐使用的,xhtml1.1已经将其标准为不建议使用,原因很简单这种方式不比font标记强多少,削弱了css集中控制整个文档外观的优点。前3种方式利用了link标记和style标记,在ie(包括ie6、ie7和ie8 beta1)中有如下限制:
文档中只有前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文件也有这个限制。但是似乎写错了数量。请在ie看:
例1:34个style标记同时应用
例2:1个style标记和34个link标记同时应用
一个style标记只有前31次@import指令有效应用。
从第32个@import指令开始忽略。请看:
例3:在一个style标记中使用34次@import指令。
一个css文件只有前31次@import指令有效应用。
从第31个@import指令开始忽略。请看:
例4:用link标记引入一个使用34次@import指令的css文件
例5:用style标记引入一个使用34次@import指令的css文件
例6:用link和style标记分别引入一个使用31次@import指令以上的css文件
一个css文件的不能超过288kb?
这个消息来自internet explorer css file size limit。
@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和例2,可以改进的地方还有:
没有考虑media这个属性,如果有多个media应该分别合并,当然更没有考虑link标记的rel="alternate stylesheet"带来的影响。但我更建议通过@media指令把相应的样式写在同一个文件中,至少可以减少http连接数。
没有解决@import指令31次限制的问题,其实可以提取其href值然后进行激活处理。但是实际应用在建议用link标记来替代@import指令,应为在ie中@import指令相当与把link标记写在文档的底部,会导致在ie5/6页面加载时瞬间无样式问题,学名叫“flash of unstyled content”(简称为fouc)的bug,当然可以通过在文档头中放一个link或script元素可以避免这个bug。
一般来讲页面之所有出现大量的link或者style标签很可能有很多是相同的,可以在acsstext合并前除掉相同的项,减少代码量。
如果不用dom中已存在的样式元素直接通过csstext属性添加样式代码,而是创建一个新的样式元素来添加,一定要注意先把新建的样式元素先添加到dom中,然后再通过csstext属性添加样式代码。反之,其添加的样式代码似乎先被ie6的样式解析器解析后才添加,这样!imporant和hack都将失效。请看例7。不建议通过添加新的样式元素的方式来添加新的样式,这样很容易达到ie的限制条件。