O IE7 e os Hacks CSS

Publicado em: 31/10/2005
Atualizado em: 05/02/2006

Autores: Holly 'n John
URL do original: http://www.positionis...-dehacker.html
Título original: CSS Hacks and IE7
Traduzido com autorização expressa do autor

Introdução

Recentemente o blog da Microsoft anunciou algumas modificações a serem introduzidas no navegador IE7 a ser lançado, provavelmente no ínicio de 2006. É muito bom que esta notícia tenha sido adiantada para nós, pois a MS está trabalhando duro para dar suporte a uma série de seletores que estão sendo usados como forma de hackear regras de estilo para o Explorer.

Mais especificamente, um grande número de diferentes hacks baseados em seletores avançados e que atualmente não são suportados pelo IEWin irão falhar no IE7, pois este navegador vai introduzir suporte para tais seletores. A longo prazo, esta é uma boa nova para nós, desenvolvedores CSS, pois a partir de agora teremos muito mais controle e poder sobre o que faz e onde atua nossa CSS. Infelizmente, a curto prazo isto implicará na neccessidade de reescrever nossas folhas de estilo e encontrar caminhos alternativos para hackear o IEWin.

Devemos nos preocupar desde já ?

Alguns são da opinião de que quem usou hack estará colhendo os frutos de uma má prática e parece haver alguma verdade neste pensamento. O mundo seria bem melhor se não existissem hacks, contudo temos que considerar o fato de que o navegador majoritário é incapaz de lidar com projetos CSS complexos sem ter que ser induzido a layout. Sem o Holly hack, nós ficariamos restritos e limitados na escolha de nossos layouts e não nos restaria outra alternativa a não ser usar tabelas.

Contudo, excetuando-se o Holly hack, é possível projetar sem hacks usando-se alguns artifícios. Ocasionalmente o IEMac precisa de um socorro, mas existe um hack-comentário, seguro e limpo para as CSS, que se emprega para aquele navegador. Os demais navegadores modernos oferecem muito melhor suporte para as standards e quando ocorrem problemas que não podem ser contornados nós simplesmente os ignoramos e supomos que o problema será resolvido eventualmente. Somente quando tal problema leva à ruína do layout da página é que nos aprofundamos mais, indo até ao redesign da página se necessário.

Como costumamos dizer, esta é a nossa filosofia de projeto, e você é inteiramente livre para escolher a sua. Em todo caso, vamos direto ao assunto e mais especificamente às mudanças esperadas no IE7, e os novos caminhos para tratar velhos problemas.

O que é In o que é Out

