Rounded corners using DOM Scripting and CSS
This is unintentionally similar to Adam Kalsey’s technique. I had the idea and did a proof-of-concept. Then I did a Google search for ‘rounded corners’ and found that he (and about 5011 other folks) had already published something quite similar.
I think my method is different enough to warrant a post. And if it isn’t, I’m sure someone will tell us :-).
As with Kalsey’s method, this will add rounded corners to the div of your choice. What’s more, the corners won’t be thrown off by text scaling.
Step one: the corners
Nothing complicated here. We’ll use one rounded-corner image:
. Our CSS will crop and place the background image as we want, so there is no need to use more than one.
Another thing: keep track of your color. We’ll use it as the background color of our containing element.
Step two: The JavaScript function
Next, we’ll create our JavaScript function. It will do three things:
- Find the specified element id.
- Create new child elements for that element.
- Assign class names to those child elements.
function corners(elementID){
if(!document.getElementById){return;}
var elID = document.getElementById(elementID);
if(!elID){return;}
var cornerClasses = ['topLeft','topRight','bottomLeft','bottomRight'];
var containers = new Array();
for(var k = 0; k < cornerClasses.length; k++){
containers[k] = document.createElement('k');
containers[k].className = cornerClasses[k];
elID.appendChild(containers[k]);
}
}
Line by line, here’s what we’re doing:
- Creating the function with one argument, the element id.
- Tells the script to die if
document.getElementByIdisn’t supported. - Sets the value of elID to
document.getElementById(elementID). - Tells the script to die if
elIDdoesn’t exist. - Creates an array literal containing the class names that we’ll assign in our
forloop. - Creates an empty array that we’ll use to store the child elements we create.
- Loops through the
cornerClassesarray to:- Create a new
ielement (which is valid HTML and XHTML). - Assign it a class name from the array.
- Append it to the document tree as a child element of
elID.
- Create a new
We could have used span, em, strong, div or b. I used i for three reasons:
- It’s shorter than
span. - It carries no semantic meaning.
- I’m personally less likely to use it than
b.
Step three: The HTML
The image and the JavaScript function don’t mean all that much without an HTML document. So create one, and add a div with an id of blah. We’ll also use dummy text in this example.
<div id="blah">
<p>Fee fi fo fum. Fee fi fo fum. Fee fi fo fum.</p>
</div>
Placing the script
I recommend keeping your scripts in an external JavaScript file. Your HTML code will be far cleaner.
We also want to ensure that any elements we’ll affect exist before the script executes. Put the call to this script at the bottom of your HTML file, just before your closing body tag. In most browsers, the script won’t work if you put it in the document head.
Step four: The CSS
Ah, here’s where the other part of the magic comes in. We’ve used JavaScript to manipulate the document object model, adding elements and class names. Now we’ll assign colors and positioning using style sheets. First up, set up a style for the blah div.
#blah{
background:#06c;
min-width:30px;
min-height:40px;
position: relative;
}
That last line, position:relative is most important. The short explanation: absolutely-positioned elements contained within a relatively-positioned element are positioned relative to their container rather than to the document window. That should make sense in a bit.
Now set the styles for all i that are children of blah.
#blah i{
position:absolute;
width:10px;
height:10px;
display:block;
background-image: url(http://tiffanybbrown.com/images/uploads/2006/11/corners.gif);
}
#blah i.topRight{
top:0;
right:0;
background-position: top right;
}
#blah i.topLeft{
top:0;
left:0;
background-position: top left;
}
#blah i.bottomRight{
bottom:0;
right:0;
background-position: bottom right;
}
#blah i.bottomLeft{
bottom:0;
left:0;
background-position: bottom left;
}
#blah p{margin:15px;}
Because we’re using an inline element, we need to make it behave like a block-level element (using display: block;). Otherwise the height and width properties won’t be applied (erm, except by some versions of Internet Explorer, if I’m not mistaken, including version 6).
We also need to make it an absolutely positioned element. Otherwise, top, left, right and bottom properties will be meaningless.
I’ve also set a margin of 15 pixels around the paragraph contained by blah to avoid any overlapping of text and i elements.
Step five: Making it run
So we’ve got an image, CSS, and a JavaScript function. But a JavaScript function won’t work unless it’s invoked. There are two ways you can invoke corners(). You can use the onload attribute. Or — and this is my preferred method — use an onLoader() function.
Using the onload attribute
To use the onload attribute, just add onload to your body tag.
<body onload="corners('blah');">
The downside to this method is that you’re commingling content and behavior. It’s minimal in this case. But if you have multiple functions to invoke, using onload can easily become cumbersome.
Using an onLoader function
I prefer using an onLoader function to group things together in the JavaScript file. Then once the document loads, the onLoader function is launched. You could name the function runEm(), or goDoIt(), or what-have-you. I just use onLoader because it’s descriptive.
function onLoader(){
corners('blah');
}
window.onload = onLoader();
The advantage to this second method is two-fold:
- You don’t wind up with 15 functions in your
bodytag. - You’re completely separating content and behavior.
Conclusion
All of the above should work just fine in Firefox, Safari, Opera 9 and Internet Explorer 7. It should mostly work in older versions of Internet Explorer. For IE6 or lower, use conditional comments to serve browser-specific styles. Hint: you should need to adjust the value of bottom for i.bottomLeft and i.bottomRight.
Of course, none of this works if JavaScript is disabled. Users will still see a functional design, but minus the rounded corners.
View a finished example. Warning: I didn’t bother separating the CSS, JavaScript and HTML, so the source is fugly.
















Nice post. I have used a similar technique in the past. I will give this a try too.