In the past few years, literally dozens of methods to produce cross-browser rounded rectangles have been developed [1] [2]. However, most of those I have read either rely on excessive and incomprehensible markup, use browser hacks (which is sort of frowned upon [3] by web development gurus), or use background images (which makes the boxes nearly impossible to scale correctly without noticeable overhead on the server side).
All of this has motivated me to research a solution that satisfies the following conditions:
- It works in the top browsers (Internet Explorer, Mozilla Firefox, Safari and Opera).
- It is built on valid XHTML.
- It supports different visual styles and box sizes.
- It does not rely on outright CSS hacks and browser bugs.
- It does not rely on Javascript browser recognition (ideally, that is).
Dealing with Mozilla Firefox was an easy one: it has (kind of) implemented [4] the CSS3 draft’s border-radius property since Firefox 1.0 [5]. To use it, apply the -moz-border-radius property to your element. Note that Mozilla’s version of the border-radius is different from the W3 proposal: it doesn’t support elliptic arcs in favour of specifying different values for all corners.
Dealing with Safari 3.1 is equally easy: apply the -webkit-border-radius property. Webkit implementation follows the CSS3 draft proposal.
Here’s a sample stylesheet portion which provides rounded borders in both Firefox and Safari:
.roundrect {
...other properties...
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
}
Beating Internet Explorer and Opera is somewhat more complicated. I have decided to draw the box using VML (not to be confused with VRML) in IE, and to use SVG in Opera. First, we need to make the browser aware of the VML and SVG namespaces. This is how it can be done:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:vml="urn:schemas-microsoft-com:vml" xmlns:svg="http://www.w3.org/2000/svg">
VML is proprietary Microsoft technology, and is thus only supported by Internet Explorer (version 5.0 and higher). So we need to enable VML drawing in IE and make sure that it doesn’t mess up everything in other browsers. To do this, we use conditional comments [6], which are also only supported by IE. Conditional comments can safely be used, since other browsers see them and all markup in between as perfectly valid comments. Include the following in the head of your document:
<!--[if IE 7]>
<style type="text/css">
vml\:* {
behavior: url(#default#VML);
display: inline-block;
}
</style>
<![endif]-->
Now you can put your VML-drawn rounded rectangles wherever you see fit. Just remember to wrap them into conditional comments so IE doesn’t get the piece written for other browsers, and vice-versa. Example:
<!--[if IE 7]>
<vml:roundrect class="roundrect" style="border: 0px" fillcolor="#ffffcc" strokecolor="navy" arcsize="25%">Hello world!</vml:roundrect>
<![endif]-->
<!--[if !IE]>-->
<div class="roundrect">Hello world!</div>
<!--<![endif]>-->
Let’s deal with Opera now. We’ll use an SVG background image in our box (method originally described in [7]). SVG, being an XML-based vector drawing language, supports variable box sizes and visual styles, and the image can even be customized with CSS. Unfortunately, the only method known to me of making things work in Opera 9.5 that does not break compatibility with Safari 3.1 requires some Javascript browser sniffing:
<script type="text/javascript">
if (window.opera) {
document.documentElement.className += document.documentElement.className ? ' ' + "opera" : "opera";
}
</script>
The window.opera object is, unsurprisingly, proprietary and specific to Opera, which enables us to look for it and apply a style named e.g. “opera” to the document:
.opera .roundrect {
border: 0px;
background-image: url("roundrect.svg");
}
The image roundrect.svg can be customized to anything your heart desires; here’s a sample.
That’s it, we’ve done it. I haven’t tested this solution in anything except Firefox 3, IE7, Safari 3.1 and Opera 9.5, so feel free to report any bugs you encounter. Also I’ll be grateful to know how to modify this solution to support Konqueror.