Vamos ao que nós chamamos de as grandes mudanças no IE7. Será oferecido suporte para dois "elementos de combinação" de seletores CSS e um elemento estrutural será eliminado. Primeiramente os elementos de combinação de seletores:

  • O seletor filho - (The Child Selector)

    Este seletor usa o símbolo (maior que) ">" como "elemento de combinação" colocado entre dois seletores CSS e indica que o alvo da regra CSS é o elemento à direita do "elemento de combinação, >" mas somente quando este elemento for filho direto do elemento à esquerda do "elemento de combinação". Assim o seletor table>td não casa nunca com qualquer elemento porque TD's nunca são filhos direto de tables, mas sim de TR's. Por outro lado o seletor tr>td casará com todas as TDs na página, pois todas TD's são filhas diretas de TR's.

    A diferença entre um elemento de combição 'filho' ">"e o conhecido elemento de combinação 'espaço em branco' entre dois seletores está no fato de que este último refere-se a elementos "descendentes" ou seja, o elemento à direita do espaço em branco será casado sempre que estiver entre as tags do elemento à esquerda no seletor. Assim, o seletor table td, casa com todas as TD's uma vez que TD's sempre estarão dentro do par de tags table de uma tabela.

    O elemento de combição 'filho' ">" é útil quando pretendemos casar os filhos diretos de um elemento, sem contudo casar os descendentes mais afastados (netos, bisnetos, etc). Infelizmente, para as versões anteriores ao IE7 os efeitos da estilização com seletore filho estarão perdidos.

    Por outro lado o uso de seletor filho pode tornar-se "útil" para escrever regras que devam ser ignoradas pelo IEWin, tal como html>body  elementoalvo. Esta regra funciona porque body sempre é filho direto de html, e em consequência a primeira parte da regra é sempre verdadeira. Colocando a seguir no seletor o elemento de combinação 'espaço em branco' logo antes de .elementoalvo (um elemento qualquer a casar) conseguiremos aplicar estilos a qualquer elemento contido em body.

    IEWin ignora completamente a regra acima porque não oferece suporte para elemento de combinação filho ">". Com a chegada do IE7 teremos suporte para o hack CSS com uso de seletor filho. Mas considerando que este navegador ainda virá com algumas falhas, deixá-lo ver o hack do seletor filho pode ser no mínimo, menos do que desejável.

  • Seletor irmão adjacente The Adjacent Sibling Selector

    Este seletor usa o elemento de combinação (sinal de adição) "+" colocado entre partes de seletores e é bastante semelhante ao seletor filho. A única diferença entre os dois é que enquanto seletor filho casa com filhos diretos de um elemento, este casa com o elemento que imediatamente se segue a um elemento no código de marcação.

    Assim, o seletor tr+td não casa com ninguém, uma vez que TD nunca se segue a TR no código. TD's estão contidas dentro de TR's, o que não pode ser considerado "seguindo" uma TR. Por outro lado o seletor tr+tr casa com qualquer TR que se segue a uma TR, e isto casa com todas as TR's de uma tabela exceto a primeita TR da tabela.

    Entendeu? Um elemento irmão adjacente (adjacent sibling) não somente se segue ao seu irmão, como também é independente e separado dele. Explicando melhor, se duas DIV's se seguem e cada uma delas contém um parágrafo, tais parágrafos não são irmãos adjacentes, pois são filhos de pais diferentes, cada um de uma DIV. O fato de um elemento se seguir a outro não significa nada é preciso que os elementos sejam irmãos (filhos do mesmo pai) e adjacentes (estejam em sequência no código fonte).

    É permitido construir uma sequência de irmãos adjacentes, assim o seletor td+td+td casa todas as TD's que se seguem diretamente à duas TD's. Isto significa que a terceira, a quarta, a quinta e todas as demais TD's existentes em uma linha da tabela casarão com o seletor de vez que todas tem duas TD's antes delas no código.

    As duas TD's na próxima linha da tabela não serão selecionadas pois estão dentro de uma outra TR. Mas, a partir dai vale o que foi visto acima e as TD's deverão ser selecionadas tal como na linha anterior.

    Seletores irmãos adjacentes serão úteis no futuro, pois por enquanto são usados para hacks tal como os seletores filho. Isto é ruim.

Está claro que precisamos eliminar tais hacks de nossas CSS antes que nossos clientes sejam tomados por ímpetos assassinos contra nós.

Mas, são ou não são três ?

Oh, quer saber a resposta desta pergunta sobre estrutura ? Bem, ela refere-se ao hack conhecido como (estrela-html) star-html, e funciona tirando partido de uma singularidade do Explorer na maneira como ele interpreta o Document Object Model, ou abreviadamente DOM. O DOM estabelece que todas as páginas web comecem com um elemento raiz chamado html, que contém dois elementos filhos, o head e o body. Estes dois elementos por sua vez contém seus elementos filhos e assim por diante.

A maioria dos navegadores segue este modelo de DOM, mas o Explorer tanto para Windows como para Macintosh não seguem. Aparentemente eles acreditam que existe um elemento misterioso servindo de container para o elemento html! Isto é muito estranho, mas o fato é que este elemento "raiz" extra, aparenta não causar qualquer efeito nas páginas web e permaneceu desconhecido durante anos até que Edwardson Tan iniciou seus experimentos com seletores CSS. Ele acabou descobrindo que um seletor do tipo * html  .elementoalvo aplica estilos no elemento alvo .elementoalvo, mas somente em navegadores IE.

Pense nisso. A estrela é o seletor "universal", e como tal casa com qualquer elemento, mas está antes de html. Então o seletor no seu todo diz o seguinte: "Selecione o .elementoalvo quando ele estiver contido em html, e quando html estiver contido em um outro elemento qualquer".

Obviamente uma vez que html é o elemento raiz da página, não pode estar contido em outro elemento qualquer, mas é isso exatamente o que pensa o IE! Não sabemos o nome deste elemento, mas isso não importa pois o seletor estrela casa tal elemento, qualquer que seja ele já que contém o html.

