Margens na tag HR: um caso resolvido
Publicado por Leandro Mello há 3 meses.
Basicamente, o tapa na cabeça que faz o IE se comportar direitinho é o
display: block. Depois dessa, você põe a margem que quiser no<hr />.
Sou dos que usa a tag <hr /> para dividir seções. É semanticamente mais coerente do que separar usando as próprias bordas dos divs, fica melhor quando se vê o HTML sem CSS, essas coisas que já se discute à beça por aí. Aprendi a apreciar sua utilidade.
Mas o fato é que é enjoado dar estilo a esta tag. Para cada browser devem-se editar atributos diferentes para se alcançar um mesmo efeito. Enfim, com algum jeitinho, deixa-se o <hr /> com a mesma cara em todos os browsers.
O que mata mesmo, o que deixa fóruns de cabelo em pé é a tal margem que fica em volta do <hr /> no IE. A margem no IE é teimosa, indestrutível, incontrolável, inestilizável. Por todo lugar que eu procurasse, as pessoas decidiam seguir com as margens mesmo, e os mais persistentes chegavam ao ponto de inserir o <hr /> num <div> para conseguir dar o estilo que quiserem. Ou seja, uns desistiam muito fácil, outros recorriam a medidas desesperadas para fazer a coisa de qualquer jeito.
Um dia encontrei dois posts que se aproximavam da solução. Sozinho, nenhum dos dois resolvia o caso. Mas juntando os dois funcionava! Fiz os testes e, de fato, misturando os dois raciocínios eu conseguia a medida que eu quisesse em qualquer browser que fosse — até zero. Mas, numa jogada um tanto infeliz, não salvei os posts nos favoritos, nem salvei o arquivo de testes. Uma resposta bastante procurada, e eu a perdi de bobeira...
Este artigo é sobre o meu caso: eu queria usar o <hr /> livre de divs sem sentido, e com margem zero; até no IE. E, sobretudo, o artigo é para deixar a resposta num lugar seguro e ao alcance de todos. Agora que eu lembrei a solução, não perco mais.
“Pescotapa”
Depois que perdi de vista os posts e as semanas se passaram, tudo o que eu lembrava é que o Internet Explorer precisava de um tapa na cabeça: era um atributo nada intuitivo e totalmente inesperado, que surpreendentemente o fazia acordar para a realidade. Basicamente, o tapa na cabeça que faz o IE se comportar direitinho é o display: block. Depois dessa, você põe a margem que quiser no <hr />.
Vai entender. O <hr /> já é um elemento em bloco. Tem toda a cara de elemento em bloco. Pula linha em cima, pula linha embaixo, não tem nada de inline. E é por isso que os fóruns tanto rodam atrás de uma solução: poucos suspeitariam que é necessário lembrar a ele que de fato é um bloco. Dizer display: block seria redundante e desnecessário. Mas o danado do IEca faz questão disso para se dar conta de que “ah, é, é verdade...”.
Como aconteceu comigo:
Vamos ao meu caso. Eu pretendia inserir umas tags <hr /> no site da fotógrafa Patricia Figueira, como experimento para implementação futura no próprio site e em nosso produto em desenvolvimento, o beonthe.net.
O primeiro passo foi inserir tags <hr /> nos espaços entre cabeçalho, conteúdo principal e rodapé. Vamos ao HTML:
<div id="header">
(conteúdo do cabeçalho)
</div>
<hr />
<div id="main_content">
(conteúdo principal)
</div>
<hr />
<div id="footer">
(conteúdo do rodapé)
</div>
E logo surgiu a linha cinza entre os divs. Ficou assim:
Safari: 
Opera: 
Firefox: 
Internet Explorer 7: 
Internet Explorer 6: 
(Ah, o IE...)
Linhas inseridas, eu queria que cada divisória tivesse as seguintes características:
- Quebrasse possíveis floats;
- Não ocupasse qualquer espaço vertical;
- Fosse invisível.
A primeira tarefa é simples. Na folha de estilos application.css, usamos:
hr {
clear: both;
}
Nota: Depois vi que, para limpar de fato os floats do div#main_content, foi necessário pôr os hr’s dentro do #main_content, em suas extremidades, e não adjacentes a ele. Mas isto é papo para toda uma outra discussão e, para efeito de ilustração, vou continuar exibindo os hr’s como se estivessem entre o #main_content e o #header.
Agora vem a segunda tarefa: limpar os espaços que a linha gera no IE. Mas, como dito antes e tantas vezes blogs afora, a margem do hr no IE é turrona, implacável, indelével, inoxidável. Tem gente tentando de tudo: margin: 0, padding: 0, line-height: 0, font-size: 0, até overflow: hidden. Zerar as margens até ajuda com os browsers que seguem os padrões, mas nada acaba com o espaçamento no IE.
Então, em nosso application.css, cuidemos dos browsers inteligentes para garantir que não haja margens:
hr {
clear: both;
margin: 0;
}
A explicação para as margens insistentes do IE é a seguinte: o IE renderiza o <hr /> com uma margem vertical de 7px a mais do que os outros browsers. Ou seja, se você escreve...
hr {
clear: both;
margin: 7px 0;
}
... Você tem num browser decente o esperado: 
E no IE, uma soma do que você inseriu mais a margem nativa: 
“Ora”, posso pensar, “Então é só escrever margens negativas para o IE”. Seria o intuitivo, mas o IE não trata de coisas como “o intuitivo”. Não funciona: o IE tira a margem superior, mas jamais elimina a margem inferior! Veja: 
O pulo do gato
Entra na nossa folha de estilos application.css o atributo display: block:
hr {
clear: both;
margin: 0;
display: block;
}
Este é o último atributo em que eu pensaria para eliminar margens. Não sei explicar por que dá certo. É contra-intuitivo. É redundante. É idiota. E mesmo assim (ou talvez por isso mesmo) faz o IE acordar.
Agora sim, podemos repensar a questão das margens negativas. Então corrigimos o application.css:
hr {
clear: both;
margin: -7px 0;
display: block;
}
E voilà! Finalmente, um <hr /> sem margens! 
Comentário condicional:
O problema de usar margens negativas é que os browsers inteligentes as interpretam como elas são — negativas:

Temos que definir um comportamento para cada tipo de browser.
O que eu costumo usar são comentários condicionais. Há quem diga que eles são maus, mas até agora só têm me ajudado.
Vamos ao <head> no HTML. Lá inserimos uma condição para o IE:
<!--[if IE]>
<link href="/stylesheets/application_ie.css" media="all" rel="stylesheet" type="text/css" />
<![endif]-->
Ela serve para chamar uma folha de estilo com regras específicas para o Internet Explorer: application_ie.css.
Nesta nova folha application_ie.css, aplicamos as margens negativas que tínhamos até então:
hr {
margin: -7px 0;
}
E pronto. Esta é a única regra que diferencia o <hr /> nos browsers inteligentes e no Internet Explorer. Agora podemos zerar as margens no nosso application.css:
hr {
clear: both;
margin: 0;
display: block;
}
E o resultado é: consenso! Nos browsers inteligentes:

... e no IE:

Acabamento
Resta a terceira tarefa, que é deixar invisíveis as linhas divisórias. Isso é fácil com visibility: hidden:
hr {
clear: both;
margin: 0;
display: block;
visibility: hidden;
}
O que vai fazer com que o <hr /> fique invisível, mas ainda ocupando o espaço que ocupava antes, de modo que fica uma lacuna de 2 pixels entre o cabeçalho e o conteúdo principal: 
Nota: Usar display: none não é útil neste caso porque cancela o atributo clear: both. E nós queremos que ele quebre os floats. Neste caso, é melhor ficar com visibility: hidden.
Nos browsers decentes, esta lacuna é devida à espessura da borda. Bordas de 1px em volta de um elemento com altura zero resultam em 2px de altura total. Um aributo de borda deve resolver:
hr {
clear: both;
margin: 0;
display: block;
visibility: hidden;
border: none;
}
A lacuna some no Safari e no Opera. Mas Firefox e IE precisam de mais uma forcinha. Lembre-os que a altura do elemento deve ser nula:
hr {
clear: both;
margin: 0;
display: block;
visibility: hidden;
border: none;
height: 0;
}
No Firefox resolve. Mas no IE a lacuna, em vez de sumir, fica reduzida a 1px (Ah, o IE...). Isso porque nele as bordas não são definidas pelo atributo border, mas pelo atributo color (já mencionei que o IE não trata de coisas como “o intuitivo”?). Como não dá para “zerar” a cor para sumir com a lacuna, o jeito é retocar as margens que deixamos no application_ie.css, contribuindo para as margens negativas com 1px em cima ou em baixo:
hr {
margin: -8px 0 -7px 0;
}
E eis o resultado final: 
Conclusão
Este foi o meu caso bem específico com a tag <hr />. Se você for uma das pessoas que se descabelavam por causa das margens teimosas no IE, saiba que há solução. Não é preciso desistir e adaptar seu precioso layout para se conformar com as margens, nem é preciso inserir a tag num <div> só para ela. Boas práticas já!
Espero ter contribuído para diminuir sua dor de cabeça. A resposta está agora aqui, para todo o mundo. E breve você a verá implementada no site da Patricia Figueira e no beonthe.net. Mas se este post não resolver o seu caso específico, escreva. Vamos juntos pensar em soluções para dominar o <hr /> — e, quem sabe, só quem sabe, o Internet Explorer.





O que você achou? Coloque seus comentários e sugestões abaixo!
Acompanhe o RSS dessa página.
Comentários (3 até o momento)
Eduardo Costa disse aproximadamente 4 horas depois:
Leonardo Faria disse aproximadamente 6 horas depois:
Bruno disse 3 dias depois: