:: O conceito hasLayout do IE ::

Editores: Holly Bergevin | Ingo Chao | Bruno Fassino | John Gallant |
Georg Sørtun | Philippe Wittenbergh
URL do original: http://www.satzansatz.de/cssd/onhavinglayout.html
Título original: On having Layout
Traduzido e publicado com direitos autorais conforme Creative Commons license.

Trabalho em andamento.

Esta versão (original em inglês):
Revisão 5 2005–09–14
Histórico de modificações
Traduções
Tabela de conteúdos
Esta versão (tradução):
Em: 2005–10–27 baseada na Revisão 5 em 2005–09–14
Atualizada em: 2007–10–25 baseada na Revisão 8 em 2007–10–23

Introdução

Várias das inconsistências de renderização no Internet Explorer podem ser solucionadas atribuindo-se o valor “layout” para um determinado elemento HTML. John Gallant e Holly Bergevin classificaram estas inconsistências como “bugs dimensionais,” termo que tem origem no fato de que tais inconsistências na maioria das vezes podem ser solucionadas declarando-se um valor para a largura ou para a altura do elemento. E, cabe perguntar: por que “layout” altera a renderização e a maneira como os elementos se relacionam? Uma boa pergunta, mas de difícil resposta. Neste artigo os autores focam alguns aspectos desta complicada questão. Para maiores discussões e exemplificações siga os links fornecidos no artigo.
(NT: Os links remetem a documentos escritos em inglês)

hasLayout — Definição

“Layout” é um conceito proprietário do IE/Win que determina como os elementos representam e delimitam seus conteúdos, como interagem e se relacionam com outros elementos e como reagem a uma aplicação/evento de usuário.

Esta qualidade pode ser irreversivelmente configurada para true (verdadeira) por algumas propriedades CSS. Alguns elementos HTML têm “layout” por default.

Desenvolvedores da Microsoft decidiram que um elemento do tipo box deveria ser capaz de adquirir uma “propriedade” (com o sentido de programação orientada a objetos) a qual eles desenvolvedores denominaram haslayout. Esta "propriedade" é configurada para true (verdadeira) quando tal conceito se efetiva na renderização.

Nomenclatura

Diz-se que um elemento “gaining layout” (ganha layout) ou ainda que um elemento “has layout” (tem layout) quando a propriedade proprietária da Microsoft hasLayout está configurada para true. Um “elemento layout” pode ser qualquer elemento que tem layout por default ou ganhou layout por uma propriedade CSS apropriada.

Para elementos “não-layout”, haslayout não é configurado, isto é, uma div sem uma dimensão definida pode ser um “ancestral não layout”.

Dar ou aplicar “layout” a um elemento que não o tenha por default envolve definir uma propriedade CSS para o elemento que configure hasLayout = true. Veja elementos que tem layout por default e propriedades para eles. Não há como configurar hasLayout = false a não ser removendo ou redefinindo a propriedade CSS que tenha anteriormente configurado hasLayout = true.

Como que estaremos envolvido

Problemas causados por hasLayout afetam designers (e programadores) de todos os níveis de experiência. É difícil prever os efeitos sobre a apresentação e comportamento de boxes, bem como para os elementos contidos nestes boxes.

As consequências de um elemento ter ou não ter “layout” podem ser responsáveis por:

  • Muitos dos bugs de floats no IE.
  • Tratamento diferenciado para propriedades básicas dos boxes.
  • Sobreposição de margens entre um container e seus descendentes.
  • Vários problemas relacionados a construção de listas.
  • Diferenças no posicionamento de imagens de fundo.
  • Diferenças entre navegadores quando do uso de scripts.

A lista acima esta resumida e incompleta. Este artigo pretende descrever mais detalhadamente questões relacionadas com a aplicação ou não de “layout”.

De onde veio layout

Ao contrário de propriedades standards ou mesmo de propriedades CSS proprietárias diponíveis para diferentes navegadores, layout não é definido diretamente via declarações CSS. Em outras palavras, não existe uma “propriedade layout.” Alguns elementos “tem layout” automaticamente, para outros esta condição é adquirida via declarações CSS.

Elementos que tem layout por default

Os elementos a seguir têm layout.

  • <html>, <body>
  • <table>, <tr>, <th>, <td>
  • <img>
  • <hr>
  • <input>, <button>, <select>, <textarea>, <fieldset>, <legend>
  • <iframe>, <embed>, <object>, <applet>
  • <marquee>

Propriedades

As declarações propriedade/valor a seguir, quando aplicadas a um elemento fazem-no ganhar layout.