Como você pode concluir este hack é bastante útil, especialmente se estiver contido em outro hack para escondê-lo do IEmac. Assim procedendo você estará criando uma regra CSS exclusiva para o IEWin e sem efeito para qualquer outro navegador. Este hack tipo pacote é perfeito para lidar com problemas de box model e outras regras que devem ser servidas com exclusividade para o IEWin, particularmente o Holly hack.

Cruel, a Microsoft vai resolver esta singularidade e o elemento html voltará a ocupar sua posição correta de "raiz" no IE7. Isto é um avanço em direção as standards para eles, mas criará um problema. Yep, assim como para os seletores combinados, qualquer página que use o hack estrela-html quebrará no IE7, porque agora este navegador não não conseguirá ler tais regras.

A procura desesperada por soluções

Felizmente para nós a Microsoft desenvolveu também uma funcionalidade no navegador, chamada Comentários Condicionais (disponível desde a versão IE5win). CC's (Comentários Condicionais) possibilita aos desenvolvedores servir código exclusivamente para o IEWin inserida dentro da marcação para comentários do HTML em uma maneira que aqueles navegadores interpretem seu conteúdo como marcação de código. Outros navegadores não tem esta funcionalidade e verão ali simplesmente comentários HTML, ignorando seu conteúdo.

Percebeu aonde poderemos chegar com isso? Aqueles tão úteis (mas agora inoportunos) hacks CSS colocados em nossas folhas de estilos devem ser retirados de lá e colocados em uma folha de estilos separada. Criamos assim uma nova e independente folha de estilos contendo os "hacks para o IEWin" que deverá ser chamada pela página por um link dentro da seção head do documento oculto dos demais navegadores com uso de Comentários Condicionais. Todos os demais navegadores (inclusive o IEmac) interpretarão ali um comentário HTML normal e seguirão adiante no código, sem problemas. O IEWin contudo interpretará o conteúdo do CC como código de marcação e seguirá o link ali indicado para uma folha de estilos contendo os hacks e que será aplicada ao documento seguindo as regras CSS do efeito cascata. Beleza! Veja a seguir como codificar o link:

<!--[if IE]>
	<link rel="stylesheet" type="text/css" href="iehacks.css" />
<![endif]-->

OK, este caminho não é tão conveniente quanto o uso do hack estrela-html, mas ao contrário deste hack os CC não estão indo embora. Além disso, os CC já demonstraram ser seguros e confiáveis. Atá mesmo o validador do W3C reconhece os CC como comentários normais e a página que os contém valida normalmente até mesmo se você inserir nos CC um link para uma folha de estilos contendo regras de estilos proprietárias da MS e inválidas.

É claro, nós entendemos que CC está sendo usado para habilitar uma folha de estilos destinada a fazer com que o IEWin tenha um comportamento o mais próximo possível das standards certo? Como assim? Você realmente quer que a sua página use aquela propriedade proprietária da MS para estilizar e colorir a barra de rolagem? Bem, agora você pode fazer isso, pois este método dos CC retira de sua folha de estilos principal, as regras proprietárias. E assim, a validação de sua CSS está garantida.

Um dos comentários postados em artigo no blog Mezzoblue's ressalta que os sinais de colchetes utilizados na sintaxe dos CC causam erros quando se projeta com XSLT. Felizmente Nick Fitzsimons também leu aquele comentário e desenvolveu para nós um método para resolver o problema de gerar CC's via XSLT. Obrigado Nick!

Vamos passar direto ao detalhamento de como tratar e limpar uma página web servida com hacks. Aqui mesmo no site da PIE existem várias páginas nesta situação. Oh, bem...

Caindo na real

Em lugar de causar embaraços para terceiros expondo seus hacks à ridicularização pública, nós usaremos como exemplo as páginas do nosso próprio site, mas parece que elas não contém outros hacks que não seja o hack estrela-html. Assim, nós iremos mostrar como tratar os hacks que normalmente são encontrados em páginas web existentes em geral.

O Tantek hack

>#wrapper {
    border: 10px solid black;
    width: 770px; /* IE5.x/win vê este valor... */
    voice-family: "\"}\"";
    voice-family: inherit;
    width: 750px; /* ..mas não vê o valor "standard".. */
}

