Multiple Borders on Dynamically Sized Elements with CSS2

I recently saw a blog post on Nettuts on how to add multiple borders to elements with simple CSS.

This method has some flaws in that text may be rendered unselectable and links unclickable, I’m working on a fix but Nicolas Gallagher has a great alternative method in his article on Multiple Backgrounds and Borders with CSS2.1.

There was one significant problem with this method: you had to know the exact size of the element that you were going to add the effect to.

It is, however, possible to replicate the effect on dynamically sized elements using some just-as-simple CSS.

See it in action.

First, here’s the code Jeff presented:

#box {  
    background: #f4f4f4;  
    border: 1px solid #bbbbbb;  
    width: 200px;  
    height: 200px;  
    margin: 60px auto;  
    position: relative;  
}  

#box:before {  
    border: 1px solid white;  
    content: '';  
    width: 198px;  
    height: 198px;  
    position: absolute;  
}  

As you can see, the effect is produced by simply reducing the size of the :before content to fit inside its parent.

Here’s my approach:

div {
    width: 200px; 
    height: 200px; /* Added so the div has a size but not necessary */
    background: #F4F4F4;
    border: 2px solid #BBB;
    position: relative;
}

div:before {
    content: '';
    border: 1px solid #FFF;
    width: 100%;
    height: 100%;
    position: absolute;
    top: -1px;
    left: -1px;
}

We use 100% width and height so the :before content has the same width as its parent but by adding a 2px border to the parent, the size is increased by an extra pixel and therefore leaves room for us to place the second border inside using top and left positions of -1px.

This works because the W3C box model doesn’t count the border as part of the width and height of the element, only the content is taken in to account.

There is, however, one caveat: my method doesn’t support more than one extra border but hey, three’s a crowd.