Lesson 9

CSS Rounded-Corners

One criticism of CSS-only designs is that they look too boxy and plain. One way to soften the boxiness of many CSS designs is to employ rounded corners on boxes. The following technique is based on Creating Custom Corners & Borders by Søren Madsen.

The problem is that CSS 2 doesn't offer many ways of implementing rounded corners without abusing XHTML elements to make it happen. With CSS 2 the best way to achieve rounded corners appears to be by using an adaptation of the sliding doors technique used for flexible, graphical tabs.

For this exercise, I'll be using the following XHTML code. It's still a little bulkier than I'd like, but it's a lot tighter than nearly every other rounded corner attempt I've seen:

	<div class="newsbox">
		<div class="boxhead">
			<h3>Daily News</h3>
		</div>
		<div class="boxbody">
			<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Phasellus
			 hendrerit nisl eu libero. Cras mollis. Quisque malesuada neque at tellus auctor
			 sollicitudin. Curabitur dapibus felis ac tortor. Vivamus in ligula sed erat
			 feugiat mollis. Aenean tincidunt laoreet diam.</p>

			<p>Donec hendrerit dictum massa. Suspendisse non felis. Proin mollis
			 sagittis sem. Integer tincidunt dui eu risus. Nunc hendrerit semper nisi.
			 Vestibulum varius. Aenean sodales nulla id quam. Cras volutpat felis ut lorem.
			 Etiam a enim id purus blandit dictum. Integer sollicitudin dapibus sapien.      </p>
		</div>
	</div>
	

I don't like the extra divs around the h3 and the p elements; they aren't necessary structurally, and don't lend much to the semantic meaning of the XHTML. However, they are necessary for my design goal as they accomodate the rounded corners. Compare this code to what some designers use for rounded corners and you'll at least appreciate how bad this could be!

	<div class="box">
		<div class="innerbox">
			<div class="topbox">
				<div></div>
			</div>
			<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Phasellus
			 hendrerit nisl eu libero. Cras mollis. Quisque malesuada neque at tellus auctor
			 sollicitudin. Curabitur dapibus felis ac tortor. Vivamus in ligula sed erat
			 feugiat mollis. Aenean tincidunt laoreet diam.</p>

			<p>Donec hendrerit dictum massa. Suspendisse non felis. Proin mollis
			 sagittis sem. Integer tincidunt dui eu risus. Nunc hendrerit semper nisi.
			 Vestibulum varius. Aenean sodales nulla id quam. Cras volutpat felis ut lorem.
			 Etiam a enim id purus blandit dictum. Integer sollicitudin dapibus sapien.      </p>
		
			<div class="bottombox">
				<div></div>
			</div>
		</div>
	</div>
	

Yuck. One or two non-semantic divs is one thing, but several non-semantic divs enclosing empty divs is quite another!

Well, my XHTML isn't 100% semantic, but it's not too shabby. Time to implement the corner images I've created.

What Would You Do?

You've probably guessed that I'm going to use background images for the corners of the box as I did with the sliding door tabs.

Four Corners

I've created four images in Photoshop, each with a rounded corner made using the elliptical marquee tool. In the example I'm using, the box has a heading so I've taken the liberty of darkening the background and corners that run along the top.

Here's a look at the 4 images I've created:

Because I want my box to be very flexible, I've made my images quite large, somewhere around 1200px wide or 1200px high. Yours don't have to be so large; they just have to be as large as you think your box might ever grow to be! Remember, one of the key benefits of sliding doors technique is that the text can be resized by the user without hiding the text or breaking the box.

Let the Styling Begin!

I've already set a font for my body element:

		body { font-family: Verdana,sans-serif; font-size: 80%; }
	

With that out of the way, I'm going to give each div a temporary border so I can monitor how things will shape up:

		div {border: 1px solid red }
		div div { border: 1px solid green}
	

Now add the corners in one by one, starting with the first div to supply the bottom right corner:

		.newsbox { background: #F3C06F url("images/crnr_bot-r.gif") no-repeat bottom right; }
	

I add in the other corners, working counter clockwise:

		.boxhead { background: url("images/crnr_top-r.gif") no-repeat top right; }
		.boxhead h3 { background: url("images/crnr_top-l.gif") no-repeat top left; }
		.boxbody { background: url("images/crnr_bot-l.gif") no-repeat bottom left; }
	

Note that one of the corners asits in the h3 element. If you don't use an h3 element you'll have to style this to another element, perhaps the first p element.

What Would You Do?

I've enlarged what's supposed to be the top-left corner to show a problem. Why has this problem occurred, and what syntax would you use to correct it?

Aligning & Adjusting the Corners

A common problem with this sort of design is inherent margins or padding on certain elements. The h3 element, for example, has an natural margin above and below it. This interferes with the look of our corners, so we must eliminate it:

		.boxhead h3 {
			background: url("images/crnr_top-l.gif") no-repeat top left;
			margin: 0;
		}
	

Sometimes browsers like to give divs natural margins or padding too, so let's eliminate those on our parent divs just to be on the safe side. In fact, we can write a selector grouping to wipe them all out:

		.newsbox,.boxhead,.boxhead h3 {
			margin: 0;
			padding: 0;
		}
	

I think I'm at a good place, and can eliminate those temporary borders altogether.

You've probably noticed that the text runs right to the edge of our box, possibly overlapping our corners. Let's add padding to both the h3 and the bodybox to eliminate this and make the typography cleaner:

		.boxhead h3 {
			background: url("images/crnr_top-l.gif") no-repeat top left;
			padding: .2em 22px;
		}
		.boxbody {
			background: url("images/crnr_bot-l.gif") no-repeat bottom left;
			margin: 0;
			padding: .2em 22px 1em;
		}
	

Our box so far:

Very close! Let's style the h3 text a bit and I think we're off to the races:

		.boxhead h3 {
			background: url("images/crnr_top-l.gif") no-repeat top left;
			padding: .2em 22px;
			color: #fff;
			text-align: center;
			width: 100%;
		}
	

Potential Issues

I made my images huge so that the box would scale extremely well, but everythin has a limit. The "limits" of my box is about 1200px. I can use the max-width and max-height properties to control this in standards-compliant browsers. I can also set a width using ems or % to be on the safe side:

		.newsbox { 
			background: #F3C06F url("images/crnr_bot-r.gif") no-repeat bottom right;
			width: 33%;
			max-width: 1200px;
			max-height: 1200px;
		}
	

Another potential issue lies with the h3 element and % based sizing. If the size is reduced to a width lower than the width of the h3 element in IE, the h3 element wraps and breaks the box. A good solution to this problem is to use white-space: nowrap on the h3:

		.boxhead h3 {
			background: url("images/crnr_top-l.gif") no-repeat top left;
			padding: .2em 22px;
			color: #fff;
			text-align: center;
			white-space: nowrap
		}
	

Moving Forward...

So far, this is the most efficient, most flexible technique for creating rounded corner boxes using CSS. Of course, this technique may soon be obsolete as the web browser usage market moves towards browsers with "page zoom". In the meantime, this is a strong technique that has been used for over 4 years. Søren Madsen returned to the challenge of custom rounded corners in his follow-up article, Creating Custom Corners & Borders Part II.