为什么伪元素上的filter渐变在IE8中不起作用?
我想创build这样的button:
在现代浏览器中,使用插入框阴影和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中的伪元素上工作?” 以下是我所能够接受的明确答案。 它来自这个页面上的信息。
gradient
filter是一个“程序表面”(与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被固执地破坏了。