Rounded Corners CSS & JavaScript

Introduction

Welcome to Poised Solutions howto on rounded corners using CSS (Cascading Style Sheet) and JavaScript.

Rounded corners are an often wanted design feature of many websites. Curved corners tend to help soften a design. Unfortunately there is currently no quick CSS parameter to set to turn on curved borders. Instead we have to design them into the page.

This howto will show you the various methods of creating CSS styled curved corners with a high degree of flexibility, and minimum fuss. I will also reveal a technique to keep the HTML as clutter free as possible by using JavaScript to create rounded corners in-conjunction with CSS.

CSS Methods

All displayed elements in HTML are really boxes or rectangles. There is no curve unfortunately that is major cross browser compliant, so the curve effect is generated with imagery.

In the past tables were used to create the curved effect and they will still work today, but tables for design effects has the problem of cluttering the HTML and removing the semantic effect of the document, as well as creating portability problems on other browsing platforms.

The box model of HTML & CSS is shown below.

This is an example paragraph with the border set to a 3 pixel solid black.

/*--- CSS Box Model ---*/

p.box {
    width      : 77%;
    margin     : 8px auto 16px auto;
    border     : 3px solid #000000;
    padding    : 8px;
    text-align : center;
}

Background Image

One quick way to get rounded corners is just to use a background image on an element with a fixed width and height.

/*--- CSS Background Image Fixed Width and Height  ---*/

p.curved {
    width      : 168px;
    height     : 68px;
    margin     : 8px auto 16px;
    padding    : 16px;
    text-align : center;
    background : url(/img/rounded_corners/curvey.png)
        no-repeat top left;
}

Curved border, by using a background image.

This method is somewhat inflexible, the content could change, or the font-size maybe altered by the user. If you go for this approach be sure to put some leeway into the design to allow for area change.

You may also have to create a number of images, one for each rounded element you want to display if their areas change.

Curved Rows

Another approach is to realise that the element itself does not have to be curved but the curves can placed on the top and bottom, or the left and right. Top and bottom is more flexible, but you do sacrifice an automatic padding of the element in the vertical to this approach.

/*--- Curved Rows Top and Bottom ---*/

div.topcurve {
    width      : 200px;
    height     : 20px;
    margin     : 12px auto 0px;
    background : url(/img/rounded_corners/topcurve.png)
        no-repeat top left;
}

p.enclosed {
    width            : 184px;
    margin           : 0px auto;
    padding          : 0px 8px;
    text-align       : center;
    background-color : #c7c7f7;
}

div.bottomcurve {
    width      : 200px;
    height     : 20px;
    margin     : 0px auto 12px;
    background : url(/img/rounded_corners/bottomcurve.png)
        no-repeat top left;
}
<!-- Rounded Corners - Two Surrounding Divs -->
<div
class = "topcurve"></div>
<p
class = "enclosed">Curved Corners in two surrounding
divs.</p>
<div
class = "bottomcurve"></div>

Curved Corners in two surrounding divs.

This is quite a quick method to achieve the curve and it gives you flexibility if the vertical height of the element changes, but not if the horizontal changes.

We also still have the problem of a colour change, though a variant of the technique below could sort that out.

The images used in the construction of the curved corner design above are:


 

Note, this method perhaps gives the best antialias effect on the curves, which reduces the jagged effect, though in practice only a trained eye spots the lack of antialias.

Curved Corners in Rows

This technique is a bit more involved, but gives the highest degree of flexibility; short of using JavaScript to introduce the elements. This technique is the CSS technique used in the JavaScript below.

We first concentrate on the fact that the 4 curved corners are the elements we need. We could cut out the four corners of the image. But, if we instead cut out the arch outside the curve and save those images with the background of the page colour of the page we are using, we can then reuse the images over and over again.

/*--- Four Corners Page Colour ---*/

div.top {
    width            : 200px;
    height           : 19px;
    margin           : 0px auto;
    background-color : #c7c7f7;
}

div.bottom {
    width            : 200px;
    height           : 19px;
    margin           : 0px auto 12px;
    background-color : #c7c7f7;
}

div.topleft {
    float      : left;
    width      : 19px;
    height     : 19px;
    background : url(/img/rounded_corners/topleft.gif)
        no-repeat top left;
}

div.topright {
    float      : right;
    width      : 19px;
    height     : 19px;
    background : url(/img/rounded_corners/topright.gif)
        no-repeat top left;
}

div.bottomleft {
    float      : left;
    width      : 19px;
    height     : 19px;
    background : url(/img/rounded_corners/bottomleft.gif)
        no-repeat top left;
}

div.bottomright {
    float      : right;
    width      : 19px;
    height     : 19px;
    background : url(/img/rounded_corners/bottomright.gif)
        no-repeat top left;
}
<!-- Rounded Corners - Six Divs -->
<div
class = "top"><div
class = "topleft"></div><div
class = "topright"></div></div>
<p
class = "enclosed">Curved Corners using page
background colour and six surrounding divs.</p>
<div
class = "bottom"><div
class = "bottomleft"></div><div
class = "bottomright"></div></div>

Curved Corners using page background colour and six surrounding divs.