position: absolute
Refere-se ao seu bloco de conteúdo e é aqui que começam os problemas.
float: left|right
O modelo para float apresenta uma grande quantidade de inconsistências ligadas a alguns aspectos de um elemento layout.
display: inline-block
Algumas vezes esta é uma solução para dar layout a um elemento inline. Aplicar layout é provavelmente o único efeito real desta propriedade. O “comportamento inline-block” pode ser conseguido no IE, porém de forma completamente independente: IE/Win: inline-block and hasLayout.
width: qualquer value que não seja 'auto'
Frequentemente esta é uma solução implicita mas também muito usada como solução para um comportamento errado de hasLayout.
height: qualquer value que não seja 'auto'
height: 1% é usada no Holly Hack.
zoom: qualquer valor que não seja 'normal' (MSDN)
propriedade proprietária da MS que não valida. zoom:1 pode ser usado para fins de debug.
writing-mode: tb-rl (MSDN)
propriedade proprietária da MS que não valida.

Para o IE7, a propriedade overflow faz ganhar layout.

overflow: hidden|scroll|auto
Esta propriedade não faz ganhar layout em versões anteriores do IE, a menos que "layout" tenha sido aplicado em outras propriedades como descrito acima.
overflow-x|-y: hidden|scroll|auto
Os valores overflow-x e -y previstos nas CSS3 ainda não são amplamente suportados e implementados. Estes valores não fazem ganhar layout em versões anteriores do IE.

O suporte para min/max agora implementados no IE7 atuam de maneira similar a width e height bem como os efeitos de posicionamento fixo e absoluto parecem funcionar também de forma idêntica.

position: fixed
./.
min-width: qualquer valor
Mesmo o valor 0 (zero) faz o elemento ganhar layout.
max-width: valores diferentes de 0 (zero)
./.
min-height: qualquer valor
Mesmo o valor 0 (zero) faz o elemento ganhar layout.
max-height: valores diferentes de 0 (zero)
./.

Baseado em experiências feitas com a Barra de Ferramentas do IE e testes preliminares.

Notas sobre elementos inline

Para elementos inline (tanto por default como é o elemento span, quanto por configuração via a regra CSS; display: inline):

  • as propriedades width e height ativam hasLayout, ou seja, quando aplicadas a um elemento tornam layout verdadeiro no IE 5.x e IE 6 ou mais recentes quando em modo quirks. Assim como no IE6, quando um navegador está em “standards-compliance mode” os elementos inline ignoram as propriedades width e height, então definir estas propriedades para tais elementos, não fará com que o elemento ganhe layout.
  • zoom sempre ativa hasLayout porém não é suportado pelo IE5.0.

Elementos inline que tenham definidos tanto “layout” (elementos hasLayout) quanto elementos definidos como display: inline comportam-se da maneira como previsto pelas standards para inline-block: isto é, fluem na horizontal como palavras contidas em um parágrafo, são sensíveis ao alinhamento vertical, e aplicam comportamento próprio ao seus conteúdos. Elementos inline ao adquirir layout agem como se fossem inline-block, isto explica o porque de elementos inline no IE/Win, poder conter e manipular elementos block-level de forma menos problemática que em outros navegadores onde display: inline permanece válido.

Redefinindo hasLayout

Redefinindo o valor das propriedades listadas a seguir, para o seu valor padrão em uma regra CSS separada, tornará sem efeito (ou undo) hasLayout, se nenhuma outra propriedade dando layout permanecer definida:

  • width, height (to 'auto')
  • max-width, max-height (to 'none') (in IE 7)
  • position (to 'static')
  • float (to 'none')
  • overflow (to 'visible') (in IE 7)
  • zoom (to 'normal')
  • writing-mode (from 'tb-rl' to 'lr-tb')

Autores devem tomar precauções com a redefinição destas propriedades. Suponha um sistema de navegação: Alterando o status de hasLayout para a:hover, seja intencionalmente ou não, pode resultar em renderização inesperada (ou instabilidade no IE 6 quando a mudança for feita dinamicamente e em combinação com position: relative).

A propriedade display difere: enquanto 'inline-block' define haslayout = true, não haverá mudança para false se o valor for definido para 'block' ou 'inline' em uma subsequente regra CSS.

Definindo as propriedades min-width, min-height para seu valor padrão '0' ainda continua dando hasLayout, mas o IE 7 aceita para elas o valor inválido 'auto', que redefine hasLayout.

A propriedade script de hasLayout

Nós escolhemos nos referir a hasLayout como uma “propriedade de script” com a finalidade de fazer distinção com a nossa conhecida e familiar propriedade CSS.

Não existe uma maneira de definir diretamente a propriedade script de hasLayout .

A propriedade hasLayout pode ser usada para verificar se um determinado elemento has layout: Se, por exemplo existir no documento uma id com o nome “eid”, digite na barra de endereços do IE5.5+ a seguinte linha de comando para rodar o teste:

javascript: alert(eid.currentStyle.hasLayout)

A Developer Toolbar para o IE permite inspecionar os estilos aplicados a um elemento; quando hasLayout é verdadeiro ela retorna um valor "-1". Editando os atributos de um nó, você pode definir "zoom (css)" para "1" para ativar hasLayout com propósitos de debug.

