This article looks at the best methods I've found and lessons I've learned trying to style various HTML elements consistently with rounded corners. As with all articles of this type, your mileage may vary.

I don't know about you, but as an ASP.NET Webforms developer one of the first things I look for when a designer sends me a new look for a site I'm working on is the presence of rounded corners. Switching between square and round corners in photoshop or illustrator is done with the click of a button. In HTML, there's a little more effort involved. How much depends on

  • What range of browsers are being targeted
  • Whether or not I need to inject additional HTML into the markup generated by my webform controls. Will I end creating a user control to keep generating the correct HTML for the technique?
  • How many additional images I'll need to create to get it working
  • Will I need to use some javascript (jQuery etc) in the technique and slow the total page load time further?

For example, let's assume we have three nesting block-level elements (a form, and 2 divs) and three buttons (an input element, a link as a button and a button elements) inside the inner div

  • The form and outer div will both have rounded corners of radius 25px and 20px respectively.
  • The inner div will have rounded corners top left and bottom right of 15px radius.
  • The three buttons should have rounded corners of 10px radius.
<%@ Page Language="C#" AutoEventWireup="true"  
    CodeFile="css3.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">  
  <title>Rounded Corners</title>
</head>
<body>
  <form id="a" runat="server">
  <div id="b">
    <div id="c">
      <p>This is an &lt;input&gt; button -  &lt;asp:button&gt;: 
        <asp:Button runat="server" ID="testInputButton" 
          CssClass="button" Text="Input Button" /></p>
      <p>This is an &lt;a&gt; tag - &lt;asp:linkbutton&gt;: 
        <asp:LinkButton runat="server" ID="testLinkButton" 
          CssClass="button">Link Button</asp:LinkButton></p>
      <p>This is a &lt;button&gt; tag: 
        <button runat="server" id="testHtmlButton" 
          class="button">Html Button</button></p>
    </div>
  </div>
  </form>
</body>
</html>

Ideally of course, we should be starting to use CSS3. The border-radius property is custom-made for rounding the corners of any element. Adding a few rules like the ones below - not forgetting the -moz-border-radius and -webkit-border-radius equivalent properties as Firefox and Safari don't directly support border-radius itself yet - and we get pretty good results.

html
{
   background-color: #004;
   font-family: Calibri;
}
#a
{
   width: 500px;
   margin: 25px auto;
   padding: 25px;
   background-color: #888;
   border-radius: 25px;
   -moz-border-radius: 25px;
   -webkit-border-radius: 25px;
}
#b
{
   padding: 25px;
   background-color: #00c;
   border-radius: 20px;
   -moz-border-radius: 20px;
   -webkit-border-radius: 20px;
}
#c
{
   background-color: #fff;
   border-radius: 15px 0 15px 0;
   -moz-border-radius: 15px 0 15px 0;
   -webkit-border-radius: 15px 0 15px 0;
}
p
{
   padding: 10px;
}
.button
{
   background-color: #ccc;
   padding: 10px;
   border-radius: 10px;
   -moz-border-radius: 10px;
   -webkit-border-radius: 10px;
}

That bit of CSS renders the page correctly in Chrome 4 and 5, Safari 3 and Firefox 3.6.

CSS3

In Opera 10.51, <input> and <button> don't get rounded corners, and to give it credit, the current IE9 preview rounds everything save the Link Button as well, but it's IE8 and older which cause the problems, steadfastly refusing to do anything at all. There are many - and I do mean, many - CSS solutions to do away with IE's sharp corner fixation. Some involve lots of images, some use javascript and some both.

After trying pretty much all of them over the past few days, here are some thoughts.

  • No one of these techniques works satisfactorily on both block-level and button elements - out of the box anyway. And unless you feel confident working with some of the javascript-based techniques, that means you'll need to incorporate one technique for divs and the other for the buttons.
  • The <input> element is incredibly intransigent as far as styling goes in IE. The path of least resistance is to prefer using <button runat="server" onserverclick="handler"> to <asp:Button> wherever possible. The only exception to this is when you want to use a CommandName property on the button. In this case, you can use an <asp:LinkButton> instead.
  • The most backward-compatible techniques seem to be those that were originally created around IE7 time and have been built-upon since. Many of the button-rounding techniques are based on the sliding doors technique first documented here and here on A List Apart back in October 2003.
  • A lot of these techniques use several images. Some already combine all these images into one 'sprite' to improve performance, implying that it's more than possible to do the same with the others too. Automatically bundling CSS images into sprites looks to be one of the items being investigated for ASP.NET vNext. Perhaps we may be able to leverage these automation with these techniques in years to come.

And here are the two techniques that are now secured in my toolbox for the time being.

For Rounded DIVs - CurvyCorners

