Tuesday, July 27, 2010

inline elements and background-images

This dreaded issue has been looked at to death in so many forums, but in all my research I haven't found a working solution. In here, I wil describe a few solutions that worked for me but let's start with the basics first.

The issue that we're facing be described in detail here: http://www.maxdesign.com.au/articles/inline/

We are attaching a background-image to all elements that have the 'icon' attribute set. The advantage of doing this is that if we wanted to change a commonly used image, we'd only have to change it in one spot. Here's some of the code:


[icon] {
    padding-right: 20px;
    background: no-repeat center right;
}

[icon='required'] {
    background-image: url(../images/required.png);
}
[icon='toggle'] {
    background-image: url(../images/toggle.png);
}
[icon='addField'] {
    background-image: url(../images/add.png);
}
[icon='first'] {
    background-image: url(../images/btn_first.png);
}
[icon='last'] {
    background-image: url(../images/btn_last.png);
}
[icon='next'] {
    background-image: url(../images/btn_next.png);
}
[icon='prev'] {
    background-image: url(../images/btn_prev.png);
}

The image icon is visible in firefox, but not in IE 7. It's not at fault of IE (for once), because inline elements with padding on them has undefined behaviour and the CSS spec gives no details.


[icon] {
    padding-right: 20px;
    background: no-repeat center right;
}

We we're applying the icon attribute to Anchor elements as follows:

<a href="javascript:animatedcollapse.toggle('details')" icon="toggle" title="View Details"></a>


Solutions:

1) Adding a space

I stumbled upon this accidently while trying other possible solutions, and I haven't seen it documented anywhere else so it is worth mentioning. It's quite simple. If we add   inside the anchor element, then IE7 will display the icon correctly. The added side effect is that there will be a space. It works but then that means you have to add a silly   to all your elements.

2) Javascript/jQuery

The idea is to inspect all elements that have the icon attribute, and pull out the URL for the background-image and create a new element and assign the src attribute as follows:
<!--[if IE 7]>
    <script type="text/javascript">
    
        $(document).ready(function() 
        { 
        
            $("a[icon]").each(function() 
                    { 
                var iconUrl = $(this).css("background-image");
                iconUrl = iconUrl.replace(/"/g,"").replace(/url\(|\)$/ig, "");
                
                
                var imgEl = document.createElement('img');
                imgEl.src = iconUrl;
    
                $(this).css('icon','');
                this.removeAttribute("icon");
                
                $(this).append(imgEl);
                $(this).hover();
            }); 
        });
            
    </script>
<![endif]-->

It's not pretty, but if your project is already using jQuery and you have a template page, then you can add this to your template.

3)  Switching the CSS display property
 This is the best solution with the least amount code and less invasive. The idea is to trick IE 7 into using a display property of inline-block but then switching it back inline as follows:

[icon] {
    *display: inline-block;
}
[icon] {
    *display: inline;
    background: no-repeat right center;
    *position: absolute;
    padding-right: 20px;
}

The asteriks are IE 7 specific as mentioned here: http://css-tricks.com/how-to-create-an-ie-only-stylesheet/

No comments:

Post a Comment