Um outro aspecto a considerar é o de como “layout” afeta o funcionamento de scripts. As propriedades clientWidth/clientHeight sempre retornam zero para elementos sem “layout”. Isto pode causar confusão para programadores inexperientes pois scripts podem induzir comportamentos diferentes nos navegadores Mozilla. Podemos usar este fator pra determinar a condição de “layout” no IE5.0: Se clientWidth retorna zero então o elemento em questão não tem layout.

hacks CSS

Os seguintes hacks que ativam haslayout foram testados no IE7 e anteriores:

John Gallant e Holly Bergevin publicaram o Holly hack em 2003:

  1. /* \*/
  2. * html .gainlayout { height: 1%; }
  3. /* */
  • Dá layout no IE5-6 para qualquer elemento, exceto para elementos inline no IE6 em modo standards.
  • De um modo geral funciona de forma adequada exceto em alguns casos raros onde height:0 ou 1px é mais estável.
  • É incompatível com overflow: hidden, exceto para o IE6 em modo standards (onde height: 1% transforma-se em height: auto, a menos que o elemento pai tenha uma altura - height - especificada.)
  • Não tem efeito no IE7 em modo standards em que * html não casa com nada.

Para dar layout ao IE6 e anteriores, podemos usar também o underscore hack:

  1. .gainlayout { _height: 0; }

Para dar layout ao IE7 podemos usar a propriedade min-height:

  1. .gainlayout { min-height: 0; }

Alternativamente temos os comentários condicionais:

  1. <!--[if lte IE 6]>
  2. <style>
  3. .gainlayout { height: 1px; }
  4. </style>
  5. <![endif]-->
  1. <!--[if IE 7]>
  2. <style>
  3. .gainlayout { zoom: 1; }
  4. </style>
  5. <![endif]-->

Usar comentários condicionais para fornecer um link apontando para uma folha de estilos externa que contenha soluções aplicáveis ao IE/Win constitui-se em uma alternativa segura e elegante:

  1. <link rel="stylesheet" href="allbrowsers.css" type="text/css" />
  2.  
  3. <!--[if lte IE 7]>
  4. <link rel="stylesheet" href="iefix.css" type="text/css" />
  5. <![endif]-->

Para o IE6 e anteriores height deve ser usado "sempre" (se quisermos servir o IE5, não temos muitas alternativas), desde que isto não entre em conflito com outras declarações (overflow: hidden). Os valores, 1%, 1px, 0 são mais ou menos equivalentes, mas 1% pode (embora muito raramente) causar problemas.

