为啥伪元素上的过滤器渐变在 IE8 中不起作用?
Posted
技术标签:
【中文标题】为啥伪元素上的过滤器渐变在 IE8 中不起作用?【英文标题】:Why does a filter gradient on a pseudo element not work in IE8?为什么伪元素上的过滤器渐变在 IE8 中不起作用? 【发布时间】:2012-05-11 08:19:39 【问题描述】:我想创建这样的按钮:
在现代浏览器中,效果是使用插入框阴影和滤镜创建的。 对于 IE8 - 选择伪元素。 对于 IE7 - 我使用包含在条件 cmets 中的特殊标签。
演示: (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 中的伪元素不起作用?
更新:
我猜过滤器不适用于 css 生成的内容,尽管 MSDN page 中没有提到它。
我通过将过滤器应用于条件元素来解决我在 IE8 中的问题,就像我在 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: 我为 ie8 上的过滤器(以及 -ms-filter)创建了 testcase:
但过滤器仍然不想处理伪元素。
更新 4: 我认为Scotts answer 最接近真相。
【问题讨论】:
真的值得去经历这些麻烦吗? IE 过滤器和伪元素一样有缺陷。我要么使用图像,要么让 IE 做它的事情。用户甚至不会注意到。 +1 表示你的提问风格很好。 只有我一个人每次都在图像的十字路口看到消失的灰点吗? 据我所知,公共 IE8 错误数据库不再可用,因此您的赏金问题可能无法回答“这是一个错误”,除非 IE 团队中的某个人出现并打算分享。 在 IE8 测试期间,微软表示他们将维护一个公共错误数据库,任何人都可以提交错误供微软查看。它……非常有效,但还是有一些不为人知的错误通过了。 【参考方案1】:问题是“为什么过滤器对 IE8 中的伪元素不起作用?”以下是我所能收集到的最接近明确的答案。它来自this page上的信息。
gradient
过滤器是一个“程序表面”(与alphaimageloader
一起)。程序表面是这样定义的:
程序表面是显示在 对象的内容和对象的背景。
仔细阅读。它本质上是您可以在对象的内容和该对象的背景之间说的另一个“层”。你看到问题的答案了吗? :before
和 :after
创建的内容...是的! 内容。具体为MSDN notes:
::before 和 ::after 伪元素指定 文档树中元素之前和之后的内容。内容 属性与这些伪元素一起指定什么 已插入。
生成的内容与其他盒子交互,就好像它们是真实的一样 元素插入到它们的关联元素中。
现在,如果生成的是content,那么它不是包含内容的“对象”,而是内容本身(恰好有一些类似于可能包含内容的元素对象的行为。
因此,没有“对象”包含“内容”(因为它是内容)filter
可以在它们之间放置由一个伪元素(即“假元素”)。必须将gradient
应用于对象,然后将程序表面放置在它和内容之间。
【讨论】:
我注意到 MSDN 交替使用“属性”和“属性”这两个词来描述content
。好的。
@matmuchrapna--好吧,可能没有办法证明我的解释是不是真正的原因,但当我阅读信息时,这对我来说确实是最合乎逻辑的结论。很高兴您同意并满足您对答案的要求。【参考方案2】:
-ms-filter
上的文档-filter
的同义词-指出:
对象必须具有过滤器才能呈现的布局。
我的第一个猜测是 :before
内容没有将 hasLayout
设置为 true。虽然它可能未设置为 true,但可能也未设置为 false。对于初学者,当我按照hasLayout docs 强制内容获取hasLayout = true
(请参阅jsfiddle)时,它没有解决任何问题。
所以我会说它既不是真的也不是假的。相反,它可能是未定义。我在同一文档中提到了该属性的来源:
对象.currentStyle.hasLayout
如果我们看一下W3 documentation on the content property,它会说:
生成的内容不会改变文档树。特别是,它不会反馈给文档语言处理器(例如,用于重新解析)。
因此,可能的结论是生成的内容不是对象,因此它没有currentStyle
属性,因此也没有' t 将 hasLayout
设置为 true
。这就是过滤器对生成的内容不起作用的原因,因此可以回答问题。
乍一看,我以为我在上面小提琴的控制台中找到了提示:
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 在 cmets 中提到的:querySelectorAll cannot access pseudo-elements。
在this msdn introduction on filters 中可以找到filter
对伪元素不起作用的另一个提示(虽然-再次-只不过是一个提示),说明(强调我的):
过滤器通过过滤器属性应用于HTML控件
虽然我不确定“HTML 控件”是什么意思,但我不希望 :before
伪元素生成的内容被视为“HTML 控件”。
【讨论】:
关于querySelectorAll()
的部分是红鲱鱼,如it can never access pseudo-elements。自然,伪元素不是 DOM 的一部分。
@BoltClock 啊,当然,谢谢!那么可能没有“干净”的方法来确定生成的内容上是否存在内部 hasLayout
属性。我将编辑问题并将您提到的链接也放在那里。
是否可以通过将zoom:1
应用于伪元素来触发hasLayout
?这是一个奇怪的发现,但我无法从我的家用机器访问 IE 框来测试它。
@o.v. AFAIK 没有可靠的方法来找出伪元素的 hasLayout
属性是什么,在我的回答中,我推测它甚至可能没有该属性。无论哪种方式,如果您使用zoom:1
打开this updated version of the jsfiddle,filter
在IE8 中仍然不起作用。
虽然我不同意您的任何其他观点与它有任何关系,但我确实认为当您说“所以,一个可能的结论是生成的内容是不是一个对象。”根据我刚刚发布的答案,我相信这是问题的一半。【参考方案3】:
与其使用 IE 的 filter
样式,您是否考虑过使用 CSS3Pie?
这是一个 IE 脚本,增加了对标准 CSS box-shadow
和渐变的支持,因此您可以在所有浏览器中编写相同的代码,而不必拥有所有那些特定于 IE 的样式。
【讨论】:
它在 inset box-shadow 上失败,并且在没有 javascript 的情况下也无法工作 就个人而言,如果我只关心渐变,我宁愿使用the Ultimate CSS Gradient Generator(支持IE6-9),而不是处理CSS3Pie的额外.js和.htc文件。 @gmeben 我也用这个生成器colorzilla.com/gradient-editor/#ff0000+0,00ff15+100;Custom【参考方案4】:我已经给出了我喜欢的解决方案(使用 CSS3Pie),但我会将此作为单独的答案发布。
IE8 无法与 IE7 工作的 filter
一起工作的可能原因是 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
版本的整个thin 周围添加引号的原因。
所以简短的回答是,在你的样式表中使用这两个版本,你会没事的。
【讨论】:
>"IE8 无法与 IE7 工作的过滤器一起工作的可能原因是 IE8 更改了过滤器的语法。"不,因为在这个 demo 选择器.ie8 .btn:before
上使用正确的 ie8 语法,并且未应用过滤器
我同意@matmuchrapna 的观点,filter
语法不是问题。我相信它是基于伪元素的性质和我在回答中概述的 gradient
过滤器。
我对帖子进行了更新3,证明过滤器在两种语法中都有效
很公平。 IE8 肯定有很多时候更喜欢-ms-filter
syntqx,但如果你在这里都可以,那也很好。不过,我会将答案留在原处,以供将来参考。【参考方案5】:
哇,这太难了。
After reviewing this chart,确认IE8 only likes single colons on its pseudo-elements,阅读此possibly related blog article,并做了很多testing in jsFiddle(尽管与您的73 相比,它很少??jsFiddles),我不得不得出结论,这是IE8 中的一个错误。
IE9 可以在伪元素上做渐变(用 base64 废话),但 IE8 被顽固地破坏了。
【讨论】:
IE8 不支持 CSS3 伪元素语法与过滤器首先不能在伪元素中工作没有太大关系,除了整个“IE 是错误的”心态 :) @BoltClock 很好地抓住了元素/选择器编辑。我只是想指出在 IE8 中使用伪元素时所有必要的部分。从理论上讲,当考虑到所有这些部分时,过滤器应该可以工作。他们不这样做的事实让我相信这是一个错误(不一定是因为我有一种心态啊!)。 @gmeben--因为“伪元素”的意思是“假元素”(字面意思),并且因为它被设计为仅用于 content 插入(它在技术上会仅仅内容包含内容本身是一个逻辑矛盾;就像一个苹果包含一个苹果,而不是是一个),并且由于IE将它们的程序表面定义为在内容和它的对象之间(他们有权定义他们想要的程序表面;它不是 HTML/CSS 规范的一部分),我不确定我是否可以对“设计不佳”进行指控" 在 IE8 上针对这个特定问题(现在,其他问题......)。 @gmeben--是的,“属性”和“属性”的使用不正确。我不确定是否需要放弃“伪元素”。事实上,它不是一个真正的元素。你不能把 html 放进去,就 html 本身而言,它也不存在于 DOM 树中,所以它不是 html 标签意义上的“真实”。生成时,它确实是为了视觉目的,就像一种幻觉——它似乎存在,但实际上并不存在(与“真实”元素具有相同的意义)。 @gmeben——你没抓住重点。不仅仅是 IE 认为它们是“装饰性的”,这就是它们的全部目的。它们纯粹是为了 presentational 使用,这就是为什么它们是 CSS 的一部分,而不是 HTML。初衷只是为了做typographical change。后来,加上:before
和:after
,是为了让generated textual content 也用于演示。此后,网页设计师利用“空白”内容制作了许多简洁的效果。以上是关于为啥伪元素上的过滤器渐变在 IE8 中不起作用?的主要内容,如果未能解决你的问题,请参考以下文章
jQuery.animate 在 IE8/IE9 上的 Facebook iFrame 中不起作用