Main Menu
Home
Forums
CSS
JavaScript
HTML & XML
Web Design
Web Dev
Downloads
Industry and Site News
Security Alerts
Web Dev Reference
Search
Who's Online
Popular
Syndicate
CSS Style for HR with a Background Image PDF Print E-mail
Thursday, 01 December 2005

Using CSS to style an HR element with a background image can be frustrating, if you want it work in both Firefox and Internet Explorer and if you want to use an HR element rather than a DIV element, as is common practice. Many current solutions to this problem work, but not in all situations. I have yet another solution to add to the mix. Hopefully, it will work for you if something else does not.

Table of Contents

  1. The Challenge Has Been Met
  2. What is Wrong with Using a DIV Element?
  3. Mozilla Supports a Pure CSS Solution
  4. The Internet Explorer Ugly Gray Border Problem
  5. Existing IE Solutions
  6. My Solution: The CSS Clip Property

The Challenge Has Been Met

Creating a dotted border seems to be the most common reason to use a background image for an HR element. Many people do not like the native CSS dotted border, using the border property set to the value dotted. In this tutorial, I use a dotted horizontal rule for my examples.

Example

Here is a working example. Yes, believe it, the dotted line below is an HR element styled with CSS that works in both Internet Explorer and Firefox. It is not a DIV element with a repeating img background. The dotted line below is an actual HR element.


Here is the code used to create the HR element above.

<style type="text/css">
hr.dotted
{  background: url(/images/articles/CSS_Style_for_HR_with_a_Background_Image/line.gif) no-repeat top center;
  filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/images/articles/CSS_Style_for_HR_with_a_Background_Image/line.gif');
  width: 1px;
  height: 1px;
  border: 0;
}
* > hr.dotted
{  width: 100%;
  height: 10px;
 
}
</style>
<hr class="dotted">

What is Wrong with Using a DIV Element?

I strive to write HTML that is semantically accurate. When I need a horizontal rule I use an HR element, not a DIV element that looks like a dotted HR element. If you are comfortable using the DIV solution, then that is fine and up to you. But I encourage you to use the correct HTML element for horizontal rules, which is the HR element. Common practice has been, when a dotted HR element was needed, to use a DIV element instead because no one had figured out a way to style an HR element with e background image that works in Internet Explorer, until now.

As far I know, the solution I use and detail in this article is the ONLY solution and is an original solution. The common solution is to use a DIV element. I will describe the common DIV solution and then my HR solution.

Mozilla Supports a Pure CSS Solution

The most straightfoward and common solution, which works in Mozilla/Firefox, is to:

  1. Set the borders to a value that hides them
  2. Add a background image to the HR element
  3. Add height to the HR element, so the background image can be seen
  4. Center the image vertically within the height of the HR element
  5. Optionally, repeat the image horizontally if it is not wide enough to fill the space of the HR element
 
hr 
{  border:none;
  height:10px;
  background:url(/images/global/us/line.gif) repeat-x center;
}

The code above works well in Mozilla/Firefox, and probably in Safari. Here is a screenshot of how the HR looks in Firefox.

The CSS styled HR in Firefox

But ... as we will see, Internet Explorer does not correctly render the HR using the same code listed above.

The Internet Explorer Ugly Gray Border Problem

Unfortunately, while the above code works great in Mozilla/Firefox and Safari, it does not work well in Internet Explorer: gray borders remain around the HR element. This little problem screws up everything! Even though the borders are set to none, a gray border remains around the HR element, and thus around the background image.

IE adds ugly, gray borders to the content of the HR element. These gray borders are not the true borders of the HR element.

Setting the color property proves to be the only way, using CSS, to remove the gray borders in Internet Explorer. But there's a catch: the color property manages to hide the background image. So if you are not using a background image, then setting the color property will give you the results you need in Internet Explorer. You can even go on to use the border property to add borders.

But if you do need to use a background image to style your HR element, why does Internet Explorer exhibit this bizarre border behavior? Technically, I am not sure if the gray borders are actually borders. The gray borders appear to be part of the content of the HR element, not borders around the HR element. Evidence of this was seen when the color property replaced the gray borders. Also, when you explicitly add borders using CSS, Internet Explorer adds the borders around the existing gray borders, which can be clearly seen when zooming in. Here, I added a red border to the HR element. The dot gif is in the background. And the gray borders are inside the red border I added with CSS. Therefore, the gray borders are part of the foreground content of the HR element in Internet Explorer, which is why the CSS border property has no effect on the gray borders but the color property does.

IE adds ugly gray borders to the content of the element, inside the true borders, shown here in red.

Existing IE Solutions

First I will discuss a few existing solutions, their benefits and limitations, and then I will provide my solution in the next section below.

