January 24th, 2008 - by Paul OB

Oh No! Not more round corners!

In a previous article we learned how to apply some nice shadowed corners and sides to a fluid width box and I thought it would be good to show a similar method that allows for transparent corners. This will allow the element to sit on any colored background without having to paint the transparent part of the corner with the background color.

I know you might think “Oh no – not another round corner tutorial” but stick with it and I’m sure you’ll find some of this info useful. Round corners are always a bit of a pain to do in CSS so I present here an easy to follow way to make round corners that can be used everywhere. We aren’t going to do anything clever or overly complicated and we aren’t going to bother with shadowed corners/sides because as I mentioned above we have already been there.

Before we begin here is a finished example for you to look at.

In order to use the round corner on different backgrounds I am going to use an image using the PNG8 (Portable Network Graphics) format with alpha transparency as shown by Alex in this useful article. If you don’t have Fireworks or want smoother corners in IE6 and under then you will need to make images with the appropriate color background in the normal GIF (Graphic Interchange Format) format.

Here is the type of image I will be using for the following examples:

Figure 1

one-round-test.png

The image is a white circle with a 20px diameter that I have placed on a green background so that you can see it and so you can see what the effect will be against a different color background. (The real image won’t have a green background of course.)

As you can see the image displays nicely on the green background in browsers that support alpha transparency because the corners are transparent. In IE6 and under the corners will appear slightly more jagged but eminently usable. What’s good about this is that no hacks or filters are required.

Here is a magnified screenshot of the top left corner in IE6 and IE7 to show the differences:

Figure 2

simple-screen1.jpg

That looks quite acceptable to me and if it’s acceptable to you then we will plow on with the demonstration.

I should point out that you will need to create different colored circles if you want your elements to be different colors but unlike other methods you don’t have to worry about the background of the elements that your box is laid upon.

One Size Fits All

We are going to use a single image (20px x 20px) to provide our rounded corners and to save on using different images we will use one image only and simply place each corner into place using the background-position property. The image is completely round but I’ll only be showing one quadrant of it at a time and therefore we can supply all four corners with one simple image weighing in at only 300 bytes.

Figure 3

one-round-quadrant.png

The benefit of using a single image is that all corners get loaded immediately after the first corner is drawn so there is virtually no delay.

Cut It Out

You may think that you could simply place the image in the four corners of a rectangular box but things aren’t as simple as that. Our box needs to have a background color and as we are using a white corner image we need a white background for our box. However, if we place a transparent corner in the corner of that box then in fact nothing really happens. The reason is that the transparent part of the image lets the white background show through and all we get is the square box we started with.

In order for the corners to work properly the corner of the box must be over the background color of the element outside our current box. We therefore need to drag the round corners outside the box to start with but that presents more problems. Here is a screenshot of what the corners will look like outside the box so you can understand what’s going on

Figure 4

simple-screen3.jpg

As you can see we have a problem whatever we do! If the images are inside the rectangle then they become invisible. If they are outside the rectangle then it looks even worse as figure 4 above shows

What we really need is a rectangular box where the four corners are cut-out to give a cross-shaped effect. If we made sure that the cut-out matched the radius of our circle (10px) then we could pop our corners nicely into place.

We can achieve this by nesting an inner box inside our outer box and then dragging it outside of the parent using a negative top and bottom margin. If we also give side padding to the parent and top padding to the child we can get a cut out effect like this.

Figure 5

simple-screen2.jpg

The CSS mark up for this is as follows:

  1. * {margin:0;padding:0}
  2. h1 {margin:.5em;}
  3. body {
  4. background:#e5e5e5;
  5. color:#000;
  6. }
  7. .box{
  8. float:left;
  9. background:#fff;
  10. padding:0 10px;
  11. margin:10px;
  12. display:inline;/* IE double margin bug*/
  13. }
  14. .one{width:40%}
  15. .inner{
  16. background:#fff;
  17. padding:10px 0;
  18. margin:-10px 0;
  19. position:relative;
  20. }

Followed by the simple HTML:

  1. <div class="box one">
  2. <div class="inner">
  3. <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed convallis mauris eu ipsum. Proin volutpat facilisis dui. Sed pretium pulvinar arcu.</p>
  4. </div>
  5. </div>

The next step is to provide four elements and place our corners into position with static positioning. We will be leaving a 10px padding around our box so that we have room to position the corners nicely without affecting the inner content. (Don’t be tempted to use absolute positioning because IE is always 1px out when the distance traveled is an odd pixel number. This happens on right and bottom absolutely placed elements and can destroy a layout like this.)