A propriedade height não pode ser usada para elementos inline em modo standard e deve ser evitada para o IE7 (ou usada com precaução:(somente valores em porcentagem quandoo elemento não tiver uma altura definida). Neste caso nós preferimos usar display: inline-block ou zoom: 1.

Nós temos presenciado tentativas desesperadas da aplicação de “holy” hacks (sic!) a elementos flutuados ou mesmo a elementos que já tenham uma largura - width - definida. Lembre-se que a finalidade de aplicação de um hack deste tipo não é a de definir uma altura - height - para um elemento, mas sim a de configurar hasLayout = True.

Não dê layout a todos os elementos com a declaração: * {_height: 1px;}. Aplicar um veneno nesta concentração não produz a cura, pois isto altera os conceitos fundamentais de renderização.

Gerenciamento de hack

A chegada do IE7 demonstrou que é impossível prever se futuras versões deste navegador corrigirão ou não bugs devidos a haslayout bem como qual o comportamento que assumirão face aos filtros em uso hoje em dia. Em função disto, pode-se aconselhar o uso da propriedade zoom proprietária da Microsoft e/ou de comentários condicionais.

  1. <!--[if lt IE 7]><style>
  2. /* style for IE 6 + IE5.5 + IE5.0 */
  3. .gainlayout { height: 0; }
  4. </style><![endif]-->
  5.  
  6. <!--[if IE 7]><style>
  7. .gainlayout { zoom: 1;}
  8. /* or whatever we might need tomorrow */
  9. </style><![endif]-->
  • zoom: 1; dá layout para qualquer elemento no IE5.5+ (inclusive para elementos inline), contudo não produz qualquer efeito no IE5.0
  • Não produz qualquer efeito colateral conhecido (elementos inline se comportam como inline-block).
  • Se você precisa validar então zoom deve ser oculto via comentário condicional.

Se por um lado acreditamos que “prova futura” seja um termo contraditório, nós fortemente sugerimos que projetistas web “plays for sure” e revisem suas páginas no que se refere a existência de “hacks” explícitos e implícitos e use comentários condicionais para servir tais hacks para as apropriadas versões do navegador.

Para uma visão mais detalhada de como ativar hasLayout bem uma comparação dos hacks existentes para as várias versões do IE consulte: Thoughts on IE hack management.

Uma nota sobre IE Mac.

IE Mac e IE para Windows são animais diferentes que vivem em jaulas separadas no zoológico. Cada um deles tem sua engine própria e o IE Mac não sabe nada sobre o comportamento “hasLayout” (ou contenteditable). A engine do IE Mac tende a ser mais complacente com as standards, tratando height como deveria ser tratada. Hacks e workarounds para problemas ocasionados por “hasLayout” (especialmente quando se usa as propriedades height ou width) frequentemente causam efeitos nocivos para o IE Mac, e devem ser ocultos para este navegador. Para saber mais sobre problemas no IE Mac consulte IE Mac, bugs and oddities pages.

Documentação MSDN

Em MSDN, existem poucas páginas dedicadas a propriedade MS, hasLayout e poucas explicações de como layout se relaciona com o modelo visual de formatação do IE.

Retrocedendo à época do IE4, quase todos os elementos tinham uma espécie de layout, exceção a elementos simples não posicionados absolutamente e sem uma dimensão definida (MSDN - Este documento foi modificado 1). Neste antigo conceito de layout existiam “propriedades de layout” tais como border, margin, padding, que não podiam ser aplicadas a tais elementos simples inline. Em outras palavras “tendo layout” era jutamente um outro termo para: “pode ter estas propriedades”.

MSDN ainda hoje se refere a “propriedades de layout,” contudo seu significado mudou, não está mais associado a elementos que tem layout. A propriedade MS, hasLayout foi introduzida com o IE5.5, mais ou menos como uma flag interna.

Em IE5.5, a documentação MSHTML para Plataformação de Edição (que permite livre edição, dimensionamento e deslocamento de elementos do layout via declaração <body contenteditable=true>) expõe três aspectos importantes relacionados a ter layout:

Se um elemento tem algum conteúdo o layout para este conteúdo é determinado pelos limites de um retângulo.

Ter layout, significa basicamente que o elemento é retangular.

Internamente, ter layout implica em que o elemento é o responsável pelo delineamento do seu conteúdo.

(Plataforma de Edição - Documento removido da MSDN 2)

Os aspectos do funcionamento interno relacionados ao layout não estavam documentados até agosto de 2005, quando Markus Mielke [MSFT - Força Tarefa da Microsoft] abriu as portas para discussões em conjunto com The Web Standards Project e com a Microsoft task force:

De maneira geral, na engine do Internet Explorer para HTML dinâmico os elementos não são responsáveis pela maneira como se arranjam. Um elemento div ou um elemento p devem ocupar uma posição definida no código fonte e no fluxo do documento, contudo seus conteúdos são arranjados pelo seu ancestral mais próximo com layout (normalmente body). Estes elementos são dependentes do layout do ancestral para determinação de tamanhos e medidas para seu próprio layout.

(HasLayout Overview)

Interpretação

Nossa interpretação é uma tentativa de explicar o que acontece em casos conhecidos e isto poderá servir como uma orientação para casos ainda não totalmente conhecidos. A tentativa de dismistificar uma caixa preta simplesmente observando o que acontece quando realizamos alguns testes, está condenada ao fracasso. O “por quê” fica sem resposta. Temos que tentar entender como o modelo “hasLayout” funciona e como afeta a renderização de documentos web. Ao entender o modelo, diretrizes poderão ser desenvolvidas (mas serão apenas diretrizes e não soluções absolutas).

Acreditamos que o modelo da MS compara-se a um quadro que se pendura na parede. O conteúdo de um elemento layout deve ser completamente independente de qualquer coisa fora dos limites do elemento e tampouco poderá afetar qualquer coisa fora daqueles limites.

A propriedade MS hasLayout é uma espécie de flag: quando ativada atribui ao elemento a “qualidade” layout, que lhe confere capacidades especiais - por exemplo, para floating e stacking - para si mesmo e para seus elementos filho sem layout.

Uma das razões de os elementos layout serem usualmente mais estáveis está nesta sua maior independência, o que resulta no desaparecimento de alguns bugs. Hoje, o preço a se pagar por isto pode ser a divergência com as standards e o aparecimento de problemas causados com bugs futuros.

O modelo para “página” da MS sintomaticamente pode ser comparado a pequenos blocos que não se relacionam entre si enquanto no modelo para “página” do HTML do W3C, os blocos se relacionam entre si e com seus conteúdos.

Uma revisão das consequências

Clearing floats e o auto ajuste

Floats são auto-contidos por elementos layout. Esta é uma das razões pelas quais a maioria dos iniciantes esforça-se no trabalho de compatibilizar suas páginas projetadas para o IE com os navegadores complacentes com as standards onde os elementos floats ultrapassam os limites dos seus blocos de conteúdo quando não se usa a propriedade clear.

O comportamento oposto: e se um bloco flutuado deva ultrapassar os limites do seu conteúdo isto é, quando não se deseja que o bloco de conteúdo se expanda para conter o float? para uma demonstração dos frustantes problemas daí advindos confira nossa discussão:

No IE, um elemento flutuado sempre "pertencerá" ao seu container que tenha layout. Elementos subsequentes devem respeitar o layout do container, mas não o do elemento flutuado.

Isto, e a expansão do bloco de conteúdo feita pelo IE6 para conter seu conteúdo (o"expandir para conter "), pode ser visto como um aspecto da regra "determinado pelos limites do retângulo do elemento container".

Pior ainda: clear não afeta um float fora do container 'clareado'. Layout com Float baseados neste bug do IE não funcionam em navegadores standards sem passar por uma total modificação.

A característica de auto conter para floats do IE, que em alguns casos é inevitável, pode ser conseguida em outros navegadores, ver: "Semelhanças com as especificações para CSS" para maiores informações.

Elementos próximos a floats

Quando um bloco segue um elemento float deveria - como bloco que é - ignorar o float e o seu conteúdo deslocado pelo float: um texto contido em um elemento nível de bloco posicionado próximo a um float à esquerda deveria fluir à direita do float e então ( caso seja mais alto que o float) continuar abaixo do float. Contudo, se o bloco tem layout , digamos que por alguma razão foi definida para ele uma largura, o bloco como um todo será deslocado pelo float como se ele mesmo fosse um float e assim o texto nele contido permanecerá à direita sem se deslocar por baixo do float. Uma largura expressa em porcentagem para um bloco, será calculada com base no espaço disponível ao lado do float no IE5 e com base na largura total do elemento pai no IE6. Assim, no IE6, uma declaração width: 100% não será interpretada como a largura total disponível ao lado do float, ocasionando problemas, por não "encaixe" do blocos no espaço disponível.

Páginas de testes para casos de blocos adjacentes a floats:

De modo similar a isto, atualmente, elementos posicionados relativamente e próximos a floats deveriam tomar como base os limites do padding do elemento pai (ou seja, left: 0; em um elemento posicionado relativamente o colocaria no topo do box que o precede e estivesse float à esquerda.) No IE6, a declaração left: value; toma para base de posicionamento a margem direita do float, causando um desalinhamento horizontal igual a largura total do float (uma solução para isto seria declarar alternativamente uma margin-left, mas cuidado com as inconsistências ao usar valores percentuais).Similarities with the CSS specs

De acordo com as especificações floats entrelaçam com boxes que lhes sucedem. Isto não pode ser conseguido com dois retângulos que não se interceptam.

Se o autor pretende um comportamento semelhante ao do IE então a questão se resume a saber como fazer com que browsers com comportaamento standard comportem-se de modo a abrir espaço para floats antecedentes. Nós fornecemos opções para estabelecer um novo bloco de contexto próximo aos floats na seção “Similarities with the CSS specs”.

ao (re-)visitarmos a página que trata do bug no IE6:

veremos que o texto dentro do box layout quando logo abaixo do float não mais é afetado pelo deslocamento de 3px, porque a partir dali o float deixa de influenciar o texto, contudo ao longo da altura correspondente a área do float, todo o layout sofre um deslocamento de 3px. Como uma armadura, layout protege o conteudo de ser afetado, mas a força do deslocamento acaba por deslocar toda a armadura.

Ver a seção “” para maiores informações.

Listas

Listas são afetadas quando layout é aplicado tanto a lista em si (ol, ul) como aos elementos da lista (li). Reações diferentes ocorrem em diferentes versões do IE. O efeito mais evidente aparece nos marcadores de listas (listas personalizadas onde os marcadores não são necessários, não apresentam problemas). Provavelmente os marcadores foram criados com a finalidade de internamente adicionar alguns elementos a serem “agregados” aos elementos de listas (usualmente como um apêndice ao item da lista) e se mostram bastante instáveis. Lamentavelmente, por serem objetos “internos”, os marcadores não podem ser acessados para uma tentativa de correção de um comportamento errado.

Os efeitos mais evidentes são:

  • Quando layout é aplicado a uma lista ocorre o desaparecimento dos marcadores ou seu incorreto posicionamento.

Em alguns casos pode-se resolver o problema alterando as margens do elemento lista. Isto parece ser consequência do fato de que elementos layout tendem a seccionar elementos internos colocados como apêndice.

Um problema a mais (em listas ordenadas) é que qualquer elemento de lista com layout apresenta seu contador próprio. Considere uma lista ordenada com cinco itens onde somente o item três tem layout. Você veria assim:

1... 2... 1... 4... 5...

E para este caso, ainda ocorre que quando um item da lista com layout é apresentado em múltiplas linhas o marcador do item alinha-se verticalmente na parte inferior do item (e não no topo como esperado).

Alguns destes problemas não podem ser evitados, assim, quando os marcadores não forem dispensáveis é melhor não dar layout para listas e itens de listas. Caso seja necessário definir uma dimensão, será melhor definir para outro elemento: por exemplo; a largura poderá ser definida para uma div externa servindo como container para a lista e a altura poderá ser aplicada ao conteúdo de cada um dos itens da lista.

Outro problema comum com listas no IE ocorre quando o conteúdo de qualquer item li da lista é uma âncora com display: block. Nestes casos o espaço em branco entre os itens da lista não será ignorado e em consequência renderizado como se fosse uma linha extra entre cada item li. Um dos métodos para corrigir este problema consiste em dar layout para as âncoras. Este procedimento tem como vantagem adicional o fato de tornar clicável toda a área retangular da âncora.

Tabelas

Um elemento table sempre tem layout, sempre se comporta como um objeto com largura definida. No IE6, table-layout: fixed usualmente equivale a uma tabela com largura igual a 100%, e todos os problemas que isto acarreta (erros ao computar base para cálculos). A título de notas adicionais consulte este documento para mais considerações sobre este problema no IE5.5 e noIE6 em “modo quirks”.

Elementos posicionados relativamente

Notar que a definição position: relative não ativa hasLayout, o que resulta em alguns erros de renderização, normalmente causando desaparecimento ou perda de conteúdos. Tais inconsistências podem ocorrer quando do recarregamento da página, do redimensionamento da janela do navegador e quando acionamos uma rolagem da tela. A definição para position: relative faz com que o IE posicione corretamente o elemento, mas parece que ele se esquece de proceder um “reposicionamento” para os elementos filhos (procedimento adotado por um elemento layout quando ocorre um evento qualquer que requeira reposicionamento).

os links acima descrevem problemas relacionados. Como uma regra de bolso, nunca posicione um elemento relativamente sem ativar layout para ele. Adicionalmente devemos verificar se o elemento pai também precisa ter layout ativado e/ou position: relative, isto é fundamental quando floats estão envolvidos e são afetados.

Elementos posicionados absolutamente:
Bloco de conteúdo, qual bloco?

É fundamental entender o conceito CSS de bloco de conteúdo pois é dele que virá a resposta para a origem do posicionamento absoluto (a.p.) bem como a base para cálculos de medidas expressas em percentagem.

Para elementos a.p. o bloco de conteúdo é o ancestral mais próximo que tenha sido posicionado. Se não existir tal ancestral, será considerado o elemento de conteúdo inicial, ou seja o html.

Normalmente, nós definimos um bloco de conteúdo via position: relative. Isto permite que elementos a.p. se posicionem e tenham a base de cálculos para suas medidas independentemente do fluxo dos elementos no código; permitindo assim cumprir critérios de acessibilidade colocando os “conteúdos em primeiro” ou ainda tornar as coisas mais fáceis em layouts complexos baseados em floats.

Este conceito de design é questionado pelo IE: um elemento posicionado absolutamente tem suas coordenadas interpretadas corretamente somente quando o bloco de conteúdo tem layout e caso sua largura seja expressa em porcentagem a referência de cálculo será ao ancestral errado. Aqui, o IE5 e o IE6 comportam-se de modo diferente, mas ambos são problemáticos. O IE7b2 apresenta um comportamento mais consistente, mas ainda incorreto em alguns casos. Sempre que possível procure se limitar aos casos em que o bloco de conteúdo tenha layout e seja elemento pai de blocos posicionados absolutamente (isto é, assegure-se de que não hajam outros ancentrais entre o container e o bloco posicionado absolutamente)

Suponha um elemento pai não–layout posicionado relativamente — é urgente dar layout para este elemento para fazer funcionar a origem tomada para posicionamento:

Suponha que um elemento pai não posicionado tenha que ter uma dimensão e o design baseia-se em larguras expressas em percentagens. — podemos abandonar esta idéia devido a falta de suporte pelo navegador.

Filtro

Os filtros proprietários da MS são aplicáveis somente a elementos layout. Tais filtros tem suas inconsistências próprias.

Reajuste dos elementos renderizados

Uma vez que todos os elementos do documento tenham sido renderizados e ocorra uma transição provocada por uma declaração a:hover (por exemplo; uma mudança no background do link) o IE reajusta o layout do bloco de conteúdo. Em alguns casos, quando ocorre o evento hover, os elementos da página são colocados em uma nova posição porque agora o IE reconhece todas as dimensões ao contrário do que ocorreu na primeira renderização quando as dimensões seguiram a regra expandir para conter. Isto poderá causar uma desconfiguração quando ocorre o evento hover.

Os bugs relacionados ao reajuste torna problemático o uso de percentages para margens e paddings em layouts líquidos.

Origem para background

A propriedade MS, hasLayout afeta tamanho e posicionamento do background. Por exemplo, de acordo com as especificações CSS , background-position: 0 0 deveria tomar como referência “os limites do padding” definido para o elemento. No IE/Win a referência é considerada “os limites da borda ” quando hasLayout = false, e “os limites do padding edge” quando hasLayout=true:

Sobreposição de margens

A propriedade MS, hasLayout afeta a sobreposição de margens entre um box e seus descendentes. De acordo com as especificações a margem superior de um box para o qual não tenha sido definido nem padding superior nem border superior deve se sobrepor à margem superior do elemento filho nível de bloco que lhe segue no fluxo do documento:

No IE/Win isto nunca acontece quando trata-se de box que tem layout: parece que layout impede que as margens do elemento filho ultrapassem o seu bloco de conteúdo. Além disso, quando hasLayout é verdadeiro tanto o bloco de conteúdo quanto o bloco filho são afetados por cálculos errôneos para margens:

Links nível de bloco

hasLayout afeta a região clicável de uma âncora nível bloco. Usualmente com hasLayout = false somente a área coberta pelo texto é sensível ao clique. Com hasLayout = true toda a área do bloco é sensível. O mesmo é válido para qualquer elemento nível de bloco ao qual tenha sido atribuido onclick/onmouseover como disparador de evento.

Navegação pela página via teclado: uma odisséia

Quando o teclado é usado para navegar dentro de uma página a ação de pressionar a tecla tab logo após ter sido ativada uma âncora, não leva o foco para a âncora que se segue no documento:

A ação em tab levará — e não na maioria dos casos, erroneamente — o usuário para a primeira âncora existente dentro do ancestral mais próximo do foco atual e que tenha layout (se este ancestral for uma table, div, span e alguns outros elementos).

Encolher para conter

Algumas propriedades quando aplicadas a elementos com declaração width: auto fazem com que a largura do elemento seja calculada com um algorítmo encolher-conter. Exemplos de tais propriedades são float: left|right, position: absolute|fixed, display: table|table-cell|inline-block|inline-table.

Isto acontece no IE/Win, limitado às propriedades suportadas. Contudo quando o elemento que deveria encolher para conter, contém um elemento nível de bloco ao qual foi dado layout, na maioria dos casos acontece que este elemento filho se expande para ocupar toda a largura disponível independentemente do seu próprio conteúdo e assim anulam o efeito encolher para conter do seu elemento pai.

Exemplo:
Um menu de navegação vertical construido com um elemento ul flutuado, não sofre o efeito encolher para conter porque a declaração para os links a {display: block; zoom: 1;} foi necessária para anular o bug do espaçamento entre os itens da lista e também para expandir a área clicável.

O efeito encolher para conter permanece somente se o elemento filho com layout tem uma largura definida ou se tem o efeito naturalmente devido a uma propriedade que lhe foi aplicada, tal como a propriedade float.

Recorte além das fronteiras

Geralmente, quando uma caixa contém uma estrutura mais complexa tal como conteúdo ultrapassando os seus limites, será necessário dar layout a este container com a finalidade de evitar problemas de renderização. Isto acaba por gerar um dilema com relação às fronteiras da caixa, pois quando um elemento nível de bloco ganha layout ele transforma-se em uma caixa auto enclausurada.

Caixas de conteúdo aninhadas, quando movidas para fora das fronteiras de tais elementos (através do uso de margens negativas por exemplo) têm seus conteúdos recortados.

Recorte em blocos com margem negativa para containers com hasLayout

As porções recortadas podem ser recuperadas dando-se layout para as caixas de conteúdo e adicionalmente a declaração position: relative também é necessária para servir o IE 6. Para o IE 7 a declaração position: relative não é mais necessária.

Empilhamento, camadas, e layout

Parece haver duas ordens de empillhamento e disposição em camadas no IE/Win:

  • Uma é a (pseudo) tentativa de implementar o modelo css: Effect of z-index value to RP and AP blocks
  • A outra é a ordem de empilhamento criada por “hasLayout” e seu irmão gêmeo o comportamento “contenteditable”. Como foi mostrado no exemplo para posicionamento relativo quando elementos nao tem layout o empilhamento se processa de uma maneira que deixaria confuso até o mágico Harry Houdini.

Ambos os modelos de empilhamento, embora incompatíveis, são residentes na engine do IE. Uma regra de bolso: Ao proceder um debug faça uma verificação dos dois conceitos de empilhamento. Com frequência vemos problemas com drop down menu tanto mais simples como mais complexos, onde a ordem de empilhamento, de posicionamento e de floating pode conduzir a resultados catastróficos e onde a solução pode estar em atribuir z-index para posicionamento do layout, contudo, esteja atento pois cada caso é diferente.

Contenteditable – o fiasco

O atributo contenteditable=true, quando definido em uma tag HTML tal como <body contenteditable=true> permite a livre edição, a movimentação e o redimensionamento de um elemento e de seus elementos layout filhos. Agora tente isto com floats ou layout de listas ordenadas.

Com a finalidade de permitir a manipulação de elementos (editar), “contenteditable” e “hasLayout” criaram uma uma ordenação de empilhamento separada para aqueles elementos que fazem retornar true para hasLayout.

A plataforma de edição (Documento removido da MSDN) 2) herda o conceito de layout e as evidências apontam para creditar à contenteditable a razão para a interpretação errônea de layout (uma vez que as aplicações que integram a edição na engine do IE forçam uma retro-compatibilidade para o conceito de layout).