Curvy Corners (www.curvycorners.net) is a simple Javascript library, actively maintained and updated for new browser versions as they appear. It comes in a plain Javascript and jQuery variants, the latter as a reaction to the work done on the former.

Once you've downloaded it, you can round the corners of DIVs by either calling the javascript library explicitly, like this

<script type="text/JavaScript"> 
  addEvent(window, 'load', initCorners);
 
  function initCorners() {
    var settings = {
      tl: { radius: 25 },
      tr: { radius: 25 },
      bl: { radius: 25 },
      br: { radius: 25 },
      antiAlias: true
    }
     curvyCorners(settings, "#a");
  }
</script> 

or, more excitingly, it also works as a frictionless library. Just make a reference to the curvycorners.js in your page and when the page loads, it will look for the CSS3 -webkit-border-radius properties on divs and use them as cues to do its thing. Crucially, it detects first whether or not your browser supports the CSS3 border-radius property (or its -moz or -webkit reflections) and works its magic only if the browser does not - i.e. if your browser is IE8-, Firefox 2-, Chrome 2-, or Opera 9-.

There are naturally, some limitations... And I quote

Because of the need for the mechanism to operate across all browsers, the CSS selector syntax supported is necessarily limited. This sets out what is supported:

  • a selector-list, where a selector-list is either a single selector or a single selector followed by a comma and an optional space, followed by a selector-list.
  • A single selector may be either a simple-selector or a simple-selector followed by a space followed by another simple-selector.
  • A simple-selector may be either an ID of the form #myID, or a tag-class-selector.
  • A tag-class-selector may be any one of:
    1. a tag name (e.g. div);
    2. a class name preceded by a dot (e.g. .myClass); or
    3. a tag name followed by a dot followed by a class name (e.g. div.myClass).

The following are examples of supported selectors:

  • .myclass
  • #mydiv frameset.myclass
  • form.rounded frameset,div.rounded

Warning: because CurvyCorners appends extra DIVs to the boxes you wish to round, the following selector will reliably not work:

#myBox div

This is because the style will be applied not just to the top-level DIVs within the element whose ID is myBox, but also to the DIVs inserted by CurvyCorners.

The following selectors may not work as expected:

  • div #mybox
  • div.rounded #mybox

Because an ID identifies a page element uniquely, qualifying it with an enclosing scope may cause the selector to fail (e.g. if #mybox is a top-level DIV, or if it is not located within a DIV of class rounded). However, CurvyCorners assumes that the element is to be referenced anyway and will apply the appropriate rounding styles.

But it is otherwise a pretty solid thing and, obviously, easy to disable - just remove the js file reference from the page.

For Rounded Buttons - Simply-Buttons

Simply-Buttons (http://www.p51labs.com/simply-buttons-v2/) is one of the aforementioned sliding doors technique, so fully CSS-based using two image for left and right sides of the button with enough hacks to produce the same result for LinkButtons and <button>s in all browsers back to IE6. In addition, should you need your buttons to react to a click or a hover event, it also proffers a small javascript routine which allows you to set additional images to reflect those events.

The demonstration code on the site also shows how to embed icons into your buttons for a better UI feel.

SimplyButtons

What's nice about Simply-Buttons is the flexibility it offers. As far as additional HTML goes, all you need add are two nested <span> elements to your button. This means the technique would be invalid with <input> buttons but as noted earlier, a combination of <asp:LinkButton> and <button runat="server"> tags as replacement work just as well.

<asp:LinkButton runat="server" ID="testLinkButton" 
  CssClass="button">
  <span><span>Link Button</span></span>
</asp:LinkButton>

<button runat="server" id="testHtmlButton" class="button">
  <span><span>Html Button</span></span>
</button>

The download contains the stylesheet that makes the buttons so well. Once you've created the left and right images for your buttons, you need to adjust four well-identified CSS properties in the stylesheet to match the height of the button with the height of the image et voila.

Should you need the hover and click actions for the button, you create the rest of the images to reflect those states (find a good tutorial for creating round buttons here and rectangular ones here) and add the javascript file to your page.

<link rel="stylesheet" type="text/css" href="stylesheets/SimplyButtons.css" media="screen" />
<script type="text/javascript" src="SimplyButtons.js"></script>
<script type="text/javascript">
  window.onload = function()
  {
    SimplyButtons.init();
  };
</script>

The included stylesheet includes styles for both link buttons and html buttons, the iconized buttons shown above and for the hover and clicked pseudo-selectors, so you can cut it down a fair amount as well. All in all, it's a great tool to add to your basket.

Summary

In this article, I've outlined my two preferred methods for incorporating rounded corners into my ASP.NET web sites. Both are are almost frictionless as far as the original asp.net page goes with the only significant restriction being the inability to use <asp:Button> with simply-buttons. However, html\asp.net provides a complete alternative for this so it is a viable option. As ever, your mileage may vary, but it works for me :-)

Happy coding!