I am going to use a div with nested span to provide elements for the corners but if you wanted to reduce mark up you could use a nested “b” element as suggested by Eric Meyer (although its use for background images is not likely to be very semantic). Using a nested b element would also negate the need for a class as you are unlikely to have any other elements like this on your page. Anyway I am sticking with the div and nested span as it is easier to follow.

The HTML we need for this is as follows:

  1. <div class="box one">
  2. <div class="inner">
  3. <div class="top"><span></span></div>
  4. <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed convallis mauris eu ipsum. Proin volutpat facilisis dui. Sed pretium pulvinar arcu.</p>
  5. <div class="base"><span></span></div>
  6. </div>
  7. </div>

The extra div and span has been placed inside the .inner element which means we must drag the top corners upwards into the padding area and then outwards into free space so that the transparent corners can show. The reverse process is needed for the bottom corners. There are a couple of “haslayout” bugs to squash on the way and IE6 also needs position relative applied to make the corners show.

The revised CSS and HTML for the whole section is shown below.

  1. * {margin:0;padding:0}
  2. h1 {margin:.5em;}
  3. body {
  4. background:#e5e5e5;
  5. color:#000;
  6. }
  7. .box{
  8. float:left;
  9. background:#fff;
  10. padding:0 10px;
  11. margin:10px;
  12. display:inline;/* IE double margin bug*/
  13. }
  14. .one{width:40%}
  15. .inner{
  16. background:#fff;
  17. padding:10px 0;
  18. margin:-10px 0;
  19. min-height:0;/* ie7 haslayout issues fix*/
  20. position:relative;
  21. }
  22. * html .inner{height:1px}/* ie6 haslayout issues fix*/
  23. .top,.base{
  24. margin:-10px -10px 0;
  25. background:url(images/one-round-test2.png) no-repeat left top;
  26. height:10px;
  27. position:relative;
  28. font-size:10px;
  29. }
  30. .base{
  31. background-position:left bottom;
  32. margin:0 -10px -10px;
  33. }
  34. .top span,.base span{
  35. background:url(images/one-round-test2.png) no-repeat right top;
  36. display:block;
  37. height:10px;
  38. font-size:10px;
  39. }
  40. .base span{background-position:right bottom;}

I have also added a content div in the middle just to tidy things up and the revised HTML is as follows:

  1. <div class="box one">
  2. <div class="inner">
  3. <div class="top"><span></span></div>
  4. <div class="content">
  5. <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed convallis mauris eu ipsum. Proin volutpat facilisis dui. Sed pretium pulvinar arcu.</p>
  6. </div>
  7. <div class="base"><span></span></div>
  8. </div>
  9. </div>

The font-size:10px in the CSS is there to restrict IE’s height to 10px; otherwise it would increase the element to the full current font-size and spoil the effect. The result of the above code can be seen in these live examples:

Example 1

Example 2

Example 3

For ease of use the CSS has been left in the head so that you can view source and inspect it easily.

Not Floated

The above example uses floats to hold everything together but we can simplify this a little and use static elements instead. Instead of floating the outer we can give it a width or leave it as width:auto and set the margins accordingly. Once again IE6 needs a helping hand and we have to use the ubiquitous “haslayout” fix to bring it all into line.

The only thing worth noting is that now that the main element isn’t floated you will find that margin collapse affects the negative margined corners in Firefox and in order to stop the margin collapse we will simply add a 1px border in the current background color. This will cure the effect quite simply (read more about collapsing margins in a previous article.)

Here is the revised CSS:

  1. .box{
  2. width:760px;
  3. background:#fff;
  4. padding:0 9px;
  5. margin:30px auto;
  6. position:relative;
  7. border:1px solid #fff;/* stop margin collapse*/
  8. }
  9. .inner{
  10. background:#fff;
  11. padding:10px 0;
  12. margin:-10px 0;
  13. min-height:0;/* ie7 haslayout issues fix*/
  14. position:relative;
  15. }
  16. * html .inner, * html .box{height:1px}/* ie6 haslayout issues fix*/
  17. .top,.base{
  18. margin:-10px -10px 0;
  19. background:url(images/one-round-test2.png) no-repeat left top;
  20. height:10px;
  21. position:relative;
  22. font-size:10px;
  23. clear:both
  24. }
  25. .base{
  26. background-position:left bottom;
  27. margin:0 -10px -10px;
  28. }
  29. .top span,.base span{
  30. background:url(images/one-round-test2.png) no-repeat right top;
  31. display:block;
  32. height:10px;
  33. font-size:10px;
  34. }
  35. .base span{background-position:right bottom;}
  36. .content{width:100%;}

HTML:

  1. <div class="box">
  2. <div class="inner">
  3. <div class="top"><span></span></div>
  4. <div class="content">
  5. <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed convallis mauris eu ipsum. Proin volutpat facilisis dui. Sed pretium pulvinar arcu. </p>
  6. </div>
  7. <div class="base"><span></span></div>
  8. </div>
  9. </div>

As you can see in Example 5 things are looking better now and much easier to control. You can even nest the boxes quite easily now.

What about borders?

If you want to add borders to the element and the corners then you will need to make a new round image with the border color that you require. We can then add CSS borders to our layout to match up and complete the illusion. Unfortunately you will need to make two images this time because of course the bordered part of the round corner that extends into our layout will show. We can get away with two images because some of the image will already be covered up by the negative margin we used on the content.

Here is a screenshot of what happens when just the single image is used:
simple-screen4.png

As you can see some of the border has already been rubbed out so we just need to make images without the sections that are visible above. Two images will be enough for this.

If you don’t mind a couple of hacks you can drag the inner content over the visible part of the border and the whole thing can be done using one image only as shown in this live example and in the screenshot below.

simple-screen5.png

I would recommend, however, using two images and avoiding the hacks to keep things simpler. You should be able to work out what’s going on by looking at the source code so I won’t go into more detail and leave that as an Lose Weight Exercise for you.

Drawbacks

The main drawback is once again the extra html mark up required to place each corner and if that upsets you then you may want to try one of the many javascript solutions that are out there.

There is also extra maintenance involved with the negative positioning that we used and you will need to take this into account when you place the corners alongside other elements as they will overlap other elements if you don’t allow about 10px more space than you thought you needed.

In addition, the first examples make a lot of use of floats to hold everything together and you may need to wrap the whole lot in a static element if you need to place it somewhere (see example 4 above). Example 5 is the most stable version and the method I recommend you use but either method will work following the guidelines already outlined.

IE6 is also a little jumpy on fluid floated layouts at small screen sizes but that’s nothing new and something you’ll have to live with. Example 5 does not suffer from this though because the outer wrappers are not floated.

The advantage of this method is that the image is only 300bytes and you are not restricted by size like most other methods that use a massive image to draw the sides and borders. The above examples can have unlimited width and height and carry virtually no overhead in file size apart from the extra HTML of course.

I started out by saying this was simple but due to bugs and browser differences it wasn’t really that simple was it? Please refer to the examples for the full code as there are some fixes in place for the various demos. Have fun playing with the examples and if you find a better method of doing this, or want help with the above, or if you find some bugs then let’s hear from you.

14 Responses to “Simple Round Corners in CSS (revisited)”

1 Felipe

Though http://www.sitepoint.com/blogs/2007/09/18/png8-the-clear-winner/ has only found Fireworks to successfully create PNG-8 with both alpha (8-bit) and index (1-bit) transparency, there is also the open source software PNGnq cited in this post: http://eriestuff.blogspot.com/2007/11/cross-browser-png8-alpha-transparency.html

Though it doesn’t work in every situation: I had issues with some images in IE6. You still have to create Gif (and lose alpha transparency in FF/Opera/Safari) or use Fireworks in those cases.

2 John

Just looking at example 5, you could’ve saved yourself a few lines on .two, .three etc by only specifying a different bg-image and then not having to repeat the bg-positions or was that done for clarity and ease copying?

3 Paul OB

Hi John,

Yes that’s correct and there are opportunities in there for reducing code. I just copied and pasted each block for clarity so it was clear where each part was going.

Usually anything that reduces code weight is a good idea though :)

4 Blogging Squared

I have seen tutorial after tutorial on “rounding corners” – There’s even some web sites that dynamically create the png’s for you.

Overall your code looks solid – I would agree that anything that reduces code weight is a good thing :)

Nicely done!

5 Patrick Burt

How did you save out the PNG so its transparency didn’t show up as light blue in ie6?

6 Paul OB

Hi Patrick,

It’s done in Fireworks. You can read how to do it in Alex’s article on Sitepoint.

http://www.sitepoint.com/blogs/2007/09/18/png8-the-clear-winner/

There is also an open source link in post #1 above.

7 Paul Davis

This is very cool…

Unfortunately I need borders (nothing can ever be easy), didn’t like the hack version, so I’m working on the two image version. what I’d like to see is a sample for that, i’m not a CSS guru so I’m still debating where to put the second set of images to overwrite the remaining image pieces.

But this is so very cool…

Again, great work…

Thank You

-Paul-

8 Paul OB

Hi Paul,

Rather than complicating it with the one or two image method just use the usual 4 images (quarter image segments) for each corner and you won’t have to worry about any clever trickery.

All you have to do then is where the code originally specified a different background position for the same image you just supply a new image instead.

This will save you having to hide any parts of the image.

9 Paul Davis

Thanks Paul….

It’s always the simple ideas that are the hardest to figure out :)

That’s a perfect solution, we are using the other standard for everything else on the site so for now I’ll just do this for CSS pop-ups (we need to be able to tell customers when the site is going into maintenance and when there are power warnings and such). But now that the designers know we can do transparent corners their little minds are cooking up all kinds of new ways to make my life difficult :)

Thank You

-Paul-

10 Paul Davis

So I got it working on Firefox, IE6, safari mac but on IE7 the rounded corners do not show up. Not sure why just yet, I can view them in IE7 by putting them inthe URL.

I’ll see if I can find a place to stick this so you can see it online, it looks good other than that little issue.

here is the CSS in case something sticks out (the images are just 2 pixel corners).

Thanks

-Paul-

.boxfloat
{
padding:0px;
margin:0px;
margin-top:12px;
float:left;
}

.box
{
width:auto;
background:#fff;
padding:0 9px;
margin:0px auto;
position:relative;
border:2px solid #fff;/* stop margin collapse*/
border-left:2px solid #64a0c8;
border-right:2px solid #64a0c8;
z-index:2;
min-height:0;/* ie7 haslayout fix*/
}
.inner
{
background:#fff;
padding:10px 0;
margin:-10px 0;
min-height:0;/* ie7 haslayout issues fix*/
position:relative;
border-top:2px solid #64a0c8;
border-bottom:2px solid #64a0c8;
z-index:2
}

* html .inner, * html .box
{
height:1px
}/* ie6 haslayout issues fix*/

.top,.base
{
margin:-12px -11px 0;
background:url(/images/boxes/tipbox/topLeft.png) no-repeat left top;
height:12px;
position:relative;
font-size:12px;
clear:both;
z-index:-1;/* drag corner under background*/
}

.base
{
background:url(/images/boxes/tipbox/bottomLeft.png) no-repeat left top;
background-position:left bottom;
margin:0 -11px -12px;
}

.top span,.base span
{
background:url(/images/boxes/tipbox/topRight.png) no-repeat right top;
display:block;
height:12px;
font-size:12px;
}

.base span
{
background:url(/images/boxes/tipbox/bottomright.png) no-repeat bottom right;
}

.content
{
width:100%;
background:#fFf;
margin:-8px -1px -10px 2px;
}

* html .content
{
margin:-12px 0
}/* ie fails again*/

*+html .content
{
margin:-9px 0
}/* ie7*/

11 Paul OB

Hi Paul, any chance you can put it online as I always like to work with a real copy before I start looking at the code in detail.

It could be any number of things for IE7 but it looks like “haslayout” issues are already covered. I can’t see anything obvious so I’m sure there’s an easy fix.

12 Paul Davis

Hi Paul…

Yep, we are in the middle of a whole site re-design so it took a bit to get it moved over to the test servers (still setting stuff up).

But you can see it here, I left it in one of our template pages we use for the designers, it’s the second box in the center column (the only one with blue). It’s CSS is actually in the main html file, I had not moved it off just yet.

http://testipco.idahopower.com/boxtest.cfm

it’s odd because it only has that problem in IE7, we are thinking that we will have to do something different for IE6, like transparent Gifs or something…

Thanks

-Paul-

13 Paul OB

HI Paul,

IE7 doesn’t like the fact that .boxfloat is floated without a width. Either give it a width (e.g. 100%) or remove the float altogether as it doesn’t look like you need it in that type of situation.

For IE6 you can use png 8 as mentioned in this article which should give pretty good results.

Hope that helps :)

14 Paul Davis

Your my hero…

That fixed it, the boxfloat was there originally as a holder so I could manage the spacing between the elements. But I can do that right in the .box css as well….

I’m having them convert over the images to png 8 which should make us good to go.

Thank you for your help…

-Paul-

mulberry sale spyder womens jacket cheap new balance 574 mulberry outlet cheap new balance 574 arcteryx outlet mulberry sale spyder womens jacket mulberry sale spyder womens jacket mulberry outlet mulberry outlet new balance 574

Popular Articles

Top 10 Commentators


Subscribe to this feed! Subscribe by Email!

Random Bits Podcast

You need to download the Flash player from Adobe

Blogs Worth Reading