This method allows the highest degree of flexibility a change in both the horizontal and the vertical can be accommodated, though only the vertical is automatic. The horizontal changes have to be mirrored with the element's change in horizontal. Still, a lot faster than having to redo image each time.

The colour change problem is avoided by just using the page colour the rest of the image is transparent. PNG would solve the antialias effect, though support for PNG alpha channel is still spotty in some browsers, instead a transparent GIF has been used for each rounded corner.

If the page colour changes then the four images would need to be redone, but of course that is generally less work than artworking each change in element colour.

The images used on the construction of the four corner curved design are shown below:

   
 
   

The four corner method is perhaps the standard method of creating curved corners, and it can be used both in the vertical and horizontal. But, it suffers from non semantic, design markup in the HTML document. We actually introduce 6 new elements to achieve the curved effect.

By not being semantic, browser portability issues can be introduced, and it does make it harder for documents to be transformed between different styles of markup. With all that said, 90% of the time this technique will be ok.

A Sprinkling of Magic JavaScript Dust

So, here is my contribution to the rounded corner festival of web design. Instead of placing the curved corner markup in the HTML code, it is instead, introduced by JavaScript after the page is initially rendered.

There is a site development life cycle speed gain if a site is heavy with rounded corners, though on balance this approach probably takes a little longer on normal sites, than just inling into the HTML.

We gain all the advantages above, and negate the drawbacks of the CSS HTML only techniques, but we do introduce a slight shudder on page render. This technique also degrades well for terminal browsers.

function roundCorners() {
    // round corners

    var eles = [
        'jsrounded0',
        'jsrounded1']

    for (var c = 0; c < eles.length; ++c) {

        var ele = getEle(eles[c]);

        var width;
        var bgcolor;

        // get element width
        if (window.getComputedStyle)
            width =
                window.getComputedStyle(
                    ele, null).width;

        else if (ele.currentStyle) 
            width =
                ele.currentStyle.width;
        else
            continue

        // get element background colour
        if (window.getComputedStyle)
            bgcolor =
                window.getComputedStyle(
                    ele, null).backgroundColor;

        else if (ele.currentStyle) 
            bgcolor =
                ele.currentStyle.backgroundColor;

        else
            continue

        width  = parseInt(width) + 16;
        width += "px";

        ele.style.margin  = "0px auto";

        topRow(ele, bgcolor, width);

        bottomRow(ele, bgcolor, width);
    }
}
//----------------------------------------------------------

function topRow(ele, bgcolor, width) {
    // top row

    var div1 = crtEle('div');
    var div2 = crtEle('div');
    var div3 = crtEle('div');

    div1.className = "top";
    div2.className = "topleft";
    div3.className = "topright";

    div1.style.width = width;

    div1.style.backgroundColor = bgcolor;

    div1.appendChild(div2);
    div1.appendChild(div3);

    ele.parentNode.insertBefore(div1, ele);
}
//----------------------------------------------------------

function bottomRow(ele, bgcolor, width) {
    // bottom row

    var div1 = crtEle('div');
    var div2 = crtEle('div');
    var div3 = crtEle('div');

    div1.className = "bottom";
    div2.className = "bottomleft";
    div3.className = "bottomright";

    div1.style.width = width;

    div1.style.backgroundColor = bgcolor;

    div1.appendChild(div2);
    div1.appendChild(div3);

    if (ele.nextSibling)
        ele.parentNode.insertBefore(div1, ele.nextSibling);
    else
        ele.parentNode.appendChild(div1);
}
//----------------------------------------------------------

function getEle(id) {
    // get document element by id

    if (document.getElementById(id))
        return document.getElementById(id);
    return false;
}
//----------------------------------------------------------

function crtEle(tag) {
    // create a document element from a tag

    if (document.createElement(tag))
        return document.createElement(tag);
    return false;
}
//----------------------------------------------------------

Rounded corners created by JavaScript and CSS.

Rounded corners again created with JavaScript and CSS; different width and colour.

The elements to have the rounded corners are id'd, and the JavaScript eles array, in the function roundCorners is updated with the ids.

The CSS is the same as the four corner CSS. The width and background color of each element to be rounded is examined and the appropriate width and background color applied to the new elements. Padding is hard coded in this example but it is not infeasible to make a generic padding parser, it would just have made the code a little longer. There are perhaps other things to take into consideration, but the code can be modified to handle the anomalies.

The beauty of this technique is the HTML is allowed to flow without design markup.

Links

Concept Visor - CyberVisor

Bookmark and then activate Concept Visor to comment on this page, or any other page on the web. The Concept Visor will also allow you to view comments made on the page.

Concept Visor
 

For more details on the Concept Visor please visit http://www.cybervisor.org.uk

Books


If you have found this site useful please consider linking to it @ http://www.poisedsolutions.com/rounded_corners/

Social BookMarks
Google      Digg      Del.icio.us      Yahoo      Reddit      Facebook

Site Designed & Developed by Poised Solutions

If you wish to discuss hiring Poised Solutions for an information technology project please get in contact
or visit the main PoisedSolutions IT Consultancy Website.