提醒:本页面将不再更新、维护或者支持,文章、评论所叙述内容存在时效性,涉及技术细节或者软件使用方面不保证能够完全有效可操作,请谨慎参考!

某个项目需要支持打印样式,测试下来Chrome和FireFox正常,唯独IE8无法应用打印样式,也就是说识别不了 @media 定义的CSS样式节。

网上解决的办法也五花八门,我在这里整理一下,首先我们还是要从让IE支持media的的思路开始,首先JavaScript大将出马。

1. 项目css3-mediaqueries-js

该项目由Wouter van der Graaf发起( 项目地址 ),旨在为了提供对于类似于 IE 5+ Firefox 1+ Safari 2 低版本浏览器的Media Queries支持,使用方式也很简单,直接引用脚本即可,当然现在基本上非IE的浏览器和IE9及以上版本已经原生支持Media Queries了,所以我们可以使用IE特有的条件注释处理代码引用,比如下面的代码示例:

<!-- css3-mediaqueries.js for IE less than 9 -->
<!--[if lt IE 9]>
<script 
   src="//css3-mediaqueries-js.googlecode.com/svn/trunk/css3-mediaqueries.js">
</script>
<![endif]-->

遗憾的是在IE8浏览器下实际测试下来并没有效果。

2. 使用CSS Hack

IE各个版本对CSS都有一些怪异的支持模式,猜测是浏览器开发人员故意留下的,所以我们可以利用这种特性对IE浏览器进行CSS Hack。

Keith Clark在其博文 《Moving IE specific CSS into @media blocks》 提供了一种CSS Hack的新思路:

目标平台IE6或者IE7:

@media screen\9 {
    body { background: red; }
}

目标平台IE6、7和8:

@media \0screen\,screen\9 {
    body { background: green; }
}

目标平台IE8:

@media \0screen {
    body { background: blue; }
}

目标平台IE8、9和10:

@media screen\0 {
    body { background: orange; }
}

目标平台IE9和10:

@media screen and (min-width:0\0) {
    body { background: yellow; }
}

使用示例

body {
  background: pink;
}

/* IE 6 and 7 fallback styles */
@media all\9 {
    body {
        background: red;
    }
    h1 {
        color: yellow;
    }
}

/* IE 6 and 7 fallback print styles */
@media print\9 {
    body {
        color: blue;
    }
    h1 {
        color: red;
    }
}

大家可以访问 《IE specific CSS rules and bypass filters using @media block hacks》 来测试相关属性及获取支持情况。

3. 使用onbeforeprint和onafterprint方法

这里我再提供一个思路供大家参考,我们可以给body设置一个id,比如这样的:

<html>
	<head></head>
	<body id="MyPage"></body>
</html>

然后JavaScript代码可以这样写:

window.onbeforeprint = function() {
    document.getElementById("MyPage").className += " printstyle";
};
window.onafterprint = function() {
    document.getElementById("MyPage").className =
   	document.getElementById("MyPage").className.replace
      		( /(?:^|\s)printstyle(?!\S)/g , '' );
};

最后CSS代码类似如下:

.printstyle div { /* div style */ }
.printstyle p { /* paragraph style */ }

这里利用了JavaScript触发的打印前和打印后的两个事件,对页面的 class 引用做出修改,这样就可以让不同的CSS样式表发生作用。

这里再说个题外话: onbeforeprint onafterprint 在IE和FireFox中支持良好,如果我们需要利用这两个事件设置其他的效果,这时发现这个事件属性不是跨浏览器的,比如WebKit家族的Chrome就不支持,参考 《Detecting Print Requests with JavaScript》 这里有个替代的办法:

var mediaQueryList = window.matchMedia('print');
mediaQueryList.addListener(function(mql) {
    if (mql.matches) {
        console.log('onbeforeprint equivalent');
    } else {
        console.log('onafterprint equivalent');
    }
});

兼容的写法如下:

(function() {
    var beforePrint = function() {
        console.log('Functionality to run before printing.');
    };
    var afterPrint = function() {
        console.log('Functionality to run after printing');
    };

    if (window.matchMedia) {
        var mediaQueryList = window.matchMedia('print');
        mediaQueryList.addListener(function(mql) {
            if (mql.matches) {
                beforePrint();
            } else {
                afterPrint();
            }
        });
    }

    window.onbeforeprint = beforePrint;
    window.onafterprint = afterPrint;
}());

好了,扯多了,让我们继续回到IE浏览器打印上面,毕竟其他浏览器对页面打印支持良好。

参考微软MSDN的文章 《Scripting Support for Web Page Printing》 我们可以获取更多关于IE打印专属的特性,比如我们除了使用 window.print() 调用打印功能外还可以使用WebBrowser控件实现相关功能,比如下面的代码同样的实现了打印:

document.body.insertAdjacentHTML("beforeEnd",
    "<object id=\"idWBPrint\" width=0 height=0 \
      classid=\"clsid:8856F961-340A-11D0-A96B-00C04FD705A2\">
    </object>");
  idWBPrint.ExecWB(6, 1);
  idWBPrint.outerHTML = "";

实际上对于IE来说 ExecWB 还有更多的功能实现,比如:

WebBrowser.ExecWB(6,1)  // 打印
WebBrowser.ExecWB(7,1)  // 打印预览
WebBrowser.ExecWB(8,1)  // 打印页面设置
WebBrowser.ExecWB(10,1) // 查看页面属性

今天的介绍就到这里。

参考文档:

《Change an element's CSS class with JavaScript》