Designers love images with rounded corners. I don’t blame them – it’s a great way to make the angular WWW a bit more cuddly. But for a Web Developer rounded corners poses a problem. Back in the old days, when the content of a web page was put there manually by a Web Designer, images where exported directly from Photoshop – rounded corners and all.


Today this is not an option since almost all web pages are based on some form of CMS or blog tool. Images are uploaded directly to the page via the CMS by users that have little or no experience from imaging. Most of them don’t even have Photoshop installed on their computer. This means that the creation of rounded corners has to be automated using code.

There are lots of different solutions out there. Some are based on intricate positioning of small GIF or PNG corner overlays, some use javascript to dynamically render a plethora of pixel-sized divs that does the job okay, but bloats your markup and opens up for browser compatibility issues. So what’s a girl to do?

Lo and behold: in CSS3 there is the border-radius option. Finally a solution that follows web standards and solves our pesky rounded corner problem. Or does it? Well *hrrrm* almost. CSS3 is a standard in the making. It’s not ready yet so not all browsers support the border-radius option. This means that users with browsers that don’t support this option (mainly Internet Explorer) will have to live without rounded corners. If you’re not happy with that, go for one of the options listed above.

If you’re an experienced Web Developer, by now you’re probably thinking: CSS3 rounded corners on plain div’s is one thing. Making it work on images is something completely different. Let’s look at some examples with code. In order for this example to work, you will need a browser that has support for the border-radius option: Mozilla Firefox, Google Chrome or Apple Safari. Don’t bother looking at the following examples with Internet Explorer – you won’t see any rounded corners.

Let’s start with a plain div with no image – just a background color:

div.roundedCornersDiv
{
	width: 228px;
	height: 178px;
	padding: 0;
	background-color: #f93002;
	-moz-border-radius: 7px;
	-webkit-border-radius: 7px;
	border-radius: 7px;
}

<div class="roundedCornersDiv">
</div>

Although this red square is very nice, this article is not about rounded corners on plain div’s. It’s about rounded corners on images. So let’s see what happens if we put an image inside this div. Since the image is placed inside the div, logic dictates that the surrounding div should clip the image giving it nice round corners. Right?

<div class="roundedCorners">
<img src="corner.jpg" width="228" height="178" alt="Corner" />
</div>

Corner

Nope. Doesn’t work. The square image covers the rounded corner div. Okay – what happens if we remove the image tag and use the image as a background image on the div instead?

div.roundedCornersDivBgImage
{
width: 228px;
height: 178px;
background-image: url(corner.jpg);
background-repeat: no-repeat;
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
border-radius: 7px;
}

<div class="roundedCornersDivBgImage">
</div>

Nice! Still there is a problem: If your web site is generated by a CMS or a blog tool, the images are added to the page using image tags, not as background image URL’s in the CSS. Bummer…

But what if the images are placed in the code using regular image tags and then we use some jQuery to transform them into div’s with background images? A bit of a hack, but as long as the hack is based on standard XHTML/CSS I’m fine with it. First we need a basic CSS class for the images we want to transform. This example contains just the bare-bones stuff. You don’t want any padding since it will mess up the positioning of the image. And then the three different radius options.

.roundedCorners
{
padding: 0;
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
border-radius: 7px;
}

We also need a JavaScript helper function to check if the browser has support for border radius. After all, if the browser doesn’t support border radius, there’s no point in transforming the image into a div with a background image. To my knowledge there is no such helper function built into jQuery, so we’ll make our own. It looks like this:

function hasBorderRadius() {
var d = document.createElement("div").style;
if (typeof d.borderRadius !== "undefined") return true;
if (typeof d.WebkitBorderRadius !== "undefined") return true;
if (typeof d.MozBorderRadius !== "undefined") return true;
return false;
};

The above function checks if the browser has support for: border-radius, -webkit-border-radius or -moz-border-radius (in that order) and returns either true (browser has support for border radius) or false (browser doesn’t support border radius). The next step is to write some jQuery that takes care of transforming the image into a div with an image background. Here’s the code I came up with:

if (hasBorderRadius()) { // 1
$("img.roundedCorners").each(function() { // 2
$(this).wrap('<div class="roundedCorners" />'); // 3
var imgSrc = $(this).attr("src"); // 4
var imgHeight = $(this).height(); // 4
var imgWidth = $(this).width(); // 4
$(this).parent()
.css("background-image", "url(" + imgSrc + ")")
.css("background-repeat","no-repeat")
.css("height", imgHeight + "px")
.css("width", imgWidth + "px"); // 5
$(this).remove(); // 6
});
}

  1. First there’s a call to the helper function to check if the browser has support for border radius. If hasBorderRadius returns true…
  2. …we use jQuery to select all images with the class roundedCorners. For each image with this class we run our transformation code.
  3. We wrap a new div around the image tag and give it the same class as the original image.
  4. Then we get the src attribute and the image width and height.
  5. Then we set the background image of the new container div to the image src. We also set the width and height of the container div to the same width and height as the image. This prevents the container div from collapsing when we remove the original image in the following step.
  6. The last thing I do is remove the original image tag inside the div.

Here is the result:

What happens if the original image is surrounded by a link? Like this:

<a href="http://www.swedishfika.com" title="Swedish Fika">
<img src="corner.jpg" alt="Corner" class="roundedCorners" />
</a>

As you can see it works!

Then of course there are lot’s variations on the same theme. Sometimes you have a combination of several (X)HTML elements that need’s to get rounded corners. An example:

This is a headline

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam blandit odio at mi adipiscing pellentesque. Donec sit amet mi orci, nec aliquet leo. Donec convallis sollicitudin odio in pharetra. Phasellus ut est enim, sit amet consequat enim.

Here’s the code (XHTML, CSS and jQuery):

<div class="severalElements">
<img src="corner.jpg" width="228" height="178" alt="Corner" />
<h3>This is a headline</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam blandit odio at mi adipiscing pellentesque.
Donec sit amet mi orci, nec aliquet leo.
Donec convallis sollicitudin odio in pharetra.
Phasellus ut est enim, sit amet consequat enim.</p>
</div>
div.severalElements
{
width: 228px;
height: auto;
border: solid 1px #000;
padding: 0;
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
border-radius: 7px;
}
if (hasBorderRadius()) {
$("div.severalElements").each(function(){
var img = $(this).children("img");
var imgSrc = img.attr("src");
var imgHeight = img.height();
var imgWidth = img.width();
$(this).css("background-image", "url(" + imgSrc + ")")
.css("background-repeat","no-repeat")
.css("padding-top", imgHeight + "px");
img.remove();
});
}

When I get the time, I plan on turning this example into an easy-to-work-with jQuery plugin. Stay tuned!

// Thomas