The solution for the other non-IE browsers remains the same: set the borders to none or whatever color you would like using CSS. For Internet Explorer, the solution is to NOT count on the CSS border property, because it has no effect on the gray borders that IE adds to the HR element. Instead, we must take a different approach, just for IE.

The Common DIV Element Solution for Internet Explorer

One common solution is to wrap the HR element in a DIV element, then style the DIV element and set the HR element display property to none.

 
div.hr {background:url(/path/to/my/image.gif);}
hr {display:none}

That has the advantage of working great in terms of styles, but in terms of structure you are adding an unnecessary DIV element. Also, the HR element, in terms of style, is not doing anything, because it is hidden. Using one element for style and a second element for structure works, but is a little clunky, in my opinion. If it works for you, then there it is.

Another related solution is to leave out the HR element and just use the DIV element. The CSS and HTML code is shorter, but structurally you are using a DIV element to represent an HR element in your HTML code. That is theorectically incorrect, but who cares? Much of the HTML used today is not correct in many ways. Still, I would like something correct. That's just the way I am. But in terms of real-life projects, there is nothing wrong with the DIV solution, because it works.

 
div.hr
{  background:url(/path/to/my/image.gif);
}

My solution will use only the HR element. But, first, there is another existing solution to discuss.

The Transformation Filter Solution

Using the AlphaImageLoader filter is an interesting solution. These filters are specific to IE, so this solution provides code that targets the IE problem without affecting other browsers. And by also using the background property, the image is still included for non-IE browsers.

 
hr.dotted
{  background: url(/images/global/us/line.gif) no-repeat top center;
  filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/images/global/us/line.gif');
  width: 1px;
  height: 1px;
  border: 0;
}
* > hr.dotted2
{  width: 100%;
  height: 10px;
}

The AlphaImageLoader filter replaces the content of the HR element with the image, which appears to solve to our problem: remember, the original problem is that gray borders are part of the content of the HR element. Unfortunately, if your image is larger than the content of the HR element, there is no way to clip the image to the content, because this same solution also must set the content size to 1x1 pixels. It's a bit complicated and if you search you will find examples which explain all this in more detail. The bottom line for us is that to use this solution, you must have an image that exactly fits the size of the hortizontal rule you need. For example, if you need the HR element width to fit any column width, you are out of luck. You could make multiple images, of different sizes, but I do not like that requirement. The examples I have seen use an image that does not need to expand to fill the full width of the column. If that is true for you, then this solution could work. One more thing to mention. Unfortunately, it also requires an IE CSS hack using * > which is something I try to avoid. But, hey, it works. It's up to you to decide.

My solution uses CSS instead of an Internet Explorer filter to solve the IE problem.

My Solution: The CSS Clip Property

My solution, I believe, solves all the problems. It works in Internet Explorer, Mozilla/Firefox, and Safari. I do not have additional browsers for testing. There is a catch (as always), which is that any HTML elements following an HR element, must have their position property set to relative and their top property set to provide a top margin. While not as convenient as I would like, these requirements should not be a problem. I will explain this more later.

What is unique about my solution, as far as I've seen, is the use of the CSS clip property. Using the clip property, we can effectively hide the ugly gray borders that Internet Explorer adds to the content of the HR element.

Keep in mind, we are not actually clipping the borders of the HR element. The true borders lie outside the area of the element that the clipping region applies to, so we still need to set the CSS property border to none to remove the true borders of the HR element. The clipping regions applies only to the area inside the true borders, the content of the element, which is where Internet Explorer, for some strange reason, chooses to add those pesky ugly gray, extra borders to the element.

IE adds ugly gray borders to the content of the element, inside the true borders, shown here in red.

So the solution is to hide the true borders of the HR element and to clip the ugly, gray borders that IE adds.

hr.dotted
{  background: url(/images/global/us/line.gif) repeat-x center left;
  border:0;
  clip:rect(5px 100% 6px 0);
  height:10px;
  left:0px;
  line-height:10px;
  position:absolute;
  width:inherit;
  top:inherit;
}

I have tested this in Internet Explorer 5.5 and 6, Safari 1.2, and Firefox 1.0.4.

The Catch: Absolute & Relative Positioning

The catch is that in order to use the clip property, the position property must also be set to absolute, which removes the HR element from the natural document flow, potentially playing havoc with the positioning of any element following the HR. The result is that the top of the element, for example, a paragraph, will position flush against the bottom of the HR element, leaving no space between the HR element and the following element. To prevent this problem, any element that could follow an HR needs it's CSS property set to relative, so it change its position relative to the HR element, and it's top property set to the amount of spacing required. These two requirements should not be an issue, because setting an element's position to relative means it will move relative to where it would have been anyway, which is what we want. The only drawback is if you did not want to include a top margin for those elements, because you will forced to, if you want any spacing between the HR element and the element that follows.

Last Updated ( Monday, 20 February 2006 )
 
< Prev