Esse texto mostra os erros mais evidentes na construção de páginas de websites. O objetivo então é desenvolver documentos compatíveis com os diversos browser (navegadores) existentes no mercado. Na prática, o que acontece é que alguns navegadores mais antigos não têem suporte para linguagens mais recentes e simplesmente não lêem parte dos códigos. Na maioria dos casos o equivoco também parte por má interpretação ou renderização do navegador, o tal do bug. Apesar de ultrapassado, o Internet Explorer 6, ainda é um dos navegadores mais usados. Isso porque a maioria dos usuários não costuma atualizar os sistemas ou navegadores com frequência e, diferentemente do Firefox, o Internet Explorer não tem atualização automática. Na prática, o usuário instala o windows xp e mantém o navegador padrão, o nosso amigo Intenet Explorer 6.
Vamos ao que interessa:
1º - Zerando o seu trabalho.
Ao editar estilos, é comum aparecer diferenças de um mesmo documento se exibidos em diferentes navegadores. Como exemplo, os formulários (<form>) possuem alguns valores embutidos no Internet Explorer, já no Firefox não. Por isso, a primeira coisa para se fazer quando inicia-se um trabalho desse tipo é "zerar" esses valores padrões dos navegadores:
* {
margin:0;
padding:0;
border:0;
}
O seletor asterisco, quando sozinho, seleciona todas as tags do documento. Ou seja o código acima limpa os valores que são encontrados em alguns navegadores, como as margens de formulários ou as bordas das imagens.
a) Outros usos dos seletores:
Recapitulando alguns possíveis usos dos seletores:
.minhaDiv {} /* elemento class='minhaDiv' */
#minhaDiv {} /* elemento id='minhaDiv' */
#minhaDiv.conteudo {} /* elemento id='minhaDiv' e class='conteudo' */
div#content table#tabela a{} /* todos os links da table#tabela dentro da div#content */
body div#content div.info * {} /* o asterico classifica tudo dentro do body > div#content > div#info */
b) O nível hirarquíco dos seletores:
Exemplo:
<div id="pai">
<div id="filho" class="filho">
</div>
</div>
Estilos para determinar a características do filho:
.filho{}; < #filho{}; < #filho.filho{}; < #pai #filho{}; < body #pai #filho{};
#filho {}; vale menos do que um estilo mais epecifico como body div#pai div#filho.filho {};, por exemplo.
Independentemente da ordem no CSS ou da ordem de processamento do browser.
Se existir mais de um estilo ligado ao mesmo id (ou class), vale a última a ser processada pelo browser,
seguindo a seguinte ordem:
- 1ª) inline: é mais forte, pois está dentro da tag e, certamente, será a última a ser processada pelo navegador, ex: <p style="color:#ccc">
- 2ª) incorporada, linkada ou importada: Todos empatados, pois depende de uma váriavel: a que vier por último dentro da tag <head> será a última a ser processada pelo código-fonte do navegador, veja no exemplo:
<head>
<!-- incorporada: -->
<style type="text/css"><!-- .texto {color:#ccc;} --></style>
<!-- linkada -->
<link href="arquivo.css" rel="stylesheet" type="text/css" />
</head>
O estilo .texto que estiver dentro do arquivo.css ganhará daquele que está incorporado logo acima.
Porém, se nele existir um css importado do tipo @import url(), ai dependerá se o import está antes ou depois do .texto do primeiro css.
Uma questão de orndenação pura e simples.
2º - Hacks, solucionar problemas
Esse não é exatamente um erro, mas uma solução. Os hacks são dicas de como lidar com navegadores diferentes dentro de um mesmo documento CSS. São maneiras de postar propriedadedes CSS de forma específica por navegador. O ideal é que nunca usemos o tal do hack. Sempre há uma solução para se livrar de problemas. Mas, por algum motivo resolvi postar:
#suaDiv {
width:100%; /* TODOS / GERAL (VALERÁ PRO F.F) */
*width:10%; /* APENAS IE6 e IE7 (VALERÁ PRO IE7) */
_width:50%; /* APENAS IE6 (VALERÁ PRO IE6) */
}
No exemplo acima, a largura de sua div será de 100%, mas a próxima linha indica que ela será de 10%. Acontece que somente o IE é capaz de interpretar uma propriedade com o hack asterisco. Já a próxima linha indica a mesma altura agora com 50%. Dessa vez, somente o IE 6 irá interpretar o hack underline antes da propriedade.
Existem outros métodos de hack, mas esse é o mais usual.
3º - Centralizar containers
Existem 2 metodos para centralizar uma div.
Os mais usado é também o mais simples:
#suaDiv {
margin: 0 auto 0 auto;
width: 600px; /*largura*/
}
Dessa forma, a div ficará centralizada horizontalmente. Mas se precisar centralizar sua div de forma vertical, o metodo acima não atende. Portanto, é necessário outra solução:
#suaDiv {
position:absolute;
top:50%;
left:50%;
margin-left:-300px; /* negativo da metade da largura */
margin-top:-200px; /* negativo da metade da altura */
border-style:none;
width: 600px; /*largura */
height: 400px;
}
O que a solução propõe é declarar que a sua div será forçada (position:absolute) a ficar na metade da largura e da altura do navegador. (top:50%; left:50%). Mas como o registro das divs ficam na quina superior a esquerda, é necessário retroceder exatamente a metade dos valores de largura e da altura nos planos x e y, respectivamente.
4º - Sobre alturas
Quando inserimos textos dentro de uma div, percebemos que a altura cresce conforme o conteúdo o "empurra" para baixo. Isso é chamado de tamanho fluído de um container. Mas se for necessário fixar um tamanho, basta usar a propriedade overflow:hidden:
#suaDiv {
width:200px;
overflow:hidden;
}
pronto, até mesmo o IE6 aceita.
Não importa o que existir dentro da div (pode ser imagem, texto, flash..), o conteúdo será cortado afim de respeitar o tamanho ali declarado.
Esse metodo overflow:hidden; também vale para imagens, caso você queira redimensionar uma imagem via CSS:
img {
height:200px;
width:auto;
overflow:hidden;
}
Da mesma forma, em alguns casos é necessário declarar que a div tenha uma altura mínima. Depois desse tamnho mínimo, ela voltará a ser fluída. A propriedade para isso é o min-height:
#suaDiv {
min-height:500px;
}
Novamente, o IE6 não respeitará essa propriedade. Contudo também é possível solucionar o problema:
#suaDiv {
min-height:500px;
height:auto !important;
height:500px;
}
5º - Sobre Larguras
Como destacado acima, as divs tem a altura fluída, cresce conforme o conteúdo. As vezes é necessário aplicar o mesmo comportamento para a largura de uma div. Mas por default (padrão), na maioria dos casos os navegadores exibem a largura de uma div em 100%.
Quando a div flutua ela já se torna fluída horizontalmente por natureza:
#suaDiv {
float:left;
}
O oposto também é possível, ou seja, se você deseja declarar uma largura máxima, basta usar novamente o overflow-x:hidden.
Acontece que muitas vezes o conteúdo é cortado sem piedade. Palavras extensas são cortadas (como um link gigantesco, por exemplo), para isso existe uma propriedade que força a quebra de linha:
#suaDiv {
width:200px;
overflow-x: hidden; /* forçar respeitar o limite da largura */
word-wrap: break-word; /* quebrar textos sem espaçamentos */
white-space: normal; /* importante para a quebra de linha */
}
Outra possibilidade é continuar mantendo a div fluída horizontalmente até atingir uma largura máxima. Ou seja, ao inves de definir uma largura fixa para a div, deixamos ela fluir até um limite máximo. Para isso usaremos a propriedade max-width. Novamente com fix para navegadores antigos, veja a solução abaixo:
#suaDiv {
float:left; /* deixar a largura fluída */
max-width:360px;
width: expression(this.width > 360 ? 360: true);
}
a) Larguras em list-menus (menu em lista), um caso a parte.
É de praxe usarmos listas <ul> e <li> para criar menus. Logo, um menu horizontal seria algo mais ou menos assim:
<ul>
<li><a href="#">link 1</a></li>
<li><a href="#">link 2</a></li>
<li><a href="#">link 3</a></li>
</ul>
O css:
ul li a {
float:left;
width:150px;
height:30px;
}
Simples. Exceto para o IE6.
Um bug conhecido como "Step-down" ("escada" ou "escadinha" como já encontrei na em alguns blogs).
Para resolver isso, basta retroceder um passo do seu seletor (voltando para o <li>) e colocar a propriedade display:inline:
ul li {
display:inline;
}
ul li a {
float:left;
width:150px;
height:30px;
}
As escadas sumiram.
Se quiser deixar a largura dos botões flexíveis (crescendo de acordo com o conteúdo ou o texto), basta usar a largura com o valor auto, veja:
ul li {
display:inline;
}
ul li a {
float:left;
width:auto;
height:30px;
}
Outra maneira menos elegante de acabar com "Stepdown" é passar o float do <li> para o <ul>. Apesar de preferir o primeiro método vou postar esse também (nunca se sabe):
ul li {
float:left;
}
ul li a {
width:150px;
height:30px;
}
Mas dessa vez, o valor de height não é interpretado por nenhum navegador.
A propriedade display:block; resolve isso:
ul li {
float:left;
}
ul li a {
width:150px;
height:30px;
display:block;
}
Para esse segundo fix do Stepdown existe outro bug do IE6 caso queira usar larguras flexiveis nos botões com width:auto
Não há um motivo muito claro. Todaiva já existe uma solução acompanhada de um hack:
ul li {
float:left;
}
ul li a {
width:auto; /* para ff */
_width:1px; /* bug ie6 para width:auto */
_white-space: nowrap; /* para forçar não quebrar a palavra (caso tenha espaço) */
}
Pronto!
6º - Margin dobrado no Internet Explorer 6.
Se numa div flutuante também existir a propriedade margin, é bem possível que o seu ie6 interprete de forma errada o valor da sua margem.
É um bug bem comum, o ie6 dobrou o margin. Para resolver isso basta acrescentar o display:inline:
#suaDiv {
float:left; /* ou right */
display:inline;
}
7º - Uso de imagens transparentes
Outro erro comum do Internet Explorer 6 está relacionado às imagens transparentes. Se a imagem do seu documento for do formato PNG transparente, o ie6 irá exibi-la opaca.
Para evitar esse tipo de coisa, basta usar imagens do formato gif transparente. Isso já é garantia que todos os navegadores irão exibi-las corretamente.
Mas nem sempre os gifs transparente suprem todas necessidades. O gif transparente é incapaz de exibir gradações de cores em alpha.
O único formato transparente capaz disso é o png-24. Então, para corrigir o problema do png no ie6 é se apoiando numa solução em javascript:
deixe-o junto de seu html;
e filnamente chame o javascript no cabeçalho (<head>) do seu html que possui um png transparente:
<!--[if lt IE 7.]>
<script defer type="text/javascript" src="pngfix.js"></script>
<![endif]-->
Mesmo se usar a solução acima para exibição, as mesmas imagens png's transparente não irão ser exibidas corretamente se usa-las dentro de um documento CSS, como no exemplo:
#suaDiv {
background-image:url(suaImagem.png);
}
para isso, há 2 outras soluções. Cada uma com sua peculiaridade:
- iepngfix funciona muito bem. Mas links ficam desabilitados dentro de div's absolutes (position:absolute) que usam o iepngfix.
- fx-iepngfix também funciona muito bem. Mas as vezes não é possivel colocar margin-top em elemento dentro de div's que usam o fx-iepngfix. Nada que um padding-top não resolva.
Veja os dois metodos:
a) iepngfix
deixe-o junto de seu html;
e finalmente chame por todos os seletores (id's ou classes) que usam png de background dentro do cabeçalho (<head>) do seu html:
<!--[if lte IE 6]>
<style type="text/css">
#suaDiv, #suaOutraDiv {
behavior:url(iepngfix.htc)
}
</style>
<![endif]-->
b) fx-iepngfix
deixe-o junto de seu html;
e finalmente chame por todos os seletores (id's ou classes) que usam png de background dentro do cabeçalho (<head>) do seu html:
<!--[if lte IE 6]>
<style type="text/css">
#suaDiv, #suaOutraDiv {
behavior:url(fx-iepngfix.htc)
}
</style>
<![endif]-->
Faça a sua escolha.
8º - Displays tables não funcionam mesmo.
Com o surgimento do CSS2, os containers (div's) podem herdar características de tags HTML proveniente de tabelas, como o <table>, <tr> e <td>. Através dos comandos:
display:table;
display:table-row
display:table-cell;
Você achando que se livrou das tabelas, mas percebeu que em algum momento elas tinham utilidade. Afinal, qual a vantagem? Bem, um dos beneficios é a facilidade de controlar o posicionamento das div's sem a necessidade de usar float (float:left ou float:right).
Ao inves de taxamos um container (div) como fluante à esquerda ou flutuante à direita, podemos simplesmente classifica-las como celulas de tabelas:
<div style="display:table">
<div style="display:table-row">
<div style="display:table-cell">Esse container flutua à esquerda</div>
<div style="display:table-cell">Esse container flutua à direita</div>
</div>
</div>
Pra que usar divs/tabelas se podemos usar o float?
A diferença é que o comportamento das divs flutuantes são independentes, ou seja, a altura de uma não influencia em nada na altura da outra.
Usando display:table-cell, as divs passam a ter alturas comuns (como numa tabela).
Mas de que adianta usar divs/tabelas se o ie6 não lê CSS2?! Realmente é melhor esquecer as propriedades display:table, pois ela não é compatível com todos os navegadores.
Mesmo assim ainde é possível estabelecer paralelismo entre as alturas das divs usando "javascript":
<div id="container" style="width:428px; background-color:#ccc; display:table;">
<div id="esquerda" style="width:100px; background-color:#ff0; float:left;">
Menu lateral esquerdo
</div>
<div id="meio" style="width:200px; background-color:#fff; float:left;">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.<br />
Integer rutrum sodales convallis. Maecenas pellentesque convallis.<br />
Curabitur ornare arcu in justo egestas lacinia.<br />
Proin augue velit, ultrices rutrum iaculis sit amet, tempus a nisl.<br />
Aliquam erat volutpat. Sed est velit, dictum placerat dictum in.<br />
In quis lorem purus. Nam commodo euismod urna quis tincidunt.<br />
Donec interdum, risus vel convallis ultrices, tellus lectus placerat est.<br />
Et blandit neque ligula id augue. Aenean a auctor turpis. Sed at eros neque.<br />
Integer quis rhoncus odio. Praesent ac purus id est volutpat pharetra.<br />
Proin facilisis vehicula quam, vel congue diam cursus vel.<br />
Pellentesque metus quam, faucibus et bibendum vitae, rhoncus eu tellus.<br />
Nam vel elit sed sapien aliquam pharetra eget non erat. Nulla facilisi.<br />
Vestibulum accumsan diam iaculis massa pellentesque aliquam.<br />
Mauris tempus leo sit amet mi condimentum at rhoncus libero semper.
</div>
<div id="direita" style="width:100px; background-color:#0ff; float:right;">
Navegação direita
</div>
</div>
<script type="text/javascript" language="javascript">
<!--
function tamanho (){
obj_esq = document.getElementById('esquerda');
obj_pri = document.getElementById('meio');
obj_dir = document.getElementById('direita');
obj_container = document.getElementById('container');
altura_pri = parseInt(obj_container.offsetHeight) + 'px';
obj_esq.style.height = obj_dir.style.height = obj_pri.style.height = altura_pri;
}
tamanho();
//-->
</script>
postando esse código imediatamente antes do </body> você garante que as divs: "esquerda", "meio" e "direita" terão a mesma altura que a div "container". Ou seja, a div "container",que engloba as outras divs, certamente será a de maior tamanho. Logo o javascript aproveita disso e repassa o valor dela para as demais.
a) falando em diplays...
Outra propriedade muito útil dos displays, são os displays do tipo inline-block.
Como o próprio nome sugere, nada mais é do que a junção do inline com o block.
Sozinhos elas não resolvem muita coisa.
O display:inline consegue colocar os elementos em linha (como o float). Mas se aplicado em um link <a>, por exemplo, não interpretará padding-top ou uma altura height.
O display:block resolve esse problema, mas aí os elementos perdem o posicionamento linear.
"Fácil, só usar o display:inline-block". Sim, mas Internet Explorer não reconhece tal propriedade. Veja como resolver esse bug:
#suaDiv {
display : inline-block; /* FF+ */
*display : inline; zoom: 1; /* IE5.5+ */
}
Não sei muito bem o motivo desse fix funcionar tão bem, mas funciona. E isso é o que queremos. As vezes os fins justificam os meios.
9º - Centralizar conteúdo verticalmente.
Outro vantagem dos displays do tipo tabela está na possibilidade de centralizar verticalmente os conteudos dentro de uma div. A propriedade se baseia no mesmo conceito de como era feito com o atributo valign=middle da tag <td>, basta declarar:
#suaDiv {
display:table-cell;
vertical-align:middle;
}
Achamos o porque da existência do até então inútil vertical-align:middle. Porém o uso do display:table-cell não garante compatibilidade com o ie6 ja que se trata de uma propriedade do CSS2. E esse não tem jeito. O ideal é evita-lo.
O Existem dois meios para "alinhar" o conteúdo de uma div centralizado verticalmente.
A primeira (e nada elegante) é voltando ao velho padding-top para conseguir "alinhar" o conteúdo de forma vertical. (lembre-se que o valor do padding-top ou padding-bottom deve ser subtraído na altura)
<div style="height:160px; padding-top:140px;"><!-- altura total = 300px -->
Conteudo.
</div>
A segunda (e mais eficaz) é declarando um line-height com o mesmo valor da sua altura height. Em seguinda, use vertical-align:middle;
<div style="height:300px; line-height:300px; vertical-align:middle;">
Conteudo.
</div>
Os dois metodos funcionam em qualquer navegador. Porém, é preciso declarar uma altura. Ou seja, você não consegue ter uma div fluida que centralize verticalmente seu conteúdo. Esse caso dá muito pano pra manga. É preciso estudar projeto a projeto.
10º - Seletores de atributo
Outro ganho interessante oferecido pelo CSS2 nos leva ao próximo "erro". A possibilidade de usarmos seletores de atributos de tag's, como por exemplo:
input[type='submit'] {}
Dessa forma, podemos selecionar todas as tags input do tipo submit.
Mas o ie6 não lê CSS2. Sim, mas é possível desenvolver um javascript para selecionarmos atributos, como nesse mesmo exexplo do <input type="submit">:
<script type="text/javascript">
<!--
if(document.getElementsByTagName('input') != null ) {
for (i=0; i<document.getElementsByTagName('input').length; i++) { //todas tags input
//Tags input de atributo submit:
if(document.getElementsByTagName('input')[i].attributes['type'].value=="submit"){
document.getElementsByTagName('input')[i].className="typeSubmit";
}
}
}
//-->
</script>
Colocando esse javascript imediatamente antes do final do body (</body>), você declara que todas os inputs submit terão a classe "typeButtons". Ou seja, ao invés de usarmos input[type='submit'] {}, basta usar: input.typeSubmit {}