Round Corners With jQuery and CSS

Page content

Rounded Intro

So you’re all grown up and want Rounded Corners on your site. There’s just one small problem: the normal rounded corners implementation comes with tons of divs used for styles and you’ve got your fellow web developers screaming down your neck about web semantics.

So what’s this funky semantics thing? Basically, we’re looking for a separation of styles and data. We want to keep all the styles in the CSS style sheets and all the data in the XHTML files. Now, I’ve been known to be flexible on this a bit, however it is a great idea with a purpose and in this case, it actually helps us out a ton.

Ignore Me - Take The Easy Way Out

There are two jQuery plugins that can do this instantly, aptly named jQuery Corners and jQuery Corner. Yeah, I know totally different, right? They vary slightly in terms of their capabilities (anti-aliasing, background images, etc.). So if you’re not up to the heavy lifting or your requirements are very light (just basic rounding) these plugins more than fit the bill.

Classic Rounded Corners

Now, if you’re looking for something that regular borders and the plugins above can’t manage, take a look classic implementation of rounded corners. We’re using images to make things look exactly like we want them to.

Essentially, we’re wrapping (if you think visually, it’s more layering actually) tons of divs in order to apply different background images. All these divs are needed because you can only apply one background image to an HTML element.

So a basic run down is that we need four (4) divs for the corners (top left, top right, bottom left, bottom right) and four (4) more for the sides (top, bottom, left, right). This allows us to add the four images in appropriate positions. Please note that all these divs gives us the option of having rounded divs that can be freely resized.

As mentioned about, the problem is that these are eight (8) huge divs, which are not very semantic; not to mention they add useless code to the HTML download.

Some things to note:

  • Side Divs First - Top, Bottom, Right, and Left divs must be on the outside of the corners. If not the effect may not come out right. I think it has something to do with transparency, but somethings are easier to fix than to diagnose.
  • Check Transparancy - Keep in mind that if your images are PNG you might need to apply some of the horrendous IE 6 hacks.
  • Padding and Margins - I don’t think the original article mentioned, however since we are layering divs, they shouldnt' have any margins. Divs don’t usually do, but depending on your current styles, you might need to reset.
  • Perfect Slices - Doesn’t really need much explanation, but your images need to be sliced perfectly so that everything lines up right.

Dynamic Divs

Now, this is where the beauty of jQuery comes in. This is a modification of this tutorial. We’re going to use javascript to inject these divs where we need them.

This is the markup we are aiming for:

<div class="rounded">
	<div class="t">
		<div class="r">
			<div class="b">
			 	<div class="l">
					<div class="tl">
						<div class="tr">
							<div class="br">
								<div class="bl inner">
									Stuff in here
									should appear
									perfectly rounded
								</div>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>
</div>

I know, messy right? Although the original article mentions wrapping these around your main div, but it works perfectly fine by putting them inside. Also, it enables us to do some fun stuff later on. Since all these guys have no padding, the inner class is needed to apply needed padding for contents. You could just apply these styles to bl however, I don’t want to have to remember which one of these is the inner one.

Here’s out basic CSS

.t  {background: url(t.png) 0 0 repeat-x;}
.b  {background: url(b.png) 0 100% repeat-x}
.l  {background: url(l.png) 0 0 repeat-y;}
.r  {background: url(r.png) 100% 0 repeat-y;}
.bl {background: url(bl.png) 0 100% no-repeat;}
.br {background: url(br.png) 100% 100% no-repeat;}
.tl {background: url(tl.png) 0 0 no-repeat;}
.tr {background: url(tr.png) 100% 0 no-repeat;}

Notice we’re repeating the images used for the sides, so slice accordingly.

With jQuery, this is the only HTML that you need:

<div class="rounded">
	Stuff in here
	should appear
	perfectly rounded
</div>

Now, isn’t that much nicer?

Now, here’s the magical jQuery code:

$(document).ready(function() {
	$(".rounded").wrapInner('<div class="t"><div class="r"><div class="b"><div class="l"><div class="tl"><div class="tr"><div class="br"><div class="bl inner"></div></div></div></div></div></div></div></div>');
});

Now, I might have made a typo, so you may need to check. The wrapInner( ) function does exactly what it says (sort of): it wraps your content with those nested divs, but on the inside.

Um, yeah, that’s about it. Cool huh?

Yes, It’s Extensible

Now you can use this and apply it to tons of different rounded corners on your site. Simply add the rounded class to the div in question. eg:

<div class="widget rounded">
	New stuff here
</div>

Then you modify your CSS to apply the new images:

.widget .t  {background: url(widget-t.png);}
.widget .b  {background: url(widget-b.png);}
.widget .l  {background: url(widget-l.png);}
.widget .r  {background: url(widget-r.png);}
.widget .bl {background: url(widget-bl.png);}
.widget .br {background: url(widget-br.png);}
.widget .tl {background: url(widget-tl.png);}
.widget .tr {background: url(widget-tr.png);}

Now you see why we’re wrapping inside the div, instead of outside. That way, we can target different images for different divs on the site, without changing any javascript calls. Cool huh?

Now technically, we don’t need the images on the original divs, however I haven’t found a clean (shorthand) way of applying background positions and repeats without an image URL.

Hope you enjoyed and hope it works.