为什么伪元素上的filter渐变在IE8中不起作用?

我想创build这样的button:
伪3D按钮

在现代浏览器中,使用插入框阴影和filter创build效果。
对于IE8 – select伪元素。
对于IE7 – 我使用包装在条件注释中的特殊标签。

演示: ( http://jsfiddle.net/8M5Tt/68/ )

/** * Button w/o images */ html { font-size: 62.5%; } body { font: normal 1em/1em Arial, Tahoma, Verdana, sans-serif; } /* layout */ .btn { display: inline-block; height: 28px; border-width: 1px; border-style: solid; width: 170px; box-sizing: content-box; overflow: hidden; position: relative; z-index: 1; } .btn { margin: 15px; } .btn.btn_small { width: 130px; } /* ie7 */ .lt-ie8 .btn .before, .lt-ie8 .btn .after { position: absolute; right: -1px; left: -1px; display: block; height: 3px; } .lt-ie8 .btn .before { top: -1px; filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#80ffffff', endColorstr='#00ffffff',GradientType=0 ); } .lt-ie8 .btn .after { bottom: -1px; filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00ffffff', endColorstr='#80000000',GradientType=0 ); } /* /ie7 */ /* ie8 */ .ie8 .btn:before, .ie8 .btn:after { content: ' '; z-index: 1; position: absolute; right: -1px; left: -1px; display: block; height: 3px; } .ie8 .btn:before { top: -1px; filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#80ffffff', endColorstr='#00ffffff',GradientType=0 ); } .ie8 .btn:after { bottom: -1px; filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00ffffff', endColorstr='#80000000',GradientType=0 ); } /* /ie8 */ /* typo */ .btn { /* 28 / 14 = 2.57142857 */ font: bold 14px/2 Arial, Helvetica, Tahoma, sans-serif; text-transform: uppercase; } .btn:active { line-height: 2.4em; } /* color */ .btn { background-color: #00cccc; color: #fff; border-color: #00a8a8; border-radius: 3px; cursor: pointer; box-shadow: 1px 1px 4px rgba(255, 255, 255, 0.5) inset, -1px -1px 4px rgba(000, 000, 000, 0.5) inset; } .btn:hover { background-color: #00ebeb; } .btn:active { box-shadow: -1px -1px 4px rgba(255, 255, 255, 0.5) inset, 1px 1px 4px rgba(000, 000, 000, 0.5) inset; } /* green */ .btn_green { background-color: #009900; border-color: #009600; } .btn_green:hover { background-color: #00c200; } /* red */ .btn_red { background-color: #e00000; border-color: #c13d00; } .btn_red:hover { background-color: #f00000; } 
 <!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ --> <!--[if lt IE 7]> <div class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]--> <!--[if IE 7]> <div class="no-js lt-ie9 lt-ie8 ie7" lang="en"> <![endif]--> <!--[if IE 8]> <div class="no-js lt-ie9 ie8" lang="en"> <![endif]--> <!--[if gt IE 8]><!--> <div class="no-js no-ie" lang="en"> <!--<![endif]--> <button class="btn btn_green btn_small "> Send <!--[if IE 7]> <span class="before"> </span><span class="after"> </span> <![endif]--> </button> <button class="btn"> Buy <!--[if IE 7]> <span class="before"> </span><span class="after"> </span> <![endif]--> </button> <button class="btn btn_green"> Activate <!--[if IE 7]> <span class="before"> </span><span class="after"> </span> <![endif]--> </button> <button class="btn btn_red"> Delete <!--[if IE 7]> <span class="before"> </span><span class="after"> </span> <![endif]--> </button> </div> 

主要问题:为什么不在IE8的伪元素上工作?


更新:

我想filter不能在css生成的内容上工作,尽pipe在这个MSDN页面上没有提到它。

我解决了我的问题在IE8中通过应用条件元素的filter,如我为IE7。

最后的演示: ( http://jsfiddle.net/matmuchrapna/8M5Tt/73/ )

 /** * Button w/o images */ html { font-size: 62.5%; } body { font: normal 1em/1em Arial, Tahoma, Verdana, sans-serif; } /* layout */ .btn { display: inline-block; height: 28px; border-width: 1px; border-style: solid; width: 170px; box-sizing: content-box; overflow: hidden; position: relative; z-index: 1; } .btn { margin: 15px; } .btn.btn_small { width: 130px; } /* ie78 */ .lt-ie9 .btn .before, .lt-ie9 .btn .after { position: absolute; right: -1px; left: -1px; display: block; height: 3px; } .lt-ie9 .btn .before { top: -1px; filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#80ffffff', endColorstr='#00ffffff',GradientType=0 ); } .lt-ie9 .btn .after { bottom: -1px; filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00ffffff', endColorstr='#80000000',GradientType=0 ); } /* /ie78 */ /* typo */ .btn { /* 28 / 14 = 2.57142857 */ font: bold 14px/2 Arial, Helvetica, Tahoma, sans-serif; text-transform: uppercase; } .btn:active { line-height: 2.4em; } /* color */ .btn { background-color: #00cccc; color: #fff; border-color: #00a8a8; border-radius: 3px; cursor: pointer; box-shadow: 1px 1px 4px rgba(255, 255, 255, 0.5) inset, -1px -1px 4px rgba(000, 000, 000, 0.5) inset; } .btn:hover { background-color: #00ebeb; } .btn:active { box-shadow: -1px -1px 4px rgba(255, 255, 255, 0.5) inset, 1px 1px 4px rgba(000, 000, 000, 0.5) inset; } /* green */ .btn_green { background-color: #009900; border-color: #009600; } .btn_green:hover { background-color: #00c200; } /* red */ .btn_red { background-color: #e00000; border-color: #c13d00; } .btn_red:hover { background-color: #f00000; } 
 <!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ --> <!--[if lt IE 7]> <div class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]--> <!--[if IE 7]> <div class="no-js lt-ie9 lt-ie8 ie7" lang="en"> <![endif]--> <!--[if IE 8]> <div class="no-js lt-ie9 ie8" lang="en"> <![endif]--> <!--[if gt IE 8]><!--> <div class="no-js no-ie" lang="en"> <!--<![endif]--> <button class="btn btn_green btn_small "> Send <!--[if lte IE 8]> <span class="before"> </span><span class="after"> </span> <![endif]--> </button> <button class="btn"> Buy <!--[if lte IE 8]> <span class="before"> </span><span class="after"> </span> <![endif]--> </button> <button class="btn btn_green"> Activate <!--[if lte IE 8]> <span class="before"> </span><span class="after"> </span> <![endif]--> </button> <button class="btn btn_red"> Delete <!--[if lte IE 8]> <span class="before"> </span><span class="after"> </span> <![endif]--> </button> </div> 

更新2:

我解决了我的问题,但主要问题仍然没有答案:

“为什么不在IE8中的伪元素上工作?”

开始赏金。

更新3:我创build了testing用例仅用于ie8上的filter(也是-ms-filter):

在这里输入图像说明

但是filter仍然不想在伪元素上工作。

更新4:我认为斯科特答案是最接近真相的。

问题是“为什么不在IE8中的伪元素上工作?” 以下是我所能够接受的明确答案。 它来自这个页面上的信息。

gradientfilter是一个“程序表面”(与alphaimageloader )。 一个程序表面的定义如下:

程序表面是在对象的内容和对象的背景之间显示的彩色表面。

仔细阅读。 它本质上是另一个“层”,你可以说在一个对象的内容和该对象的背景之间。 你看到这个问题的答案吗? 什么是创造:before:after :是的! 内容 。 具体如MSDN所示 :

:: before和:: after伪元素指定文档树中元素前后内容的位置。 内容属性与这些伪元素一起指定插入的内容。

生成的内容与其他框交互,就好像它们是插入其关联元素内的真实元素一样。

现在,如果它是生成的内容 ,那么它不是包含内容的“对象”,而是内容本身 (恰好具有与可能包含内容的元素对象类似的一些行为)。

因此,不存在包含 “内容”(因为它内容)的“对象”, filter可以在该“对象”之间为由伪元素(即,“假元素”)生成的内容放置过程表面。 必须对对象应用gradient ,然后将程序表面放置在其与内容之间。

关于-ms-filter同义词的文档声明:

一个对象必须有用于呈现的filter的布局。

我的第一个猜测是:before内容:before没有hasLayout设置为true。 虽然它可能不会被设置为true,但也可能不会被设置为false 。 对于初学者来说,当我跟着hasLayout文档强制内容获取hasLayout = true (请参阅jsfiddle ),它并没有解决任何问题。

所以我会说这不是真的,也不是假的。 相反,它可能是未定义的 。 我在同一份文件中提到它说这个财产的来源:

对象 .currentStyle.hasLayout

如果我们看一下内容属性的W3文档,它会说:

生成的内容不会改变文档树。 特别是,它不被反馈给文档语言处理器(例如,用于重新分析)。

因此, 可能的结论是生成的内容不是一个对象 ,因为它没有currentStyle属性,因此也没有将hasLayout设置为true 。 这将是filter不能在生成的内容上工作的原因,从而回答这个问题。


乍一看,我以为我在上面的提琴的控制台中发现了一个提示:

 document.querySelectorAll('div')[0].currentStyle.hasLayout; // true document.querySelectorAll('div:before')[0].currentStyle.hasLayout // Unable to get value of the property 'currentStyle': // object is null or undefined 

但正如在@BoltClock的注释中提到的那样: querySelectorAll不能访问伪元素 。


另一个提示(虽然-again-无非是一个提示) filter将无法工作的伪元素可以在这个MSDN介绍filter ,说明(强调我的):

filter通过filter属性应用于HTML控件

虽然我不确定“HTML控件”是什么意思,但我不希望将:before伪元素生成的内容视为“HTML控件”。

而不是使用IE的filter风格,你有没有考虑使用CSS3Pie ?

这是一个IE脚本,它增加了对标准CSS box-shadow和渐变的支持,所以你可以在所有浏览器中编写相同的代码,而不必拥有所有那些IE特有的样式。

我已经给了我的首选解决scheme(使用CSS3Pie),但我会作为一个单独的答案发布。

IE8无法在IE7下工作的原因是因为IE8改变了filter的语法。

filter是IE特有的专有风格。 当微软发布IE8时,他们试图成为“符合标准”的一大亮点。 支持非标准风格的“符合标准”的方式是给它一个供应商的前缀,这就是微软所做的。

因此,在IE8中,您需要执行以下操作:

 -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#80ffffff', endColorstr='#00ffffff',GradientType=0 )"; 

IE7不支持这种语法,所以你需要它们两个。

在某些情况下, IE8确实可以使用旧的语法。 它不起作用的情况往往是你使用progid:语法的情况。 原因是progid之后的冒号导致它成为无效的CSS语法,这就是为什么MS为IE8 -ms-filter版本添加引号的原因。

所以简短的回答是,在你的样式表中使用这两个版本,你会没事的。

哇,这是一个艰难的。

在查看这个图表之后 ,确认IE8只在其伪元素上使用单个冒号 ,阅读这个可能相关的博客文章 ,然后在jsFiddle中进行大量的testing (虽然与你的73jsFiddles相比很less)必须得出这样的结论:这是IE8中的一个bug。

IE9可以在伪元素上做渐变(带有base64废话),但是IE8被固执地破坏了。