Pregunta sobre html, css, pseudo-element, internet-explorer-8 – ¿Por qué un gradiente de filtro en un pseudo elemento no funciona en IE8?

35

Quiero crear botones como estos:

En los navegadores modernos, el efecto se crea utilizando recuadros de sombra y filtros.
Para IE8 - se eligen pseudo-elementos.
Para IE7: uso etiquetas especiales envueltas en comentarios condicionales.

Manifestación: (http://jsfiddle.net/8M5Tt/68/)

<code>/**
 * 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;
    }</code>
<code><!--
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></code>

Pregunta principal: ¿Por qué los filtros no funcionan en pseudo elementos en IE8?

Actualizar:

Supongo que los filtros no funcionan en el contenido generado por css, a pesar del hecho de que no se menciona en estePágina de MSDN.

Resolví mi problema en IE8 aplicando filtros a elementos condicionales como lo hago para IE7.

Demostración final: (http://jsfiddle.net/matmuchrapna/8M5Tt/73/)

<code>/**
 * 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;
    }</code>
<code><!--
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></code>

Actualización 2:

Resolví mi problema, pero la pregunta principal sigue sin respuesta:

"¿Por qué los filtros no funcionan en pseudo elementos en IE8?"

Comenzó una recompensa.

Actualización 3: yo creécaso de prueba solo para filtros (y también -ms-filter) en ie8:

Pero los filtros aún no quieren trabajar en pseudo-elementos.

Actualización 4: Yo creo queRespuesta de Scotts es lo mas cercano a la verdad.

@BalusC te refieres a la:focus ¿estado? gmeben
Estoy totalmente de acuerdo contigo, pero el problema en otra cosa. Vladimir Starkov
@BoltClock sobre qué base de datos pública de errores ie8 hablas? Vladimir Starkov
+1 por tu buen estilo de preguntas. yunzen

Tu respuesta

5   la respuesta
0

Wow, esta es una pregunta difícil.

Después de revisar esta tabla, confirmando queA IE8 solo le gustan los dos puntos individuales en sus pseudo-elementos., leyendo estoartículo posiblemente relacionado con el blog, y haciendo un montón depruebas en jsFiddle (aunque es poco en comparación con sus 73 jsFiddles), tendría que concluir que este es un error en IE8.

IE9 puede hacer gradientes en pseudo-elementos (con base64 sin sentido) pero IE8 está obstinadamente roto.

@BoltClock Buena captura en la edición del elemento / selector. Solo quería señalar todas las partes necesarias cuando se trabaja con pseudo-elementos en IE8. Teóricamente, cuando se consideran todas estas partes, los filtros deberían funcionar. El hecho de que no lo hagan es lo que me lleva a creer que esto es un error (no necesariamente porque tengo una mentalidad, ¡ahh!). gmeben
@ScottS Si el equipo de IE consideraba los pseudo-elementos puramente decorativos, entonces deberían haberles dado superficies de procedimiento en las que generar elementos visuales como gradientes. Se siente como si simplemente no hubieran hecho el trabajo para hacer que admitieran tal característica en lugar de instituir una elección de diseño. gmeben
@gmeben - Estoy de acuerdo en que fue una pregunta difícil. Tiendo a estar en desacuerdo con que IE8 está roto en este punto (vea mi respuesta para saber por qué). ScottS
@ScottS Buen trabajo. Su respuesta fue bien explicada. Seguramente, sin embargo, y no para vencer a un caballo muerto, sino porque IE8 no considera los pseudo-elementos como objetos dentro de su DOM refuerza aún más la idea de que IE8 estaba mal diseñado. gmeben
0

Ya di mi solución preferida (usar CSS3Pie), pero la publicaré como una respuesta por separado.

La razón probable por la que IE8 no funciona confilter donde trabaja IE7 es porque IE8 cambió la sintaxis defilter.

filter Es un estilo propietario específico de IE. Cuando Microsoft lanzó IE8, intentaron ser "compatibles con los estándares". La forma "compatible con los estándares" de admitir un estilo no estándar es asignarle un prefijo de proveedor, y eso es lo que hizo Microsoft.

Por lo tanto, en IE8, debes hacer lo siguiente:

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

IE7 no admite esta sintaxis, por lo que necesita ambos.

IE8 de hecho funciona con la sintaxis antiguaen algunos casos. Los casos en los que no funciona tienden a ser aquellos en los que se utiliza elprogid: sintaxis. La razón de esto es que los dos puntos después deprogid hace que la sintaxis de CSS sea inválida, razón por la cual MS agregó comillas alrededor de todo para IE8-ms-filter versión.

Así que la respuesta corta es, usa ambas versiones en tus hojas de estilo, y estarás bien.

lo suficientemente justo. Definitivamente hay momentos en que IE8 prefiere el-ms-filter syntqx, pero si está bien para usted aquí de cualquier manera, eso también es bueno. Sin embargo, dejaré la respuesta en su lugar para futuras referencias. Spudley
Hice update3 a la publicación, que las pruebas de que los filtros funcionan en ambas sintaxis Vladimir Starkov
> "La razón probable por la que IE8 no funciona con el filtro donde trabaja IE7 es porque IE8 cambió la sintaxis del filtro". no, porque en estemanifestación selector.ie8 .btn:before use la sintaxis correcta para ie8, y el filtro no se aplica Vladimir Starkov
Estoy de acuerdo con @matmuchrapna en quefilter La sintaxis no es el problema. Creo que se basa en la naturaleza de un pseudo-elemento y lagradient Filtrar como señalé en mi respuesta. ScottS
41

La pregunta es "¿Por qué los filtros no funcionan en pseudo elementos en IE8?" Lo siguiente es lo más cercano a una respuesta definitiva que pueda reunir. Proviene de la información sobreesta página.

losgradient El filtro es una "superficie de procedimiento" (junto conalphaimageloader). Una superficie procesal se define así:

Las superficies de procedimiento son superficies de color que se muestran entre el contenido de un objeto y el fondo del objeto.

Lea eso con cuidado. Esencialmente, es otra "capa" que podría decirse entre el contenido de un objeto y el fondo de ese objeto. ¿Ves la respuesta a la pregunta? Lo que es creado por:before y:after... siContenido. Específicamente comoNotas de MSDN:

Los pseudo-elementos :: before y :: after especifican la ubicación del contenido antes y después de un elemento en el árbol de documentos. El atributo de contenido, junto con estos pseudo-elementos, especifica qué se inserta.

El contenido generado interactúa con otras cajas como si fueran elementos reales insertados justo dentro de su elemento asociado.

Ahora si escontenido que se genera, entonces esno un "objeto" que contiene contenido, pero elcontenido en sí mismo (que sucede que tiene algún comportamiento similar a un objeto de elemento que podría contener contenido).

Por lo tanto, no hay "objeto"que contiene "contenido" (ya quees contenido) entre los cuales elfilter puede colocar una superficie de procedimiento para el contenido generado por un pseudo-elemento (es decir, "elemento falso"). UNAgradient debe ser aplicado a laobjeto, y luego se coloca la superficie procesal entre ella y el contenido.

Noté que MSDN usa indistintamente las palabras "propiedad" y "atributo" para describircontent. Bueno. gmeben
Creo que tienes razón. Vladimir Starkov
@ matmuchrapna: Bueno, probablemente no haya manera de probar o no que mi explicación es realmente la razón, pero cuando leí la información, me pareció la conclusión más lógica. Me alegro de que estés de acuerdo y satisfechas tu búsqueda de una respuesta. ScottS
6

La documentación sobre-ms-filter -un sinónimo parafilter- los estados

Un objeto debe tener diseño para que el filtro se represente.

Mi primera suposición fue que la:before el contenido no tienehasLayout establecer en verdadero Y mientras que probablemente no esté configurado como verdadero, probablementeno está configurado como falso tampoco. Para empezar, cuando seguí elhasLayout docs forzar el contenido para obtenerhasLayout = true (verjsfiddle) no resolvió nada.

Así que diría que no es ni verdadero ni falso. En cambio, es probableindefinido. Noté en los mismos documentos que dice sobre la fuente de esta propiedad:

objeto.currentStyle.hasLayout

Si echamos un vistazo a laDocumentación W3 sobre la propiedad de contenido. dice:

El contenido generado no altera el árbol de documentos. En particular, no se envía al procesador del lenguaje del documento (por ejemplo, para volver a analizar).

Asi que,una posible conclusión Sería que el contenido generado no sea unobjeto, como tal no tiene uncurrentStyle propiedad, y por lo tanto también no tienehasLayout ajustado atrue. Esta sería la razón por la que los filtros no funcionan en el contenido generado y, por lo tanto, responden a la pregunta.

A primera vista, pensé que había encontrado una pista en la consola del violín anterior:

<code>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
</code>

Pero como se menciona en los comentarios de @BoltClock:querySelectorAll no puede acceder a pseudo-elementos.

Otra pista (aunque, de nuevo, nada más que una pista) quefilter no funcionará en pseudo-elementos que se pueden encontrar enesta msdn introduccion en filtros, indicando (énfasis mío):

Los filtros se aplican aControles de HTML a través de la propiedad de filtro

Aunque no estoy seguro de lo que se entiende por "controles HTML", no esperaría que el contenido generado por el:before pseudo-elemento para ser considerado un "Control HTML".

@Jeroen tu respuesta es impresionante. Quizás estás en lo cierto. Por cierto,buscando controles html en msdn resultó no más materiales relacionados sobrecontroles html, por eso no puedo hablar de excepción fuera de descripciónHtml controls. Por eso prefiero confiar en el párrafo sobre esto.página, describiendo elementos que no pueden tener filtros:embed, applet, select, option, tr, tHead, tBody ytFoot. Vladimir Starkov
@ o.v. AFAIK no hay una manera confiable de averiguar lo que elhasLayout propiedad para pseudoelementos es, en mi respuesta especulo que puede que ni siquiera tenga la propiedad. De cualquier manera, si abresesta versión actualizada del jsfiddle conzoom:1 lafilter Todavía no funciona en IE8. Jeroen
El poco acerca dequerySelectorAll() es una pista falsa, comonunca puede acceder a los pseudo-elementos. Naturalmente, como los pseudo-elementos no son parte del DOM. BoltClock
Si bien no estoy de acuerdo en que alguno de sus otros puntos tenga algo que ver con esto, sí creo que estaba a mitad de camino de la respuesta cuando dijo "Entonces, una posible conclusión sería que el contenido generado no es un problema.objeto"Creo que para ser la mitad del problema basado en la respuesta que acabo de publicar. ScottS
0

En lugar de utilizar IEfilter estilo para esto, has considerado usarCSS3Pie?

Este es un script para IE que agrega soporte para CSS estándarbox-shadow y gradientes, para que pueda escribir el mismo código en todos los navegadores en lugar de tener que tener todos esos estilos específicos de IE.

falla en el recuadro de la sombra, y tampoco funciona sin javascript Vladimir Starkov
Personalmente, si solo me preocupan los gradientes, prefiero usarel último generador de gradiente CSS (admite IE6-9) y no se ocupa de los archivos .js y .htc adicionales de CSS3Pie. gmeben
@gmeben yo también uso este generadorcolorzilla.com/gradient-editor/#ff0000+0,00ff15+100;Custom Vladimir Starkov

Preguntas relacionadas