Introduction
Yes, I know that there are thousands of tutorials regarding rounded corners with CSS, but anyway, I wanted to show you this way too.
Hopefully, you will find it useful.
It's important to point out that this tutorial is quite advanced regarding CSS, but I'll try to make it as simple as I can for CSS begginers.
CSS3 is still not fully here, so until then, let's keep our work W3C valid.
Take a look at the demo | Download css sprites + rounded corners
What are we going to do?
My rounded corner version consists in making a containing div with four absolute-positioned divs inside, where the corner images are formed using a unique CSS Sprite. We'll be doing this:

What makes this technique cool?
The ability to make rounded-bordered elements with fluid width and height. No limits whatsoever.
This technique, as I mentioned before, is combined with CSS Sprites. If you don't know what they are or how to use them, read my previous article first. Got a hang of CSS sprites?, then let's get started!
Step 1: Creating our Sprite
-
Make a rounded rectangle in the image editor of your choice (I'll be using Fireworks in this case).
-
Slice and export one corner and save it into a temporary location (We'll toss it later).
-
Make a new document, import your corner, copy it 3 times and rotate its pieces to get the other corners.
-
Compose an image with the four corners, with a 1px red line dividing them.
- Export that image, and our sprite is finished.
Step 2: HTML Code
First of all, we will give our containing div a class of .roundedBox:
<div class="roundedBox"></div>
Now, we must add four divs that will create our corners later on. We shall give all of them a class of .corner and also a class according to their position.
<div class="roundedBox">
<strong>My content in roundedBox Type 1</strong>
<div class="corner topLeft"></div>
<div class="corner topRight"></div>
<div class="corner bottomLeft"></div>
<div class="corner bottomRight"></div>
</div>
All done? Ok, let's move to our CSS code.
Step 3: CSS code
As you know, (or you'll learn it here fast) absolutely-positioned elements are situated according to their parent relatively-positioned element. If this element is not defined,
they will take as their parent relatively-positioned element, the body tag.
Huh?! - Ok, if you didn't get this, don't worry, you'll catch it in an second.
Let's style all of our corners first
We must make their position absolute and define their width and height (that will be the same for all corners).
My corners have a width and height of 17px.
![]()
.corner {position:absolute; width:17px; height:17px;}
If you export a rectangled-shaped slice when you make your first corner, the width and height will not be the same (Duh!).
Now, let's style our containing div:
.roundedBox {position:relative;}
This allows any absolutely-positioned element which is inside another element with the class .roundedBox, to position itself according to it; instead of the body tag.
We must also give it a padding, because if not, the corners will appear on top of our text; and we don't want that.
Important: The top+bottom padding must be equal and equivalent to the height of the corner. The left+right padding must be equal and equivalent to the width of the corner.
As you already know, the width and height of my corner is the same, so this padding is the same for the four sides:
.roundedBox {position:relative; padding:17px; margin:10px 0;}
I also included a margin to give some space to our div :)
Finally, let's style each corner individually
We'll define the absolute position of each corner and its background position too (according to our sprite):
.roundedBox {position:relative; padding:17px; margin:10px 0;}
.corner {position:absolute; width:17px; height:17px;}
.topLeft {top:0; left:0; background-position:-1px -1px;}
.topRight {top:0; right:0; background-position:-19px -1px;}
.bottomLeft {bottom:0; left:0; background-position:-1px -19px;}
.bottomRight {bottom:0; right:0; background-position:-19px -19px;}
As you have probably noticed, our css hasn't loaded our sprite yet. The reason for this is that we will use different ones so we will not define them generically.
Rounded Box Type 1 (Blue)
HTML Code
<div class="roundedBox" id="type1">
<strong>My content in roundedBox Type 1</strong>
<div class="corner topLeft"></div>
<div class="corner topRight"></div>
<div class="corner bottomLeft"></div>
<div class="corner bottomRight"></div>
</div>
We must give our div an ID of #type1 to apply our particular background.
CSS Code
First, we must match the #type1 background-color to our corners' background color in the sprite:
#type1 {background-color:#CCDEDE;}

And then, using the class .corner, load the CSS Sprite for that type of rounded box:
#type1 {background-color:#CCDEDE;}
#type1 .corner {background-image:url(../images/corners-type1.gif);}

Ok, our first rounded rectangle is done! Watch the preview of the rounded rectangle Type1 (Blue).
Rounded Box Type 2 (Green) / Rounded Box Type 3 (Violet)
The only difference between type1 with 2 and 3 is color. So we will only change that.
Type 2 (Green)
HTML code
<div class="roundedBox" id="type2">
<strong>My content in roundedBox Type 2</strong>
<div class="corner topLeft"></div>
<div class="corner topRight"></div>
<div class="corner bottomLeft"></div>
<div class="corner bottomRight"></div>
</div>
CSS code (Just change the sprites color, and change the background-color)

#type2 {background-color:#CDDFCA;}
#type2 .corner {background-image:url(../images/corners-type2.gif);}
Watch the preview of the rounded rectangle Type2 (Green).
Type 3 (Violet)
HTML code
<div class="roundedBox" id="type3">
<strong>My content in roundedBox Type 3</strong>
<div class="corner topLeft"></div>
<div class="corner topRight"></div>
<div class="corner bottomLeft"></div>
<div class="corner bottomRight"></div>
</div>
CSS code (Just change the sprites color, and change the background-color)

#type3 {background-color:#D3CADF;}
#type3 .corner {background-image:url(../images/corners-type3.gif);}
Watch the preview of the rounded rectangle Type3 (Violet).
Got a hang of it? Ok now let's go a bit further :)
Type 4 (Red with border)
What's the difference between type4, and types 1, 2 and 3? Color+Border. Let's deal with those factors.
HTML code
<div class="roundedBox" id="type4">
<strong>My content in roundedBox Type 4</strong>
<div class="corner topLeft"></div>
<div class="corner topRight"></div>
<div class="corner bottomLeft"></div>
<div class="corner bottomRight"></div>
</div>
CSS code (Add to your corners in the sprite a border and match the .roundedBox background and border to the corners in the sprite)

#type4 {background-color:#CCACAE; border:1px solid #AD9396;}
#type4 .corner {background-image:url(../images/corners-type4.gif);}

Ok, here is the catch. Our corners will not overlap correctly to our #type4 border. So we must correct their positioning by overriding the previous positioning styles. Let's do that:
#type4 {background-color:#CCACAE; border:1px solid #AD9396;}
#type4 .corner {background-image:url(../images/corners-type4.gif);}
#type4 .topLeft {top:-1px;left:-1px;}
#type4 .topRight {top:-1px; right:-1px;}
#type4 .bottomLeft {bottom:-1px; left:-1px;}
#type4 .bottomRight {bottom:-1px; right:-1px;}
Now, we're done with Type4. Watch the preview of the rounded rectangle Type4 (Red with border).
We are almost there, don't quit now :p
Type 5 (with vertical gradient)
Ok type 5 requires a bit more of work. We must do this:
- Change the top or bottom corners' height (depending on your gradient).
- Change the top or bottom corners' background-position (depending on your gradient).
- Give our containing div a 1px background-repeat to create the prolongation of our gradient.
- Have a significant amount of content or a min-height for our div, (depending on your gradient).
Let's get started.
HTML code (same as before)
<div class="roundedBox" id="type5">
<strong>My content in roundedBox Type 5</strong>
<div class="corner topLeft"></div>
<div class="corner topRight"></div>
<div class="corner bottomLeft"></div>
<div class="corner bottomRight"></div>
</div>
CSS code
My gradient is vertical, from the top to the bottom. So, we must increase the top corners' height, and change de bottom corners' background-position. You will understand why I do this when you see my new sprite, which is this one:

And the background-image for my div is this one:

It's 1px wide, but it is there.
My bottom corners have a solid color and we will match it with my div's background-color.
Less talking and more action. Let's start with our containing div:
#type5 {background:#FECBCA url(../images/roundedbox-type5-bg.png) repeat-x 0 0; min-height:110px;}
For the background color I sampled with the eyedropper the bottom corners' background. Then, I added the background-image that will repeat in x.
Finnally I added a min-height, as I told you before, so the gradient doesn't break.
We now add the corners (I changed the file type to .png to correct the quality of the gradient):
#type5 {background:#FECBCA url(../images/roundedbox-type5-bg.png) repeat-x 0 0; min-height:110px;}
#type5 .corner {background-image:url(../images/corners-type5.png);}
Now, I increase the top corners' height (which depends on the moment the gradient reaches the solid color):
#type5 {background:#FECBCA url(../images/roundedbox-type5-bg.png) repeat-x 0 0; min-height:110px;}
#type5 .corner {background-image:url(../images/corners-type5.png);}
#type5 .topLeft,
#type5 .topRight {height:140px;}
Finally, I correct the bottom corners' background-position:
#type5 {background:#FECBCA url(../images/roundedbox-type5-bg.png) repeat-x 0 0; min-height:110px;}
#type5 .corner {background-image:url(../images/corners-type5.png);}
#type5 .topLeft,
#type5 .topRight {height:140px;}
#type5 .bottomLeft {background-position:-1px -142px;}
#type5 .bottomRight {background-position:-19px -142px;}
All done! - Watch the preview of the rounded rectangle Type5 (with vertical gradient).
IE6 Issue
This nasty browser has a problem with this technique. You must give the container (.roundedBox, or #type1, #type2, etc) a determined width and height.
If you don't define it, the box will look broken.
Use conditional comments for IE6 to work this out.
Final thoughts
You can keep inventing other types of corners with this technique. Horizontal gradients, transparent corners. Just exercise a bit the brain and you'll
manage to get this styles also.
I hope this technique was useful for you, and not too complex.
Merry X Mas and a Happy New Year!
Kai Chan Vong 29 Dec, 2008
Really we shouldn't be adding in elements just for the sake of styling... that's why I consider this method a hack. Nothing against it, we all use it in some scenarios.
Also IE6 will have a problem if your height of your font is greater than your corner... to fix this - font-size:0;
I'd keep the class names a little shorter personally :P
Permana Jayanta 29 Dec, 2008
Standardsista 29 Dec, 2008
wow 29 Dec, 2008
The only thing that really matters is time/quality/cost
Scott 29 Dec, 2008
Besides - square is the new round in '09.
Baz L 29 Dec, 2008
The article is titled "rounded corners"; so right away semantics is out the door. That's just an understood fact.
Only thing you can do is combine it with something like this:
http://www.webdevelopment2.com/rounded-corners-jquery-css/
Evan 29 Dec, 2008
It sucks having to throw in those empty div but there are not many options when you want to build something flexible like this with just xhtml and css. There are some scripts out there to round corners but many of them basically do the same thing polluting the dom with random divs to achieve the look. The only difference being they don't appear in your original html but on the rendered page they show up.
Kai Chan Vong 29 Dec, 2008
That link you posted - http://www.webdevelopment2.com/rounded-corners-jquery-css/ - is quite possibly the least semantic option anyone could inject into a DOM.
moz-corners/web-kit corners are semantic... it's just a case of IE not thinking about semantics and helping us all to keep code as clean as possible.
It's simply a case of not adding layers to your markup for the sake of design and balancing the two.
Jason 30 Dec, 2008
I've used this technique and it works well in situations where rounded corners are vital. However, most times I consider the rounded corners to be simply a treat for people with decent browsers, not vital to the information being presented on the site. With that said, I'm perfectly content with giving rounded corners to the Firefox and Safari users out there, while the IE guys get square corners. Clients usually understand that not all browsers are created equal.
Baz L 30 Dec, 2008
Now only the ridiculous debate of semantics. Save the lecture. There are those of you who cling to the idea of semantics because you like the way the word sounds, I don't. You seem to see semantics as black or white. In the World of Web Development it is, Web Design is a whole other story. Sometimes you need to bend a lil' bit for your client's needs.
The fact that you consider DOM injection not semantic clearly shows that you don't understand that purpose for your obsession with the term.
ignari 30 Dec, 2008
I know that this is not a semantic method, but there is no way to achieve this in a fully semantic way making the design as fluid as this one.
I think it's not really good also to jeopardize our design to achieve a 100% semantic code.
Ignacio
Art 31 Dec, 2008
Pablo 31 Dec, 2008
Besides that, i think it's a simple solution, more elegant than another ones --> http://www.webdevelopment2.com/rounded-corners-jquery-css/
feir 31 Dec, 2008
Dainis Graveris 1 Jan, 2009
d 2 Jan, 2009
Martin Berglund 10 Jan, 2009
Another way to achieve different colors is setting the corners to the background color and letting the fill be transparent ;)
keith 28 Jan, 2009
I just include -moz-border-radius on my divs and leave IE with square.
Hutch 28 Apr, 2009
Willem Mol 14 May, 2009