html>body .content {
width: 750px; /* ..nem este valor é visto. */
}

Este é o conhecido Tantek hack, que define uma largura especial para as versões do IEWin anteriores ao IE6 com a finalidade de corrigir o o problema do box model, e adicionalmente descreve uma regra que usando o seletor filho que é um segundo hack para o Opera 5 que tem problemas com o hack anterior. Todas estas regras de estilo foram substituidas por uma regra mais simples com a criação do hack estrela-html, contudo muitas páginas web ainda usam o Tantek hack. O exemplo mostrado acima refere-se a correção para a largura de uma DIV com 770px e com 10px de bordas laterais que serão adicionadas onde definido 750px de largura.

Tecnicamente este hack não precisa ser retirado porque se vale do uso de caracteres de escape para esconder alguns caracteres críticos para as versões mais antigas do IE. Os IE6, IE7 e demais browsers modernos não sofren qualquer influência daqueles caracteres de escape legais e assim nada de errado acontece se o hack for visto pelo IE7. Nada, nem mesmo a última parte do hack causará problema, pois o uso do seletor filho simplesmente define a largura "standard" que para o IE6 e IE7 já foram definidas na primeira parte do hack. Mesmo que o IE7 comece a leitura pelo hack do seletor filho ele verá o valor correto da largura.

Mais ainda. Já que estaremos retirando os hacks perigosos das nossas CSS, vamos remover o Tantek hack também. Naturalmente as regras para as bordas e as demais regras CSS que não fazem parte do hack deverão permanecer na folha de estilos principal, juntamente com a definição "standard" para a largura de 750px. Lembre-se que os CC habilitarão uma folha de estilos hacks.css somente para as versões 5 e menores do IEWin, e desta forma não mais haverá necessidade de hacks para esconder regras CSS do IEMac.

Uma vez retirado o hack da folha de estilos principal ele será colocado em iehacks.css conforme mostrado abaixo:

iehacks.css
    #wrapper {
    width: 770px;
    wid\th: 750px;
}

Está vendo o caractere de "escape" em vermelho na segunda propriedade? Aquele é um caractere de escape legal e deveria ser ignorado, contudo quando colocado dentro de uma propriedade ele não é ignorado pelo IE5 e IE5.5 para Windows. Em vez de ignorar o caractere em si, aqueles navegadores ignoram a letra "t" que se segue ao caractere de escape fazendo com a propriedade não faça sentido e em consequência ignorada. O resultado disso é que todos os IE /Win adotam primeiramente a maior a largura e a seguir, somente o IE6 e o IE7 enxergam e adotam a segunda largura que é a standard. Lembre-se que o caractere de escape não deve ser colocado antes de qualquer uma das seis primeiras letras do alfabeto pois tais combinações são reservadas a uma maneira especial de interpretação. Se escrevermos "wi\dth", então o IE6 e o IE7 irão ignorar o "d" e ler o nome da propriedade como "with". Isto é mau. Sendo mais específico as letras a, b, c, d, e, f estão proibidas para se seguir ao caractere de escape nestes casos.

Felizmente sempre haverá uma letra dentro do nome de uma propriedade diferente de uma destas seis letras e que poderá ser seguramente escapada. Contudo você não poderá escapar o "w" em "width", porque o IE5.5 ignora o escape quando ele é colocado no início. Coloque o escape dentro do nome, para que funcione. Uma vez que o IE5 e o IE5.5 são os navegadores que interpretam o caracterere de escape desta maneira e que apresentam o problema do box model esta solução de uso do escape é perfeita e não causará qualquer problema futuro.

Um método alternativo

Os CC's podem ser servidos a diferentes versões do IE pois dependendo do que se escreve no início da tag do comentário condicional ele será visto ou ignorado por determinada versão. Ver a página da Microsoft para detalhes específicos, e o artigo Taming Your Multiple IE Standalones no site da PIE para maiores detalhes e dicas úteis sobre o uso de CC's.

Assim, você pode criar dois arquivos diferentes para hacks, um arquivo com hacks gerais para todas as versões do IEWin e outro somente para as versões do IE que quebram o box model com hacks que devam ser servidos para as versões anteriores ao IE¨6 para Windows:

<!--[if IE]>
  link rel="stylesheet" type="text/css" href="iehacks.css" />
  ![endif]-->

  <!--[if IE 5]>
  <link rel="stylesheet" type="text/css" href="iehacks-5.css" />
  <![endif]-->

Colocando um "5" na tag inicial, você estará servindoas versões do IEWin que começam com 5. A versão IE5.5 começa com 5 e em conaequência verá o CC tal como a versão 5.

Uma vez criados tais arquivos de hacks é fácil colocar no arquivo para as versões 5 as larguras e alturas alternativas para o box model quebrado. Isso irá evitar a necessidade de uso de hacks nas folhas de estilo para uso geral, mas por outro lado a criação de mais uma folha de estilos poderá aumentar as chances de se encontrar dificuldades e cometer erros futuramente.

Ao usar este método certifique-se de que os links para as folhas de estilo servidas por comentários condicionais sejam escritos no código depois do link para a folha de estilos geral e ainda que as regras de estilo contidas naquelas folhas tenham uma especificidade pelo menos igual ou maior que a especificidade da regra similar contida dentro da folha de estilos geral. Se assim não for feito, as regras com os hacks não terão prioridade sobre as regras gerais quando lidas pelo IEWin e tais hacks não funcionarão. Caso usar duas folhas de estilos servidas por CC's certifique-se ainda de não haver regras de estilo conflitantes e que a ordem e especificidade das regras é a apropriada, caso contrário você poderá ter problemas.

O hack do seletor filho e do seletor irmão adjacente.

Estes seletores quando usados para hacks normalmente destinam-se a esconder uma regra CSS que por uma razão qualquer quebraria no IEWin. Assim elas simplesmente podem ser removidas das CSS sem consequências para os demais navegadores que não o IE. É verdade o hack que utiliza o seletor filho pode ser retirado servindo para o IE7 a regra geral, mas as versões mais antigas do IE também verão a regra geral e quebrarão. De algum modo precisamos simplificar a regra sem contudo permitir que as versões antigas do IEWin a vejam.

De fato, esta simplificação não é possível de se conseguir atualmente na folha geral e então deixamos que o IEWin veja a regra geral e escrevemos uma regra "negando", servida por CC e que não afetará os demais navegadores.

Um uso comum de seletores filho é para servir ao IEWin a propriedade height onde os demais navegadores devam ser servidos com uma min-height. Já que o IEWin expande qualquer dimensão quando se acresenta conteúdo ao container, a propriedade height é tratada como min-height por aquele navegador. Oneste caso é importante não permitir que os demais navegadores vejam a height servida para o IEWin. Isto, tipicamente pode ser feito como mostrado a seguir:

#wrapper {
  min-height: 500px; /* IEWin does not support min-height */
  height: 500px;
}

html>body #wrapper {
  height: auto;
}

As regras acimas primeiramente definem tanto min-height como height como tendo o mesmo valor, e a seguir o hack usando o seletor filho que não será visto pelo IEWin restabelece de volta o valor default auto para height. Infelizmente o IE7 verá a segunda regra e acontece que este navegador a exemplo das versões mais antigas também expande os containers para acomodar conteúdos. Isto implica em que o IE7 também retoma o valor default auto para height e o "efeito" de min-height estará perdido para este navegador.

A solução para este caso está em se retirar completamente a declaração via o hack do seletor filho com seu valor auto e mover tal declaração om arquivo de hacks, iehacks.css. Agora o IEWin será servido com o valor apropriado para height te os demais navegadores não serão afetados por aquele valor. O problema está resolvido, pelo menos até que apareça uma versão IEWin que não expanda boxes impropriamente!

Como CC's são bastante flexíveis isso não vem a ser um grande problema. Vamos supor que foi lançada a versão IE8 e tenha sido corrigido este problemas da expansão dos boxes. Felizmente uma radical transformação com suporte para min-height. Agora não queremos que a propriedade height servida para op IE7 e anteriores seja vista pelo nosso suposto IE8. É provável que muitas outras melhorias também cheguem com o IE8 e assim haverá uma considerável quantidade de hacks a ser escondido deste navegador. Poderemos então resolver o problema escrevendo um CC como mostrado a seguir:

