html - ¿Por qué un gradiente de filtro en un pseudo elemento no funciona en IE8?
css internet-explorer-8 (5)
Quiero crear botones como estos:
En los navegadores modernos, el efecto se crea usando recuadro de sombreado y filtros.
Para IE8, se eligen los pseudo-elementos.
Para IE7: utilizo etiquetas especiales envueltas en comentarios condicionales.
Demostración: ( 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>
Pregunta principal: ¿Por qué los filtros no funcionan en los pseudo elementos en IE8?
Actualizar:
Supongo que los filtros no funcionan en contenido generado por css, a pesar de que no se menciona en esta pá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/ )
/**
* 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>
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: testcase solo para filtros (y también -ms-filter) en ie8:
Pero los filtros todavía no quieren trabajar en pseudo-elementos.
Actualización 4: Creo que la respuesta de Scotts es lo más cercano a la verdad.
En lugar de utilizar el estilo de filter
de IE para esto, ¿ha considerado usar CSS3Pie ?
Este es un script para IE que agrega soporte para box-shadow
y box-shadow
CSS estándar, 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.
La documentación en -ms-filter
-un sinónimo para filter
-states:
Un objeto debe tener un diseño para que se represente el filtro.
Mi primera suposición fue que el :before
contenido no tiene hasLayout
establecido en verdadero. Y aunque probablemente no esté configurado como verdadero, probablemente tampoco esté configurado en falso . Para empezar, cuando seguí los documentos hasLayout para forzar que el contenido obtuviera hasLayout = true
(ver jsfiddle ), no resolvió nada.
Entonces yo diría que no es ni verdadero ni falso. En cambio, es probable que no esté definido . Anoté en los mismos documentos que dice acerca de la fuente de esta propiedad:
objeto .currentStyle.hasLayout
Si echamos un vistazo a la documentación de W3 sobre la propiedad del contenido , dice:
El contenido generado no altera el árbol del documento. En particular, no se retroalimenta al procesador de lenguaje de documentos (por ejemplo, para reparsing).
Entonces, una posible conclusión sería que el contenido generado no es un objeto , como tal, no tiene una propiedad currentStyle
y, por lo tanto, tampoco tiene hasLayout
establecido en true
. Esta sería la razón por la que los filtros no funcionan en el contenido generado y, por lo tanto, responden la pregunta.
A primera vista, pensé que había encontrado una pista en la consola del violín anterior:
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
Pero como se menciona en los comentarios de @BoltClock: querySelectorAll no puede acceder a los pseudo-elementos .
Otra sugerencia (aunque -nuevo- nada más que una pista) de que el filter
no funcionará en los pseudo-elementos se puede encontrar en esta introducción msdn sobre filtros , indicando (énfasis mío):
Los filtros se aplican a los controles HTML a través de la propiedad de filtro
Aunque no estoy seguro de qué se entiende por "controles HTML", no esperaría que el contenido generado por :before
pseudo-elemento se considere un "Control HTML".
La pregunta es "¿Por qué los filtros no funcionan en los pseudo elementos en IE8?" Lo siguiente es lo más cercano a una respuesta definitiva que puedo reunir. Viene de la información en esta página .
El filtro de gradient
es una "superficie de procedimiento" (junto con alphaimageloader
). Una superficie de procedimiento se define así:
Las superficies de procedimiento son superficies coloreadas que se muestran entre el contenido de un objeto y el fondo del objeto.
Lea eso con cuidado. Es esencialmente otra "capa" que podría decir entre el contenido de un objeto y el fondo de ese objeto. ¿Ves la respuesta a la pregunta? ¿Qué es creado por :before
y :after
... Sí! Contenido Específicamente como notas de MSDN :
Los pseudoelementos :: before y :: after especifican la ubicación del contenido antes y después de un elemento en el árbol del documento. El atributo de contenido, junto con estos pseudo-elementos, especifica qué se inserta.
El contenido generado interactúa con otros cuadros como si fueran elementos reales insertados dentro de su elemento asociado.
Ahora, si se genera contenido , entonces no es un "objeto" que contiene contenido, sino el contenido en sí (que tiene un comportamiento similar al de un elemento que puede contener contenido).
Por lo tanto, no hay ningún "objeto" que contenga "contenido" (ya que es contenido) entre los cuales el filter
puede colocar una superficie de procedimiento para el contenido generado por un pseudo-elemento (es decir, "elemento falso"). Se debe aplicar un gradient
al objeto y luego se coloca la superficie de procedimiento entre este y el contenido.
Wow, este es uno difícil.
Después de revisar esta tabla , confirmando que a IE8 solo le gustan los dos puntos en sus pseudoelementos , leyendo este artículo de blog posiblemente relacionado y realizando muchas pruebas en jsFiddle (aunque es poco en comparación con los 73? JsFiddles), lo haría tiene que concluir que esto es un error en IE8.
IE9 puede hacer degradados en pseudo-elementos (con tonterías de base64) pero IE8 está tercamente roto.
Ya di mi solución preferida (use CSS3Pie), pero la publicaré como una respuesta separada.
La razón probable por la que IE8 no funciona con el filter
donde funciona IE7 es porque IE8 cambió la sintaxis para el filter
.
filter
es un estilo de propiedad específico de IE. Cuando Microsoft lanzó IE8, hicieron un gran esfuerzo por tratar de ser "compatible con los estándares". La manera "compatible con los estándares" de respaldar un estilo no estándar es otorgarle un prefijo de proveedor, y eso es lo que hizo Microsoft.
Por lo tanto, en IE8, debe hacer lo siguiente:
-ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr=''#80ffffff'', endColorstr=''#00ffffff'',GradientType=0 )";
IE7 no es compatible con esta sintaxis, por lo que los necesita a ambos.
IE8 de hecho funciona con la sintaxis antigua en algunos casos . Los casos en los que no funciona tienden a ser aquellos en los que utiliza el progid:
sintaxis. La razón de esto es que el colon después de progid
causa que sea una sintaxis de CSS no válida, por lo que MS agregó comillas en todo el thin para la -ms-filter
IE8 -ms-filter
.
Entonces, la respuesta corta es usar ambas versiones en sus hojas de estilo, y todo irá bien.