posted on:December 29, 2008

CSS Sprites Rounded corners


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:

Rounded corner types preview

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

  1. Make a rounded rectangle in the image editor of your choice (I’ll be using Fireworks in this case).

    Creating your rounded box sprite - part 1

  2. Slice and export one corner and save it into a temporary location (We’ll toss it later).
    Creating your rounded box sprite - part 2
  3. Make a new document, import your corner, copy it 3 times and rotate its pieces to get the other corners.
    Creating your rounded box sprite - part 3
  4. Compose an image with the four corners, with a 1px red line dividing them.
    Creating your rounded box sprite - part 4
  5. 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 size inside the sprite

.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;}

Rounded Box Type 1 Background Hexa Color

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);}

Corner Type 1 Sprite

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)

Corner Type 2 Sprite

#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)

Corner Type 3 Sprite

#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)

Rounded Box Type 4 Background and border Hexa Color

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

Corner Type 4 Sprite

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:

  1. Change the top or bottom corners’ height (depending on your gradient).
  2. Change the top or bottom corners’ background-position (depending on your gradient).
  3. Give our containing div a 1px background-repeat to create the prolongation of our gradient.
  4. 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:

Corner Type 5 Sprite

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

Rounded Box Type 5 Gradient Background
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!

Enjoyed the article?

Then don't miss our next one! Subscribe to our RSS feed or share it with your friends.

DeliciousStumbleUpon RedditSubscribe

Comments (20 Comments)

  1. Kai Chan Vong
    December 29, 2008

    Nice highlight of this, however I'd point out to think where you're using it... is the content scalling horizontally + vertically? Or can you get away with something a bit more semantic. Sometimes using just a top and a bottom header and footer styled corners can be better in terms of making you markup easier to read + logical. 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
  2. Permana Jayanta
    December 29, 2008

    very nice tutorial with great explanation ... I'm going to give it a try ...
  3. Standardsista
    December 29, 2008

    Interesting, but using empty tags misses the whole point of the web standards revolution and the push for semantically correct markup. Instead of old school tag soup, you're basically mixing up a new recipe for tag soup using non-depricated elements. Semantics matters.
  4. wow
    December 29, 2008

    @standardsista The only thing that really matters is time/quality/cost
  5. Scott
    December 29, 2008

    I agree with Standardsista. Dumping unnecessary HTML elements into your markup isn't an optimal solution. While this is a novel solution, there are already ways to achieve rounded corners without additional HTML code. Besides - square is the new round in '09.
  6. Baz L
    December 29, 2008

    I don't understand the 1st commentor. Rounded corners are a hack, period. You can't get it more semantic than that. 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/
  7. Evan
    December 29, 2008

    The ie6 issues are probably a result of haslayout. If you can't count on a fixed width or height you could try triggering it with display:inline-block or zoom:1. 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.
  8. Kai Chan Vong
    December 29, 2008

    Baz L: Rounded corners are not a hack - they way they're having to be implemented in the present state of browsers:- 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.
  9. Jason
    December 30, 2008

    Just my 2 cents. 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.
  10. Baz L
    December 30, 2008

    I'm sorry Mr. Vong, I thought it was obvious what I meant: The Majority of the rounded corner implementations are for browsers that don't support CSS3 and for more graphical implementations where moz-corners and web-kit corners don't cut it. Rounded corners are about presentation, simply put. That's what I meant by a hack. 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.
  11. ignari
    December 30, 2008

    Hi guys, thanks for the comments. 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
  12. Art
    December 31, 2008

    With regard to the padding for .roundedBox, the left and right padding can be less than the width of the corners if the top and bottom padding is greater than or equal to the height of the corners. Similarly, the top and bottom padding can be less than the height of the corners if the left and right padding is greater than or equal to the width of the corners.
  13. Pablo
    December 31, 2008

    Why the red line between the sprites? Sorry, it's a minor detail but i didn't understand it. Besides that, i think it's a simple solution, more elegant than another ones --> http://www.webdevelopment2.com/rounded-corners-jquery-css/
  14. feir
    December 31, 2008

    Nice tutorial. Thanx/
  15. Dainis Graveris
    January 1, 2009

    Very detailed tutorial for corners, I just could say thank You for Your work.!
  16. d
    January 2, 2009

    Hmm...HUGE ie6 problem...you usually never know the exact height of a box with content in it. Unless you have almost zero ie6 users I would not recommend using this technique. There are several other, better alternatives although this idea is nice.
  17. Martin Berglund
    January 10, 2009

    Although this technique ads to much markup for my taste, I think it looks good. Another way to achieve different colors is setting the corners to the background color and letting the fill be transparent ;)
  18. keith
    January 28, 2009

    i agree with jason, i think rounded corners are eye candy for those who use a decent browser. I just include -moz-border-radius on my divs and leave IE with square.
  19. Hutch
    April 28, 2009

    Nice.. thanks.
  20. Willem Mol
    May 14, 2009

    I f you use generated pages (cms) you can add the extra div sections to your xhtml output for ie6/7 only and use pseudo classes (:before background-image|content, :after background-image|content) for all acid compliant browsers.

Sorry, the comment form is closed at this time.