<!--[if lt IE 8]>
  <link rel="stylesheet" type="text/css" href="iehacks.css" />
  <![endif]-->

Você está vendo aquele "lt" escrita na tag do CC? Aquilo significa "less than" (versão menor que) IE8, estando assim excluido este navegador da leitura daquelas regras pois o link não será visto pelo IE8. Dependendo do que está por vir com as futuras versões do IE, várias combinações de CC's poderão ser feitas para tratar o que vier. Mais uma vez vamos esperar que a MS não traga mais complicações para nós, eh?

Existe um hack chamado Owen hack, que usa um seletor tipo head:first-child+body {}. Este hack não é visto pelo Opera 6, enquanto o Opera 7 não tem problemas com ele. Hoje em dia, poucos se preocupam com o Opera 6, mas o hack ainda é encontrado em algumas folhas de estilos e a MS alerta sobre seu uso.

Sabemos que o seletor irmão adjacente será suportado pelo IE7, mas o Owen hack contém também "head:first-child." Esta é uma pseudo classe CSS avançada que não é suportada pelas versões atuais do IEWin, mas alertas vindos da MS apontam para a possibilidade de suporte para :first-child e similares pelo IE7! Verdade ou não, isto pode ser uma clara indicação que o uso de seletores avançados para servir hacks escondendo regras CSS de navegadores com fraco suporte pode ser contra producente. Sábias palavras, eh?

O hack estrela-html

Não há mais muito a se dizer sobre este hack. Ele esconde uma regra de todos os navegadores, menos do IE, assim, permite que o IEWin e o IEMac vejam a regra. O IE7 deve ser excluido deste hack, e para isso use os CC's para a folha de estilos iehacks.css, ou se necessário um CC mais específico.

O único problema é com o navegador IEmac. Pode haver caso em que o hack deve ser visto tanto pelo IEWin como pelo IEMac, contudo como agora as regras para IE estão dentro de um CC, pobre do IEMac, não conseguirá enxergá-las. Para resolver este probvlema vamos apelar para o que nós chamamos de hack exclusivo para o IEMac, criado por Tantek Çelik ( um programador da MS entre entre coisas). É o velho hack para esconder do Mac com uma inovadora modificação. É uma sintaxe construida com um par especial de comentários CSS dentro dos quais são colocadas as regras de estilos que serão vistas somente pelo o IEmac. Suponha que o IEMac necessita de uma regra exclusiva tal como uma width especial para um float. Você poderá servir tal regra escrevendo na sua folha de estilos geral o seguinte:

/*\*//*/
    #floatedbox {width: 200px;}
/* */

Você encontrará uma explicação do funcionamento desta regra lendo este documento, mas não se preocupe por ter que conviver com um hack indesejável dentro da sua folha de estilos geral. Este hack depende totalmente de uma falha de parseamento da engine do IEMac causado pelo caractere de escape colocado dentro do primeiro comentário.Nenhum navegador posterior ao Nav 4 ou ainda por ser inventado tem ou terá problemas com este hack. Além do mais o IEMac não mais será desenvolvido pela MS e assim podemos acreditar que as chances de problemas com este hack são nulas. Use este hack sem preocupações!

Conclusão

Por hora você já tem uma boa visão geral do que está por vir. Se o seu código está recheado de hacks CSS assim como o nosso, você tem duas opções: Corrija agora ou promova e assista a ruína de seus documentos. A escolha é sua.

De toda forma, não há razão para querer triturar a Microsoft. Nós bradamos durante anos que eles deveriam efetivamente fazer o que estavam por fazer. Seria ótimo para eles corrigir todos os bugs ao mesmo tempo, mas sejamos realistas, isto não deverá acontecer. MS está definitivamente começando a encarar seriamente esta questão e o IE7 será o primeiro passo em direção ao desenvolvimento de um Explorer mais complacente com as standards. Se a MS se dispõe a enfrentar uma série de más implementações com a finalidade de colocar o Explorer em total complacência com as standards, nós preferimos encarar esta atitude como um bom sinal para o futuro.

De toda forma, por que não ter uma atitude positiva? Isto não custará nada e ainda reduzirá o risco de contrairmos uma gastrite. Esta é nossa política e estamos fechados com ela.

topo