A HaRd challenge - styling an HR element
One of the web sites I’m currently working on has a lot of line dividers, and they had been added somewhat inconsistently. Therefore, I decided to go the semantic route and throw out all div and p elements, and replace them with one single class-free hr. Oh man, did I open up a can of worms…
How to basically style a hr
Let me first show you how to basically style a hr element with CSS:
hr{
width: 100px;
height: 4px;
/* color is for IE */
color: #2F433B;
/* background is for all other web browsers */
background: #2F433B;
/* border: 0 removes the shading in most web browsers */
border: 0;
/* A zero-margin aligns it in most web browsers */
margin: 0;
/* Aligns it in IE */
text-align: left;
}
Ok, so far so good. Let’s get to the real problem.
IE and its damn margins!
Just as with certain form elements, IE is a master (or bitch) at applying space, margin and padding that can’t be removed with normal CSS; something which works for all other web browsers on all platforms:
margin: 0;
padding: 0;
The challenging thing here is that it seems that top and bottom margins just can’t be removed in IE, no matter how hard you try. And if you think float will help here, think again. All it did was, ironically, centering the content instead of aligning it to the left-hand side…
One way to go here is to keep the hr element for semantic and CSS-less reasons, and then wrap it in a div that hides the hr and creates a line effect with a border or background color:
<div class="hr"><hr></div>
div.hr{
height: 4px;
background: #ccc;
overflow: hidden;
}
div.hr hr{
display: none;
}
But this time, I decided not to cave and go down that road; I’m not backing down! Determined to “win”, I continued. In the web site context I was working on, I needed to have the line with a top and bottom margin of 20 pixels, so I thought (read: hoped) that having a margin wouldn’t cause any problem in IE. How wrong I were…
Apparently, if you do want a margin, just setting the desired value will, in IE, not result in what you expected (either). The basic code for a 20 pixel top and bottom margin would be:
margin: 20px 0;
However, in IE there’s two problems. For some annoying reason I can’t understand, it adds 7 pixels (even number, right?) to the top and bottom margin, and margin-collapsing also fails miserably. So, to make it work, I had to give IE a special top and bottom margin to get the wanted 20 pixel margin:
margin: 3px 0 13px;
Right about now, you probably say: eh, what?! Let me guide you: the bottom margin part is the easy one. It has a 13 pixel margin plus the magical 7 pixels IE adds, which together equals in 20 pixels. Great!
The 3 pixel top margin is first 20 pixels minus the IE-added 7 pixels, which would then be 13 pixels. However, since it fails to collapse the margin together with the preceding element’s bottom margin, it instead adds them together. Luckily for me, all the places where the line divider is used is following either a paragraph or a list with a bottom margin of 10 pixels, so you need to deduct that as well from the top margin, which leaves us with just a mere 3 pixel top margin in the CSS for IE, but with a result of 20 pixels…
The calculation:
20 (desired top margin) - 7 (IE-added-margin) - 10 (preceding element’s bottom margin) = margin-top: 3px; (in reality, 20 pixels).
The challenge to you
Conclusively, I did win over IE in this case, since a margin was needed. All I had to do was to find the magic IE formula. The challenge, though, is:
How do you use hr elements in IE with no margins whatsoever, and without using any container element?