Semelhanças com as especificações CSS

Seu projeto desenhado para o MSIE está quebrando em outros navegadores? Não há necessidade de deixar que isto aconteça, você sabe disto! Qualquer navegador decente é capaz de tratar corretamente projetos desenvolvidos para o MSIE se você souber serví-los convenientemente — e projetar com CSS válido.

Valendo-se das sutis semelhanças entre hasLayout e o que estabelece o “new block formatting context” nos proporciona algumas maneiras de reproduzir os efeitos de hasLayout para “containment of floats” e para o comportamento de “elements next to a floated element” em navegadores complacentes com as standards.

Modo quirks

Consultar o nosso capítulo para modo quirks para informações detalhadas a respeito desde modo de renderização.

Layout — conclusão

O conceito de layout como um todo é incompatível com os conceitos CSS para o modelo de formatação visual, particularmente os conceitos de container, fluxo, floats, posicionamento e disposição da apresentação.

Isto conduz o IE/Win a violações das especificações CSS devido a presença ou ausência de layout para os elementos contidos na página..

Tendo layout — componente de outra engine?

O modelo de objeto interno do Explorer aparenta ser um híbrido de modelo de documento e de seu tradicional modelo de aplicação. Menciono isto por ser importante para o entendimento de como uma página é renderizada no Explorer. A chave para trocar de um modelo de documento para um modelo de aplicação consiste em “dar layout” ao elemento.

