Quick Tip: Multiple Borders with Simple CSS
Tutorial Details
- Topic: CSS Borders
- Difficulty: Normal
- Estimated Completion Time: 4 Minutes
Did you know that we can achieve multiple borders with simple CSS, by using the :after amd :before psuedo-classes? This is something I recently learned myself! I’ll show you how to add more depth to your designs, without images, in just a few minutes.
Prefer to watch this video on Screenr?
Final Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Multi-Borders</title>
<style>
body { background: #d2d1d0; }
#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;
}
#box:after {
content: '';
position: absolute;
width: 196px;
height: 196px;
border: 1px solid #bbbbbb;
left: 1px; top: 1px;
}
</style>
</head>
<body>
<div id="box"></div>
</body>
</html>
In short, any browser that supports the :before and :after psuedo-elements (all major browsers) can take advantage of this effect. Of course, there are alternatives, including the use of box-shadow, as well as adding additional mark-up to the page; however, this is clean solution that you should definitely consider. Thanks for watching!

Thanks so much! I really enjoy these quick tips…
Jeffrey,
I just wanted to thank you for the jQuery series you did. I just finished it this morning and it helped me tremendously.
I Just wanted to let you know that your work is appreciated. I’m getting ready to tackle the PHP series now and watch the above quick tip as well.
thx again.
Where can I find the jQuery and PHP series? Thanks!
Thanks, Jon! That’s actually an old series. We need to update it for 1.4 — as there have been many changes.
Wow! an updated and continuing jQuery series would be amazing…
here you go drum, enjoy!:
http://blog.themeforest.net/screencasts/jquery-for-absolute-beginners-video-series/
http://blog.themeforest.net/screencasts/diving-into-php-video-series/
I never knew about the multiple borders either. I will be using them from now on for sure.
Thanks Jon! I really appreciate it man…
Hey guys — I actually discovered this technique from a blog a week ago or so…but I can’t remember where. If anyone knows, reply to this comment, and I’ll be sure to link to the blog I learned it from. :)
Here is the original article, by Nicolas Gallagher :
http://nicolasgallagher.com/multiple-backgrounds-and-borders-with-css2/
Nice to have a video Quick Tip about it ! Thanks !
Heh, I was just about to give a rant about you not giving credit to Nicolas for this tip – since it was obvious you learnt it from his blog last week ;) I’d love to see some attribution in the blog post itself. Keep the quick tips coming. It’s great to see such a high quality web development site out here for all the new people trying to learn.
According to quircksmode, :before and :after aren’t supported by IE, except IE8:
http://www.quirksmode.org/css/contents.html#t15
I discovered this from Freshface’s tooltips :)
Nice idea, I like it.
Although, the final result you their in the video could have been achieved with “border: 1px double #bbb”
Of course. But you could change it up however you wanted. This provides a bit more control over the colors, styling, spacing, etc.
That’s an awesome tip, thanks for sharing!
How do you get that live preview next to Coda?
Hey Erik,
It’s a plugin called “Lively”. You can download it here: http://menumachine.com/blog/2008/12/a-live-preview-window-for-coda/
Live Preview for Coda is a plugin.
http://celtic7.us/coda-live-preview
@Erik, that’s a Coda plugin called Lively, you can find it and more helpful lil’ plugins here
Thanks a lot, everybody!
Hi Jeff, I would like to see a PHP tutorial written by your own. By the way, your css quick tips works properly and it helps us a lot but we’re greedy to learn from your experiences!
Yours, Mohammed
This is interesting – i’m not sure I would use the example given but this is my first discovery of the content: property.
As always, thanks for your wisdom, i’m off to do more research!
Much quicker and cleaner than the way I was doing it before! Thanks
Nice effect! Thanks Jeffrey.
I will be using this in my current project to get that nice depth effect.
I’ve actually strayed away from using this ‘highlighting’ technique when designing as I didn’t want to add extra markup but once again, problem solved!
Thank-you muchly!
WOW! Thnx Jeffrey!
This quick tip helped alot, thnx for sharing :)
Seems this only works with a fixed height/width value? You could make some killer buttons with this technique and CSS3 background gradients…if it would allow for variable widths :P
Why wouldn’t it work with dynamic dimensions? I’m using it on a new design I’m working on and it works just fine.
Really? Mind sharing your code? It’s definitely not working for me. Once i take the height/width parameters out of the css it falls apart (in Safari anyway)
Nice tip Jeff, is there any solution for variable height/width?
If you haven’t declared width and height, try “width: auto; height: auto”.
if you set both top, right, bottom, and left to 1px, and delete the width and height declarations it works wonderful with variable height/width!
thanks jeff!!
Nice trick but it doesn’t work in internet explorer 7 and later. It works in ie 8.
Thanks for this tutorial.
Where did you get this TextMate like color scheme?
Thanks
Thomas
i have just tried this technique for a box that contains a hyperlink and now the link does seem to be clickable… any ideas?
It is because :after pseudo class adds another layer in front of the box class. To over come this problem you can change the z-index property on the pseudo classes so that they are positioned behind the original class.
Multi-Borders
body { background: #d2d1d0; }
#box {
background: #f4f4f4;
border: 1px solid #bbbbbb;
width: 196px;
height: 196px;
margin: 60px auto;
position: relative;
z-index:50;
}
#box:before {
border: 1px solid white;
content: ”;
width: 198px;
height: 198px;
position: absolute;
z-index:-2000;
left:-2px; top:-2px
}
#box:after {
content: ”;
position: absolute;
width: 200px;
height: 200px;
border: 1px solid #bbbbbb;
left: -3px; top: -3px;
z-index:-500;
}
Google.com
Thx guy, I was looking for that solution for a couple of days
This was great! thanks Jeffrey
Nice tutorial Jeffrey. I was just playing with the code and found that further adding outline to each of the pseudo class and the element property will allow usage of 6 different borders with just a single element.
The result looks very cool but unfortunately not all the browsers support this feature…
Interesting tip, Thanks for sharing
I think it is fine that it doesn’t work in IE <7, but just wanted you to be aware it completely breaks in FF 3.0 since they have `:before` and `:after` *partially* implemented. They have it implemented enough to show the boxes, but not enough to fully position them.
Apart from that, this is a great technique and has a *ton* of application in the mobile world where Webkit dominates!
Ahh – that’s interesting; though, I’d imagine that the upgrade percentage from Firefox 3.0 is super high.
Another possibility would be to use -moz-borders, but that’s of course Firefox-specific.
Great stuff.
I think it’s worth adding that it even works with css3 rounded corners! You have to add -moz/webkit-border-radius to both pseudo-classes and the actual class, but the result is worth it :)
Very nice tip, going to give it a try
You realize that your code creates an unusable situation if you have any content in the box, right? The :before and :after pseudo elements overlay the content blocking it from user interaction. Put a link in side your box and try to click it!
I noticed that if you use something like border-radius on your box, you have to apply it to the after/before aswell. (most might know this but I thought I’d point it out aswell :) )
Nice tip Jeffrey.
Aye whoops didn’t realise someone said it Two comments up my bad!
Thanks! This is a great article :)
WOW that was new! Thanks, I really enjoyed that and definitely gonna use it :)
Thank you first.But the last I coudn’t see.can you say it more clearly?
Nice and useful tips as for me! Thanks for sharing! Yo seem to be a really professional!
Nice tip! I’m looking forward to using this.
Great, thanks for this great technique.
I want only to tell that in general I hate video tutorials. Much better to follow a step-by-step instruction that you can also print down and follow off-line.
But expecially in coding, video tutorials are really a creepy tool. They let you to loose a lot of time.
Awesome tip, thx!
A great technique thank you for sharing! Keep up the good work.
Hi, my original article on multiple borders and backgrounds works with fluid-width containers because I used absolute positioning differently.
If you want to emulate multiple background images in IE8 (and other effects) you can find out more here:
http://nicolasgallagher.com/multiple-backgrounds-and-borders-with-css2/
I have been trying to get a double top border, and ended up using outline and then i had to try to hide the sides and bottom. This was a big help.
Thank you.
Thank you so much for this neat little quick tip Jeffrey.
- that solves the problem of simulating that nice subtle image border effect like img {padding:2px; border:1px solid #ccc; background:white;} -on boxes :)
Jeffrey, you know you could zoom in far more with the CTRL + Scroll technique, right? Just in case.
Neat trick, greatly explained!
Kev
This is totally awesome! Thank you for sharing and explaining it very well. I was looking for this the other day – win! Thanks again.
Nice Jeffry and what? when we have a resizable (height) box??
I think adding a display: block line would do. At least, it worked for me just a few hours ago.
This is such a nice post. typical nettuts quality! i am looking forward to the wordpress 3.0 feature tutorial :)
Great implementation, that would be a great way to set off photographs.
Wow, a lot of comments for what is essentially a simple post! It is a really useful and potentially wide ranging tip though, so thanks for coming up with it.
Also love the HTML tags post, quick reads like this are always handy. Although it takes twice as long to wade through the comments!
Thanks for this cool tut! Jeffrey and Nicolas rock! I like the idea how Nicolas created Pure CSS Social Media Icons using :before and :after pseudo classes.
A great post and a great technique – unlike Sauro I just love video tutorials!
Jeffrey – if you really want to impress me, how do you work the same effect on a fieldset border? I have tried
fieldset:before{}
but it doesn’t repeat the break for the legend.
Wonderful, thanks!
I just used it to create a border that changes color… just by setting the :before border-bottom to none and the :before height to half of the box’s (repositioning it by -1px top and left). Works like a charm!
#box {
width: 100px;
height: 100px;
border: 1px solid #000;
position: relative;
}
#box:before {
border: 1px solid red;
border-bottom: none;
content: ”;
width: 100px;
height: 50px;
top: -1px;
left: -1px;
position: absolute;
}
It helps a lot … thanks for sharing …
Great post, Jeffrey. I’m using this technique in a webkit specific app – works quite nicely, and plays well with content.
Just wanted to point out to IE folks,
If you really need a double border, it is important to solve the problem early. The best solution, imo, to keep your markup readable, is to use jQuery, and do something like this:
$(‘.someClass’).wrap(“”);
Then use CSS to style accordingly.
Check out this nifty little example.
http://jsfiddle.net/39uLf/
^^ That .wrap(“”) is supposed to have a div class=”anotherClass” in it. :)
Rather than deal with the width of the parent on the :before and :after you can set their position absolutely rather than the width. This allows for dynamic sized without having to rewrite this code over and over again.
#box:before{
border: 1px solid #ffcc99;
content: ”;
position: absolute;
top:0;
bottom:0;
left:0;
right:0;
}
#box:after{
border: 1px solid #ffcc99;
content: ”;
position: absolute;
top:1px;
bottom:1px;
left:1px;
right:1px;
}
Good point.
This is the method I use in the original article. But you also need to set some z-index values to avoid the pseudo-elements sitting on top of your content rendering it unselectable and links unclickable. Unfortunately, this nettuts article misses out the bits of CSS that are required to make this more flexible and practical.
Can’t dis be done with ‘border: 3px double #BBBBBB;’? Or did I missed something?