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
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:
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!
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.
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.
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!).
.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 :)
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.
<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.
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).
The only difference between type1 with 2 and 3 is color. So we will only change that.
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).
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 :)
What's the difference between type4, and types 1, 2 and 3? Color+Border. Let's deal with those factors.
<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>
#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
Ok type 5 requires a bit more of work. We must do this:
Let's get started.
<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>
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).
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.
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!