(Dean Edwards)

Algumas vezes é impossível encontrar uma interpretação para um comportamento: dependendo do status de hasLayout, uma ou duas engines de renderização são usadas, cada uma delas com seus quirks e bugs.

O absurdo dos bugs

Bugs em software são resultado de erros humanos e falhas na busca da perfeição e na lógica durante o processo de criação. É um defeito humano fundamental para o qual ainda não foi descoberta uma cura.
Qualquer tentativa de correção de bugs em software, outra que não seja a de recomeçar tudo do zero, inevitavelmente acabará por criar mais e mais bugs complexos causados pelos mesmo defeito humano.
Todo software que depende de outro software — incluindo Sistemas Operacionais (é claro!), será também dependente de seus bugs. Assim, estaremos diante de uma cascata de bugs vindas de todos os software envolvidos o que torna a idéia de encontrar um software livre de bugs um completo absurdo.

(Molly ‚the cat‛)

Editores:
Holly Bergevin
Ingo Chao
Bruno Fassino
John Gallant
Georg Sørtun
Philippe Wittenbergh
Agradecimentos especiais pelo suporte dado a este projeto para:
Dean Edwards, Molly ‚the cat‛ e David Laakso e Corina Rudel
Traduções:
Português do Brasil por Maurício Samy Silva
Búlgaro por Yordan Stoev
Chinês por old9
Alemão por Corina Rudel
Em andamento : Francês.
Traduções são bem-vindas. Entre em contato conosco.
Italiano por Grabiele Romanato
Russo por DreamwinD
Discuta este artigo:
dean.edwards.name/weblog/
Contato com o autor do original:
spam.layout@satzansatz.de
Direitos autorais :
Este trabalho foi publicado segundo regras da Creative Commons license.

