Pergunta sobre pseudo-element, css, html, internet-explorer-8 – Por que um gradiente de filtro em um pseudoelemento não funciona no IE8?

35

Eu quero criar botões como estes:

Nos navegadores modernos, o efeito é criado usando sombra e filtros inseridos na caixa.
Para o IE8 - pseudo-elementos são escolhidos.
Para o IE7 - eu uso tags especiais envolvidas em comentários condicionais.

Demonstração: (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>

Questão Principal: Por que os filtros não funcionam em pseudo-elementos no IE8?

Atualizar:

Eu acho que os filtros não funcionam em conteúdo gerado por CSS, apesar do fato de que não é mencionado nestePágina do MSDN.

Eu resolvi meu problema no IE8 aplicando filtros a elementos condicionais como o IE7.

Demonstração 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>

Atualização 2:

Eu resolvi meu problema, mas a questão principal ainda não foi respondida:

“Por que os filtros não funcionam em pseudo-elementos no IE8?”

Começou uma recompensa.

Atualização 3: eu crieicaso de teste somente para filtros (e também -ms-filter) no ie8:

Mas os filtros ainda não querem trabalhar em pseudo-elementos.

Atualização 4: eu acho queScotts answer está mais próximo da verdade.

@BoltClock sobre qual banco de dados de bugs ie8 público você fala? Vladimir Starkov
@BalusC Você quer dizer o:focus Estado? gmeben
Eu concordo totalmente com você, mas o problema em outra coisa Vladimir Starkov
Valerá a pena todo esse problema? Filtros do IE são bastante bugs, bem como pseudo-elementos. Eu usaria uma imagem ou apenas deixaria o IE fazer sua parte. Os usuários nem notarão. elclanrs

Sua resposta

5   a resposta
6

-ms-filter -um sinônimo parafilter- estados:

Um objeto deve ter layout para o filtro renderizar.

Meu primeiro palpite foi que o:before conteúdo não temhasLayout definido como verdadeiro. E embora provavelmente não seja verdade, provavelmentenão definido como falso. Para começar, quando eu segui ohasLayout docs para forçar o conteúdo para obterhasLayout = true (Vejojsfiddle) não resolveu nada.

Então eu diria que não é nem verdadeiro nem falso. Em vez disso, é provavelmenteIndefinido. Observei nos mesmos documentos que diz sobre a origem dessa propriedade:

objeto.currentStyle.hasLayout

Se dermos uma olhada noDocumentação W3 na propriedade de conteúdo diz:

O conteúdo gerado não altera a árvore do documento. Em particular, não é devolvido ao processador de linguagem do documento (por exemplo, para reparos).

Assim,uma possível conclusão seria que o conteúdo gerado não é umobjeto, como tal, não temcurrentStyle propriedade e, portanto, também não temhasLayout definido comotrue. Essa seria a razão pela qual os filtros não funcionam no conteúdo gerado e, portanto, respondem à pergunta.

À primeira vista, pensei ter encontrado uma sugestão no console do violino acima:

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

Mas como mencionado nos comentários por @BoltClock:querySelectorAll não pode acessar pseudo-elementos.

Outra sugestão (embora - novamente - nada mais que uma dica)filter não vai funcionar em pseudo-elementos podem ser encontrados emesta introdução do msdn em filtros, afirmando (ênfase minha):

Filtros são aplicados aControles HTML através da propriedade de filtro

Embora não tenha certeza do que significa "controles HTML", não esperaria que o conteúdo gerado pelo:before pseudo-elemento a ser considerado um "HTML Control".

@Jeroen sua resposta é incrível. Talvez você esteja certo. A propósito,pesquisando controles html no msdn resultou não mais materiais relacionados sobrecontroles de htmlé por isso que eu não posso falar sobre exceção fora da descriçãoHtml controls. É por isso que eu prefiro confiar parágrafo nestepágina, descrevendo elementos que não podem ter filtros:embed, applet, select, option, tr, tHead, tBody etFoot. Vladimir Starkov
Alguém seria capaz de desencadearhasLayout aplicandozoom:1 para pseudo-elementos? Este é um achado curioso, mas eu não tenho acesso a uma caixa do IE da minha máquina doméstica para testá-lo. o.v.
@BoltClock Ahh sim, claro, thx! Então provavelmente não há uma maneira "limpa" de descobrir se há umahasLayout propriedade no conteúdo gerado. Vou editar a questão e colocar o link que você mencionou lá também. Jeroen
Embora eu discorde de que qualquer um dos seus outros pontos tenha alguma coisa a ver com isso, eu acho que você estava a meio caminho da resposta quando disse "Então, uma possível conclusão seria que o conteúdo gerado não é umobjeto"Acredito que seja metade do problema com base na resposta que acabei de postar. ScottS
0

Depois de rever este gráfico, confirmando queO IE8 só gosta de um único ponto em seus pseudo-elementos, lendo issopossivelmente relacionado artigo do blog, e fazendo um monte detestando em jsFiddle (embora seja pouco em comparação com seus 73 jsFiddles), eu teria que concluir que isso é um bug no IE8.

O IE9 pode fazer gradientes em pseudo-elementos (com base64 sem sentido), mas o IE8 é teimosamente quebrado.

@ScottS - Eu vejo. Talvez devêssemos abandonar o rótulo "pseudo-elemento" então. De qualquer forma, em sua documentação, seu uso intercambiável das palavras "propriedade" e "atributo" (que são dois conceitos totalmente diferentes, é claro) ainda indica um nível mais profundo de falha. gmeben
Mas a cor de fundo énão a filtere não uma superfície processual. Lembre-se, os gradientes de segundo plano não apareceram no Firefox até as 6h (em janeiro de 2010), enquanto gradientes viafilter no IE, volte para a versão 5.5 (em 2005!), e o IE8 foi lançado em março de 2009. No máximo, o IE estava à frente de seu tempo para permitir gradientes. Agora eles estão se afastandofilter para alinhar com outros navegadores (uma coisa boa). No entanto, você tem direito a sua opinião sobre isso. O IE8 agora é um navegador antigo, por isso não será um fator importante em alguns anos. ScottS
@BoltClock Boa captura na edição do elemento / seletor. Eu só queria apontar todas as partes necessárias ao trabalhar com pseudo-elementos no IE8. Teoricamente, quando todas essas partes são consideradas, os filtros devem funcionar. O fato de que eles não é o que me leva a acreditar que isso é um bug (não necessariamente porque eu tenho uma mentalidade ahh!). gmeben
Enquanto as superfícies procedurais são de apresentação / visual, elas também são explicitamente definidas como entre conteúdo e objeto contido. Como os pseudo-elementos são conteúdo, não contendo objeto, faz sentido para mim porque a superfície não pode ser aplicada a eles. ScottS
0

mas vou postar isso como uma resposta separada.

A provável razão pela qual o IE8 não funciona comfilter onde IE7 funciona é porque o IE8 mudou a sintaxe parafilter.

filter é um estilo proprietário específico do IE. Quando a Microsoft lançou o IE8, eles fizeram questão de tentar ser "compatível com os padrões". A maneira "compatível com os padrões" de suportar um estilo não padrão é dar a ele um prefixo de fornecedor, e foi isso que a Microsoft fez.

Portanto, no IE8, você precisa fazer o seguinte:

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

O IE7 não suporta esta sintaxe, então você precisa dos dois.

O IE8 de fato trabalha com a antiga sintaxeem alguns casos. Os casos em que não funciona tendem a ser aqueles em que você usa oprogid: sintaxe. A razão para isso é que o cólon apósprogid faz com que seja uma sintaxe CSS inválida, e é por isso que o MS adicionou aspas ao redor do todo para o IE8-ms-filter versão.

Portanto, a resposta curta é usar ambas as versões em suas folhas de estilo e você ficará bem.

justo. há definitivamente momentos em que o IE8 prefere o-ms-filter syntqx, mas se está tudo bem para você aqui de qualquer maneira, então isso também é bom. Vou deixar a resposta no lugar, para futura referência. Spudley
Eu concordo com o @matmuchrapna quefilter sintaxe não é o problema. Eu acredito que é baseado na natureza de um pseudo-elemento egradient filtrar como eu descrevi na minha resposta. ScottS
"O motivo provável pelo qual o IE8 falha ao trabalhar com o filtro, no qual o IE7 funciona, é porque o IE8 mudou a sintaxe do filtro." não, porque nestedemonstração seletor.ie8 .btn:before use a sintaxe correta para ie8 e o filtro não é aplicado Vladimir Starkov
Eu fiz update3 para o post, que prova que os filtros estão trabalhando em ambas as sintaxes Vladimir Starkov
0

filter estilo para isso, você já pensou em usarCSS3Pie?

Este é um script para o IE que adiciona suporte para CSS padrãobox-shadow e gradientes, para que você possa escrever o mesmo código em todos os navegadores, em vez de ter que ter todos esses estilos específicos do IE.

Pessoalmente, se estou preocupado apenas com gradientes, prefiro usaro Gerador de Gradiente de CSS Ultimate (suporta IE6-9) e não lida com os arquivos extra .js e .htc do CSS3Pie. gmeben
ele falha na caixa inset-shadow, e também não funciona sem o javascript Vladimir Starkov
@gmeben eu também uso este geradorcolorzilla.com/gradient-editor/#ff0000+0,00ff15+100;Custom Vladimir Starkov
41

Por que os filtros não funcionam em pseudo-elementos no IE8?" O que se segue é o mais próximo de uma resposta definitiva que eu possa reunir. Vem da informação sobreesta página.

ogradient filtro é uma "superfície processual" (junto comalphaimageloader). Uma superfície procedural é definida assim:

Superfícies processuais são superfícies coloridas que exibem entre o conteúdo de um objeto e o plano de fundo do objeto.

Leia isso com cuidado. É essencialmente outra "camada" que você pode dizer entre o conteúdo de um objeto e o plano de fundo desse objeto. Você vê a resposta para a pergunta? O que é criado por:before e:after... Sim!Conteúdo. Especificamente comoNotas do MSDN:

Os pseudo-elementos :: before e :: after especificam a localização do conteúdo antes e depois de um elemento na árvore do documento. O atributo de conteúdo, em conjunto com esses pseudo-elementos, especifica o que está inserido.

O conteúdo gerado interage com outras caixas como se fossem elementos reais inseridos apenas dentro de seu elemento associado.

Agora, se éconteúdo que é gerado, então énão um "objeto" contendo conteúdo, mas oconteúdo em si (que por acaso tem algum comportamento semelhante a um objeto de elemento que pode conter conteúdo).

Assim, não há "objeto"contendo "conteúdo" (já queé conteúdo) entre os quais ofilter pode colocar uma superfície procedural para conteúdo gerado por um pseudoelemento (isto é, "elemento falso"). UMAgradient deve ser aplicado aoobjetoe, em seguida, a superfície processual é colocada entre ela e o conteúdo.

Percebi que o MSDN usa as palavras 'propriedade' e 'atributo' para descrevercontent. OK. gmeben
Eu acho que você está certo. Vladimir Starkov
@ matmuchrapna - Bem, provavelmente não há maneira de provar ou não que a minha explicação é verdadeiramente a razão, mas como eu li a informação, com certeza parecia ser a conclusão mais lógica para mim. Fico feliz que você concorda e satisfez sua busca por uma resposta. ScottS

Perguntas relacionadas