Tabela de conteúdos

  1. Introdução
  2. hasLayout — Definição
  3. Nomenclatura
  4. Com que estaremos envolvido
  5. De onde veio layout
  6. Elementos que tem layout por default
  7. Propriedades
  8. Notas sobre elementos inline
  9. Redefinindo hasLayout
  10. A propriedade script de hasLayout
  11. hacks CSS
  12. Gerenciamento de hack
  13. Uma nota sobre IE Mac.
  14. Documentação MSDN
  15. Interpretação
  16. Uma revisão das consequências
  17. Contenteditable–o fiasco
  18. Semelhanças com as especificações CSS
  19. Modo quirks
  20. Layout — conclusão
  21. Tendo layout — componente de outra engine?
  22. O absurdo dos bugs
  1. O documento original foi modificado na MSDN. Aqui nos referenciamos a uma versão que está disponível em Arquivos da Internet (Controlling Presentation with Measurement and Location Properties).
  2. O documento original foi retirado da MSDN e está disponível em Arquivos da Internet (The MSHTML Editing Platform in Internet Explorer 5.5).

Meu nome é Maurício Samy Silva e eu sou conhecido na Web como Maujor.

Mantenho o Site do Maujor hospedado em: maujor.com e meu e-mail de contato é maujorcss[ARROBA]maujor [PT]com.

Minha residência é em:

Copacabana - Rio de Janeiro,, RJ - - Brasil

Traduzido em: 2005-10-27
Atualizado em: 2006-10-23